Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions app/vmui/packages/vmui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<html lang="en">
<head>
<meta charset="utf-8"/>
<link rel="icon" href="/favicon.svg" />
<link rel="apple-touch-icon" href="/favicon.svg" />
<link rel="mask-icon" href="/favicon.svg" color="#000000">
<link id="favicon" rel="icon" href="/src/assets/favicon.svg" />
<link id="favicon-apple" rel="apple-touch-icon" href="/src/assets/favicon.svg" />
<link id="mask-icon" rel="mask-icon" href="/src/assets/favicon.svg" color="#000000">

<meta name="robots" content="noindex">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { FC, useMemo } from "preact/compat";
import "./style.scss";
import { createFaviconUrl } from "../../../../utils/favicon";
import { faviconColors } from "../../../../constants/faviconsColors";
import classNames from "classnames";
import { useBrowserTabSync } from "./hooks/useBrowserTabSync";
import { CloseIcon } from "../../../Main/Icons";

const BrowserTabController: FC = () => {
const { faviconColor, changeFaviconColor } = useBrowserTabSync();

const faviconUrl = useMemo(() => {
return createFaviconUrl(faviconColor);
}, [faviconColor]);

const createHandlerClick = (color?: string) => () => {
changeFaviconColor(color);
Comment thread
Loori-R marked this conversation as resolved.
};

return (
<div className="vm-browser-tab-controller">
<p className="vm-server-configurator__title">Favicon color</p>

<div className="vm-browser-tab-controller-palette">
<div className="vm-browser-tab-controller-palette-list">
<button
className="vm-browser-tab-controller-palette-list__item vm-browser-tab-controller-palette-list__item_reset"
type="button"
onClick={createHandlerClick()}
aria-label="Reset favicon color"
>
<CloseIcon />
</button>

{faviconColors.map(color => (
<button
className={classNames({
"vm-browser-tab-controller-palette-list__item": true,
"vm-browser-tab-controller-palette-list__item_selected": faviconColor === color
})}
key={color}
type="button"
style={{ color }}
onClick={createHandlerClick(color)}
aria-label={`Set favicon color to ${color}`}
aria-pressed={faviconColor === color}
/>
))}
</div>

<img
className="vm-browser-tab-controller-palette__preview"
src={faviconUrl}
alt="Favicon preview"
/>
</div>
</div>
);
};

export default BrowserTabController;
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import useEventListener from "../../../../../hooks/useEventListener";
import { useEffect, useState } from "preact/compat";
import { getFromStorage, saveToStorage } from "../../../../../utils/storage";
import { getFaviconStorageKey, updateFaviconColor } from "../../../../../utils/favicon";

const FAVICON_STORAGE_KEY = "FAVICON_COLOR";

const storageKey = getFaviconStorageKey();

const getColorsFromStorage = () => {
return getFromStorage(FAVICON_STORAGE_KEY) as Record<string, string> | null;
};

export const useBrowserTabSync = () => {
const [faviconColor, setFaviconColor] = useState(() => getColorsFromStorage()?.[storageKey]);

const handleUpdateColor = () => {
const colorsFromStorage = getColorsFromStorage();
const color = colorsFromStorage?.[storageKey];
setFaviconColor(color);
};

const changeFaviconColor = (color?: string) => {
const { [storageKey]: _, ...colorsFromStorage } = getColorsFromStorage() || {};
const nextColors = { ...colorsFromStorage };

if (color) {
nextColors[storageKey] = color;
}

saveToStorage(FAVICON_STORAGE_KEY, nextColors);
Comment thread
Loori-R marked this conversation as resolved.
};

useEffect(() => {
handleUpdateColor();
}, []);

useEffect(() => {
updateFaviconColor(faviconColor);
}, [faviconColor]);

useEventListener("storage", handleUpdateColor);

return {
faviconColor,
changeFaviconColor,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
@use "src/styles/variables" as *;

$color-item-size: 28px;
$outline-width: 2px;
$outline-offset: 2px;
$outline-space: $outline-width + $outline-offset;

.vm-browser-tab-controller {
.vm-server-configurator__title {
padding-bottom: 2px;
}

&-palette {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: calc($padding-large * 2);

&-list {
display: flex;
align-items: center;
justify-content: flex-start;
flex-wrap: wrap;
gap: $padding-small;

&__item {
width: $color-item-size;
height: $color-item-size;
aspect-ratio: 1;
border-radius: 50%;
background-color: currentColor;
cursor: pointer;
transition-property: transform;
transition-duration: 0.15s;
transition-timing-function: linear;

&:hover {
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
transform: scale(1.1);
}

&:focus-visible {
transform: scale(1.1);
}

&_reset {
display: flex;
align-items: center;
justify-content: center;
background: transparent;
border: $border-divider;
color: $color-text-disabled;
padding: calc($padding-small / 2);
}

&_selected {
width: $color-item-size - 2 * $outline-space;
height: $color-item-size - 2 * $outline-space;
margin: $outline-space;
outline: $outline-width solid currentColor;
outline-offset: $outline-offset;
pointer-events: none;
}
}

&__input {
position: absolute;
z-index: -1;
opacity: 0;
}
}

&__preview {
width: $color-item-size;
height: auto;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { forwardRef, useImperativeHandle, useRef } from "preact/compat";
import { forwardRef, useImperativeHandle } from "preact/compat";
import { ArrowDownIcon, SettingsIcon } from "../../Main/Icons";
import Button from "../../Main/Button/Button";
import Modal from "../../Main/Modal/Modal";
Expand All @@ -11,6 +11,7 @@ import ThemeControl from "../ThemeControl/ThemeControl";
import useDeviceDetect from "../../../hooks/useDeviceDetect";
import useBoolean from "../../../hooks/useBoolean";
import QueryTimeOverride from "./QueryTimeOverride/QueryTimeOverride";
import BrowserTabController from "./BrowserTabController/BrowserTabController";

const title = "Settings";

Expand All @@ -27,27 +28,16 @@ const GlobalSettings = forwardRef<GlobalSettingsHandle>((_, ref) => {

const appModeEnable = getAppModeEnable();

const serverSettingRef = useRef<ChildComponentHandle>(null);
const limitsSettingRef = useRef<ChildComponentHandle>(null);
const timezoneSettingRef = useRef<ChildComponentHandle>(null);

const {
value: open,
setTrue: handleOpen,
setFalse: handleClose,
} = useBoolean(false);

const handleApply = () => {
serverSettingRef.current && serverSettingRef.current.handleApply();
limitsSettingRef.current && limitsSettingRef.current.handleApply();
timezoneSettingRef.current && timezoneSettingRef.current.handleApply();
handleClose();
};

const controls = [
{
show: true,
component: <TimezonesPicker ref={timezoneSettingRef}/>
component: <TimezonesPicker/>
},
{
show: true,
Expand All @@ -56,7 +46,11 @@ const GlobalSettings = forwardRef<GlobalSettingsHandle>((_, ref) => {
{
show: !appModeEnable,
component: <ThemeControl/>
}
},
{
show: true,
component: <BrowserTabController/>
Comment thread
Loori-R marked this conversation as resolved.
},
].filter(control => control.show);

useImperativeHandle(ref, () => ({
Expand Down Expand Up @@ -108,22 +102,6 @@ const GlobalSettings = forwardRef<GlobalSettingsHandle>((_, ref) => {
{control.component}
</div>
))}
<div className="vm-server-configurator-footer">
<Button
color="error"
variant="outlined"
onClick={handleClose}
>
Cancel
</Button>
<Button
color="primary"
variant="contained"
onClick={handleApply}
>
Apply
</Button>
</div>
</div>
</Modal>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { FC } from "preact/compat";
import Switch from "../../../Main/Switch/Switch";
import { getFromStorage, saveToStorage } from "../../../../utils/storage";
import { useLocalStorageBoolean } from "../../../../hooks/useLocalStorageBoolean";
import "./style.scss";

const key = "LOGS_OVERRIDE_TIME";
const defaultValue = true;
Expand All @@ -21,17 +22,25 @@ const QueryTimeOverride: FC = () => {
};

return (
<div>
<div className="vm-server-configurator__title">
Query time override
</div>
<div className="vm-time-override-controller">
<Switch
label="Override time picker with query _time filter"
fullWidth
color="neutral"
value={overrideTime}
onChange={handleUpdateValue}
label={<OverrideTimeLabel/>}
/>
<div className="vm-time-override-controller__description">
If the query contains a time filter, it overrides the selected time range.
</div>
</div>
);
};

export default QueryTimeOverride;

const OverrideTimeLabel: FC = () => (
<p className="vm-server-configurator__title">
Override time picker with query time filter
</p>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@use "src/styles/variables" as *;

.vm-time-override-controller {
background-color: $color-hover-black;
border-radius: $border-radius-medium;
padding: $padding-large;
border: $border-divider;

.vm-server-configurator__title {
margin: 0;
}

&__description {
padding-top: $padding-global;
font-size: $font-size-small;
line-height: 1.3;
text-wrap: pretty;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FC, forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from "preact/compat";
import { FC, useEffect, useMemo, useRef, useState } from "preact/compat";
import { getUTCByTimezone } from "../../../../utils/time";
import { ArrowDropDownIcon } from "../../../Main/Icons";
import classNames from "classnames";
Expand All @@ -10,7 +10,7 @@ import TimezonesList from "./TimezonesList";
import Popper from "../../../Main/Popper/Popper";
import useDeviceDetect from "../../../../hooks/useDeviceDetect";

const TimezonesPicker: FC = forwardRef((_props, ref) => {
const TimezonesPicker: FC = () => {
const { isMobile } = useDeviceDetect();
const { timezone: stateTimezone } = useTimeState();
const timeDispatch = useTimeDispatch();
Expand All @@ -30,20 +30,14 @@ const TimezonesPicker: FC = forwardRef((_props, ref) => {
}), [timezone]);

const handleSetTimezone = (tz: Timezone) => {
setTimezone(tz.region);
timeDispatch({ type: "SET_TIMEZONE", payload: tz.region });
handleCloseList();
};

useEffect(() => {
setTimezone(stateTimezone);
}, [stateTimezone]);

useImperativeHandle(ref, () => ({
handleApply: () => {
timeDispatch({ type: "SET_TIMEZONE", payload: timezone });
}
}), [timezone]);

return (
<div className="vm-timezones">
<div className="vm-server-configurator__title">
Expand Down Expand Up @@ -77,6 +71,6 @@ const TimezonesPicker: FC = forwardRef((_props, ref) => {
</Popper>
</div>
);
});
};

export default TimezonesPicker;
Loading