v2.6.1 – Bug fixes (#743)

* Bump ejs from 3.1.6 to 3.1.8

Bumps [ejs](https://github.com/mde/ejs) from 3.1.6 to 3.1.8.
- [Release notes](https://github.com/mde/ejs/releases)
- [Changelog](https://github.com/mde/ejs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mde/ejs/compare/v3.1.6...v3.1.8)

---
updated-dependencies:
- dependency-name: ejs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump minimist from 1.2.5 to 1.2.6

Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

---
updated-dependencies:
- dependency-name: minimist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump tmpl from 1.0.4 to 1.0.5

Bumps [tmpl](https://github.com/daaku/nodejs-tmpl) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/daaku/nodejs-tmpl/releases)
- [Commits](https://github.com/daaku/nodejs-tmpl/commits/v1.0.5)

---
updated-dependencies:
- dependency-name: tmpl
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump protobufjs from 6.11.2 to 6.11.3

Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 6.11.2 to 6.11.3.
- [Release notes](https://github.com/protobufjs/protobuf.js/releases)
- [Changelog](https://github.com/protobufjs/protobuf.js/blob/v6.11.3/CHANGELOG.md)
- [Commits](https://github.com/protobufjs/protobuf.js/compare/v6.11.2...v6.11.3)

---
updated-dependencies:
- dependency-name: protobufjs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix(rich-text-editor): fix dark mode ui appearance (#696)

* fix(rich-text-editor): fix dark mode ui appearance

* Update src/components/RichTextEditor.tsx

Co-authored-by: Sidney Alcantara <sidney@sidney.me>

* Update src/components/RichTextEditor.tsx

Co-authored-by: Sidney Alcantara <sidney@sidney.me>

* Update src/components/RichTextEditor.tsx

Co-authored-by: Sidney Alcantara <sidney@sidney.me>

* Update src/components/RichTextEditor.tsx

Co-authored-by: Sidney Alcantara <sidney@sidney.me>

* Update src/components/RichTextEditor.tsx

Co-authored-by: Sidney Alcantara <sidney@sidney.me>

* Update src/components/RichTextEditor.tsx

Co-authored-by: Sidney Alcantara <sidney@sidney.me>

* Update src/components/RichTextEditor.tsx

Co-authored-by: Sidney Alcantara <sidney@sidney.me>

* Update src/theme/RichTextEditorDarkCSS.tsx

Co-authored-by: Sidney Alcantara <sidney@sidney.me>

* Update src/theme/RichTextEditorLightCSS.tsx

Co-authored-by: Sidney Alcantara <sidney@sidney.me>

* fix(rich-text-editor): add stylings to dropdown

* fix(rich-text-editor): add toolbar stylings

* fix(rich-text-editor): reset hover&focus bg

Co-authored-by: Sidney Alcantara <sidney@sidney.me>

* update date & time filter operators for clarity

* Action field: prevent selecting self as required field (fixes ROWY-551)

* Date & Time: only show date for date filters

* move fullScreenButton to be shared, remove md settings

* bundle-analyzer

* Leaf icon: use mdi-material-ui

* Feat: Percentage field color customization (#692)

* feat(percentage-c11n): convert to table cell

* feat(percentage-c11n): add logic to default configs

* feat(percentage-c11n): add color picker to settings

* feat(percentage-c11n): change default colors

* feat(percentage-c11n): fix button text color

* feat(percentage-c11n): add labels to settings

* feat(percentage-c11n): add preview section

* feat(percentage-c11n): fix cache issues with debouncing

* feat(percentage-c11n): add width responsiveness to color picker

* feat(percentage-c11n): fix responsiveness issues

* feat(percentage-c11n): add checkbox, refactor a little

* feat(percentage-c11n): convert data type to array

* feat(percentage-c11n): refactor config states

* feat(percentage-c11n): fix defaults

* feat(percentage-c11n): add basic cell without bg

* feat(percentage-c11n): remove collapse

* feat(percentage-c11n): refactor checkStates

* feat(percentage-c11n): add grid layout

* feat(percentage-c11n): chore conventions

* feat(percentage-c11n): add default theme color to sidedrawer

* remove redundant fragment

Co-authored-by: Sidney Alcantara <sidney@sidney.me>

* fix text color in preview

Co-authored-by: Sidney Alcantara <sidney@sidney.me>

* fix: change state to derived state

Co-authored-by: Sidney Alcantara <sidney@sidney.me>

* fix: review suggestions

* fix: remove redundant change call

Co-authored-by: Sidney Alcantara <sidney@sidney.me>

* fix(percentage-c11n): remove redundant dependencies

Co-authored-by: Shams <shams.mosowi@gmail.com>
Co-authored-by: Sidney Alcantara <sidney@sidney.me>

* extend callable timeout to over 9minutes

* fix timeout value

* fix page loading with white screen while system is in dark mode

* Revert "bundle-analyzer"

This reverts commit dd214b96e4.

* fix nav items not accessible with Tab

* Percentage: don’t display if value null or undefined

* fix NavDrawer causing compile to fail

* show text field if collections array is empy

* column ids

* row ID

* fix create table showing empty dropdown for collections

* fix row not writing to db once all required fields are written

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Han Tuerker <46192266+htuerker@users.noreply.github.com>
Co-authored-by: shamsmosowi <shams.mosowi@gmail.com>
This commit is contained in:
Sidney Alcantara
2022-08-10 12:18:09 +02:00
committed by GitHub
parent e4e19f3a92
commit a35afa9619
35 changed files with 682 additions and 252 deletions

View File

@@ -75,6 +75,12 @@
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap"
/>
<style>
:root {
color-scheme: light dark;
}
</style>
<title>Rowy</title>
<meta name="title" content="Rowy GCP as easy as ABC" />

View File

@@ -1,10 +0,0 @@
import SvgIcon, { SvgIconProps } from "@mui/material/SvgIcon";
import { mdiLeaf } from "@mdi/js";
export default function Leaf(props: SvgIconProps) {
return (
<SvgIcon {...props}>
<path d={mdiLeaf} />
</SvgIcon>
);
}

View File

@@ -88,6 +88,12 @@ export { LanguageMarkdownOutline as Markdown };
import { TableRow } from "mdi-material-ui";
export { TableRow as Row };
import { Table } from "mdi-material-ui";
export { Table };
import { Leaf } from "mdi-material-ui";
export { Leaf };
export * from "./AddRow";
export * from "./AddRowTop";
export * from "./ChevronDown";

View File

@@ -346,16 +346,6 @@ export const updateFieldAtom = atom(
update[tableSettings.auditFieldUpdatedBy || "_updatedBy"] = auditValue;
}
// Check for required fields
const requiredFields = ignoreRequiredFields
? []
: tableColumnsOrdered
.filter((column) => column.config?.required)
.map((column) => column.key);
const missingRequiredFields = ignoreRequiredFields
? []
: requiredFields.filter((field) => row[field] === undefined);
// Apply field update
if (!deleteField) {
// Check for equality. If updated value is same as current, skip update
@@ -367,6 +357,17 @@ export const updateFieldAtom = atom(
_set(update, fieldName, value);
}
// Check for required fields
const newRowValues = updateRowData(cloneDeep(row), update);
const requiredFields = ignoreRequiredFields
? []
: tableColumnsOrdered
.filter((column) => column.config?.required)
.map((column) => column.key);
const missingRequiredFields = ignoreRequiredFields
? []
: requiredFields.filter((field) => newRowValues[field] === undefined);
// If its a local row, update the row in rowsLocal
if (isLocalRow) {
set(tableRowsLocalAtom, {
@@ -379,12 +380,11 @@ export const updateFieldAtom = atom(
// If it has no missingRequiredFields, also write to db
// And write entire row to handle the case where it doesnt exist in db yet
if (missingRequiredFields.length === 0) {
const rowValues = updateRowData(cloneDeep(row), update);
if (deleteField) unset(rowValues, fieldName);
if (deleteField) unset(newRowValues, fieldName);
await updateRowDb(
row._rowy_ref.path,
omitRowyFields(rowValues),
omitRowyFields(newRowValues),
deleteField ? [fieldName] : []
);
}

View File

@@ -10,7 +10,7 @@ import { ResizeBottomRight } from "@src/assets/icons";
import useMonacoCustomizations, {
IUseMonacoCustomizationsProps,
} from "./useMonacoCustomizations";
import FullScreenButton from "./FullScreenButton";
import FullScreenButton from "@src/components/FullScreenButton";
import { spreadSx } from "@src/utils/ui";
export interface ICodeEditorProps
@@ -73,6 +73,7 @@ export default function CodeEditor({
return (
<TrapFocus open={fullScreen}>
<Box
component="div"
sx={[boxSx, ...spreadSx(containerProps?.sx)]}
style={fullScreen ? { height: "100%" } : {}}
>

View File

@@ -13,7 +13,7 @@ import { ResizeBottomRight } from "@src/assets/icons";
import useMonacoCustomizations, {
IUseMonacoCustomizationsProps,
} from "./useMonacoCustomizations";
import FullScreenButton from "./FullScreenButton";
import FullScreenButton from "@src/components/FullScreenButton";
import { spreadSx } from "@src/utils/ui";
export interface IDiffEditorProps
@@ -64,6 +64,7 @@ export default function DiffEditor({
return (
<TrapFocus open={fullScreen}>
<Box
component="div"
sx={[boxSx, ...spreadSx(containerProps?.sx)]}
style={fullScreen ? { height: "100%" } : {}}
>

View File

@@ -0,0 +1,76 @@
import { useState, useRef, MutableRefObject, useLayoutEffect } from "react";
import { Box, useTheme } from "@mui/material";
import { Color, ColorPicker } from "react-color-palette";
const useResponsiveWidth = (): [
width: number,
setRef: MutableRefObject<HTMLElement | null>
] => {
const ref = useRef(null);
const [width, setWidth] = useState(0);
useLayoutEffect(() => {
if (!ref || !ref.current) {
return;
}
const resizeObserver = new ResizeObserver((targets) => {
const { width: currentWidth } = targets[0].contentRect;
setWidth(currentWidth);
});
resizeObserver.observe(ref.current);
return () => {
resizeObserver.disconnect();
};
}, []);
return [width, ref];
};
export interface IColorPickerProps {
value: Color;
onChangeComplete: (color: Color) => void;
disabled?: boolean;
}
export default function ColorPickerInput({
value,
onChangeComplete,
disabled = false,
}: IColorPickerProps) {
const [localValue, setLocalValue] = useState(value);
const [width, setRef] = useResponsiveWidth();
const theme = useTheme();
return (
<Box
ref={setRef}
sx={[
{
padding: theme.spacing(1.5),
paddingTop: theme.spacing(1),
transitionDuration: 0,
"& .rcp": {
border: "none",
"& .rcp-saturation": {
borderRadius: theme.spacing(0.5),
},
"& .rcp-body": {
boxSizing: "unset",
},
},
},
]}
>
<ColorPicker
width={width}
height={150}
color={localValue}
onChange={(color) => setLocalValue(color)}
onChangeComplete={onChangeComplete}
/>
</Box>
);
}

View File

@@ -124,8 +124,9 @@ export default function ColumnMenu() {
};
const localViewActions: IMenuContentsProps["menuItems"] = [
{ type: "subheader" },
{ type: "subheader", key: "subLocalView" },
{
key: "sortDesc",
label: "Sort: descending",
activeLabel: "Remove sort: descending",
icon: <ArrowDownwardIcon />,
@@ -139,6 +140,7 @@ export default function ColumnMenu() {
disabled: column.type === FieldType.id,
},
{
key: "sortAsc",
label: "Sort: ascending",
activeLabel: "Remove sort: ascending",
icon: <ArrowUpwardIcon />,
@@ -152,6 +154,7 @@ export default function ColumnMenu() {
disabled: column.type === FieldType.id,
},
{
key: "hide",
label: "Hide",
icon: <VisibilityIcon />,
onClick: () => {
@@ -168,6 +171,7 @@ export default function ColumnMenu() {
disabled: !updateUserSettings,
},
{
key: "filter",
label: "Filter…",
icon: <FilterIcon />,
onClick: () => {
@@ -187,9 +191,10 @@ export default function ColumnMenu() {
];
const configActions: IMenuContentsProps["menuItems"] = [
{ type: "subheader" },
{ type: "subheader", key: "subActionsConfig" },
{
label: "Lock",
key: "lock",
activeLabel: "Unlock",
icon: <LockOpenIcon />,
activeIcon: <LockIcon />,
@@ -204,6 +209,7 @@ export default function ColumnMenu() {
},
{
label: "Disable resize",
key: "disableResize",
activeLabel: "Enable resize",
icon: <CellResizeIcon />,
onClick: () => {
@@ -217,6 +223,7 @@ export default function ColumnMenu() {
},
{
label: "Freeze",
key: "freeze",
activeLabel: "Unfreeze",
icon: <FreezeIcon />,
activeIcon: <UnfreezeIcon />,
@@ -229,6 +236,7 @@ export default function ColumnMenu() {
// { type: "subheader" },
{
label: "Rename…",
key: "rename",
icon: <EditIcon />,
onClick: () => {
openColumnModal({ type: "name", columnKey: column.key });
@@ -237,6 +245,7 @@ export default function ColumnMenu() {
},
{
label: `Edit type: ${getFieldProp("name", column.type)}`,
key: "editType",
// This is based on the cell type
icon: getFieldProp("icon", column.type),
onClick: () => {
@@ -246,6 +255,7 @@ export default function ColumnMenu() {
},
{
label: `Column config…`,
key: "columConfig",
icon: <SettingsIcon />,
onClick: () => {
openColumnModal({ type: "config", columnKey: column.key });
@@ -299,8 +309,9 @@ export default function ColumnMenu() {
}
};
const derivativeActions: IMenuContentsProps["menuItems"] = [
{ type: "subheader" },
{ type: "subheader", key: "sub-derivative" },
{
key: "evaluateAll",
label: altPress ? "Evaluate all" : "Evaluate all…",
icon: <EvalIcon />,
onClick: altPress
@@ -323,9 +334,10 @@ export default function ColumnMenu() {
];
const columnActions: IMenuContentsProps["menuItems"] = [
{ type: "subheader" },
{ type: "subheader", key: "subActions" },
{
label: "Insert to the left…",
key: "insertLeft",
icon: <ColumnPlusBeforeIcon />,
onClick: () => {
openColumnModal({ type: "new", index: column.index - 1 });
@@ -334,6 +346,7 @@ export default function ColumnMenu() {
},
{
label: "Insert to the right…",
key: "insertRight",
icon: <ColumnPlusAfterIcon />,
onClick: () => {
openColumnModal({ type: "new", index: column.index + 1 });
@@ -342,6 +355,7 @@ export default function ColumnMenu() {
},
{
label: `Delete column${altPress ? "" : "…"}`,
key: "delete",
icon: <ColumnRemoveIcon />,
onClick: altPress
? handleDeleteColumn

View File

@@ -4,6 +4,7 @@ import { MenuItem, ListItemIcon, ListSubheader, Divider } from "@mui/material";
export interface IMenuContentsProps {
menuItems: {
key: string;
type?: string;
label?: string;
activeLabel?: string;
@@ -36,6 +37,7 @@ export default function MenuContents({ menuItems }: IMenuContentsProps) {
return (
<MenuItem
key={index}
id={`column-menu-item-${item.key}`}
onClick={item.onClick}
color={item.color}
selected={item.active}

View File

@@ -1,6 +1,6 @@
import { useState } from "react";
import { styled, useTheme } from "@mui/material";
import { GlobalStyles } from "tss-react";
import { alpha, styled, useTheme } from "@mui/material";
import { Editor } from "@tinymce/tinymce-react";
// TinyMCE so the global var exists
@@ -10,7 +10,9 @@ import "tinymce/themes/silver";
// Toolbar icons
import "tinymce/icons/default";
// Editor styles
import "tinymce/skins/ui/oxide/skin.min.css";
/* eslint import/no-webpack-loader-syntax: off */
import skinCss from "!!raw-loader!tinymce/skins/ui/oxide/skin.min.css";
import skinDarkCss from "!!raw-loader!tinymce/skins/ui/oxide-dark/skin.min.css";
// Content styles, including inline UI like fake cursors
/* eslint import/no-webpack-loader-syntax: off */
import contentCss from "!!raw-loader!tinymce/skins/content/default/content.min.css";
@@ -55,7 +57,32 @@ const Styles = styled("div", {
},
"& .tox-edit-area__iframe": { colorScheme: "auto" },
"& .tox-toolbar__group": { border: "none !important" },
"& .tox-toolbar__group": {
border: "none !important",
"& .tox-tbtn": {
"&:hover:": {
backgroundColor: "inherit",
},
"&:focus": {
backgroundColor: "inherit",
},
},
"& .tox-tbtn__select-chevron": {
transition: theme.transitions.create("transform", {
duration: theme.transitions.duration.short,
}),
},
"& .tox-tbtn--select": {
"& .tox-tbtn__select-chevron": {
transform: "none",
},
},
"& .tox-tbtn--active": {
"& .tox-tbtn__select-chevron": {
transform: "rotate(180deg)",
},
},
},
"& .tox-tbtn": {
borderRadius: theme.shape.borderRadius,
@@ -118,7 +145,74 @@ export default function RichTextEditor({
return (
<Styles focus={focus} disabled={disabled}>
<style>{theme.palette.mode === "dark" ? skinDarkCss : skinCss}</style>
<GlobalStyles
styles={{
".tox": {
"& .tox-menu.tox-menu, &.tox-tinymce-aux .tox-toolbar__overflow.tox-toolbar__overflow":
{
backgroundColor: theme.palette.background.paper,
backgroundImage:
"linear-gradient(rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.12))", // elevation 8
boxShadow: theme.shadows[8],
border: "none",
borderRadius: (theme.shape.borderRadius as number) * 2,
},
"& .tox-collection--list": {
"& .tox-collection__group.tox-collection__group": {
padding: theme.spacing(0.5),
paddingLeft: 0,
paddingRight: 0,
},
"& .tox-collection__item": {
padding: theme.spacing(0.5),
marginLeft: theme.spacing(0.5),
marginRight: theme.spacing(0.5),
borderRadius: theme.shape.borderRadius,
},
"& .tox-collection__item--enabled": {
backgroundColor: theme.palette.action.hover + " !important",
position: "relative",
"&::before": {
content: '""',
display: "block",
position: "absolute",
top: theme.spacing(1),
bottom: theme.spacing(1),
left: 0,
width: theme.spacing(0.3),
borderRadius: theme.shape.borderRadius,
backgroundColor: theme.palette.primary.main,
},
},
"& .tox-collection__item--active": {
backgroundColor:
alpha(
theme.palette.primary.main,
theme.palette.action.selectedOpacity
) + "!important",
},
"& .tox-collection__item-checkmark": {
display: "none",
},
},
"&.tox-tinymce-aux .tox-toolbar__overflow.tox-toolbar__overflow": {
padding: theme.spacing(0.5, 0),
},
"& .tox-tbtn.tox-tbtn": {
borderRadius: theme.shape.borderRadius,
margin: 0,
},
},
}}
/>
<Editor
key={theme.palette.mode}
disabled={disabled}
init={{
skin: false,

View File

@@ -2,7 +2,7 @@ import { sortBy } from "lodash-es";
import MultiSelect from "@rowy/multiselect";
import { Grid } from "@mui/material";
import LeafIcon from "@src/assets/icons/Leaf";
import { Leaf as LeafIcon } from "@src/assets/icons";
import { CLOUD_RUN_REGIONS } from "@src/constants/regions";

View File

@@ -88,6 +88,7 @@ export default function DraggableHeaderRenderer({
return (
<Grid
key={column.key}
id={`column-header-${column.key}`}
ref={(ref) => {
dragRef(ref);
dropRef(ref);
@@ -213,6 +214,7 @@ export default function DraggableHeaderRenderer({
<IconButton
size="small"
aria-label={`Column settings for ${column.name as string}`}
id={`column-settings-${column.key}`}
color="inherit"
onClick={handleOpenMenu}
ref={buttonRef}

View File

@@ -24,6 +24,7 @@ export default function TableRow(props: RowRendererProps<any>) {
return (
<Row
key={props.row._rowy_ref.path}
id={`row-${props.row._rowy_ref.path}`}
onContextMenu={handleContextMenu}
{...props}
/>

View File

@@ -232,7 +232,10 @@ export default function TableSettingsDialog() {
})),
["section", "label"]
),
Array.isArray(collections) ? collections.filter((x) => x !== CONFIG) : null
Array.isArray(collections) &&
collections.filter((x) => x !== CONFIG).length > 0
? collections.filter((x) => x !== CONFIG)
: null
);
return (

View File

@@ -1,16 +1,21 @@
import { Suspense, createElement } from "react";
import { ErrorBoundary } from "react-error-boundary";
import {
Grid,
MenuItem,
ListItemText,
Divider,
ListSubheader,
Typography,
TextField,
InputLabel,
} from "@mui/material";
import ColumnSelect from "@src/components/Table/ColumnSelect";
import FieldSkeleton from "@src/components/SideDrawer/FieldSkeleton";
import IdFilterInput from "./IdFilterInput";
import { InlineErrorFallback } from "@src/components/ErrorFallback";
import type { useFilterInputs } from "./useFilterInputs";
import { getFieldType, getFieldProp } from "@src/components/fields";
@@ -30,6 +35,45 @@ export default function FilterInputs({
}: IFilterInputsProps) {
const columnType = selectedColumn ? getFieldType(selectedColumn) : null;
const operators = availableFilters?.operators ?? [];
const renderedOperatorItems = operators.map((operator) => (
<MenuItem key={operator.value} value={operator.value}>
<ListItemText style={{ flexShrink: 0 }}>{operator.label}</ListItemText>
{operator.secondaryLabel && (
<Typography
variant="inherit"
color="text.disabled"
sx={{ overflow: "hidden", textOverflow: "ellipsis", ml: 1 }}
>
&nbsp;{operator.secondaryLabel}
</Typography>
)}
</MenuItem>
));
// Insert ListSubheader components in between groups of operators
for (let i = 0; i < operators.length; i++) {
if (!operators[i].group) continue;
if (i === 0 || operators[i - 1].group !== operators[i].group) {
renderedOperatorItems.splice(
i === 0 ? 0 : i + 1,
0,
<ListSubheader key={operators[i].group}>
{operators[i].group}
</ListSubheader>
);
if (i > 0)
renderedOperatorItems.splice(
i + 1,
0,
<Divider key={`divider-${operators[i].group}`} variant="middle" />
);
}
}
return (
<Grid container spacing={2} sx={{ mb: 3 }}>
<Grid item xs={4}>
@@ -65,29 +109,13 @@ export default function FilterInputs({
<MenuItem disabled value="" style={{ display: "none" }}>
Select operator
</MenuItem>
{availableFilters?.operators.map((operator) => (
<MenuItem key={operator.value} value={operator.value}>
<ListItemText style={{ flexShrink: 0 }}>
{operator.label}
</ListItemText>
{operator.secondaryLabel && (
<Typography
variant="inherit"
color="text.disabled"
style={{ overflow: "hidden", textOverflow: "ellipsis" }}
>
&nbsp;{operator.secondaryLabel}
</Typography>
)}
</MenuItem>
))}
{renderedOperatorItems}
</TextField>
</Grid>
<Grid item xs={4}>
<Grid item xs={4} key={query.key + query.operator}>
{query.key && query.operator && (
<>
<ErrorBoundary FallbackComponent={InlineErrorFallback}>
<InputLabel
variant="filled"
id={`filters-label-${query.key}`}
@@ -111,10 +139,11 @@ export default function FilterInputs({
setQuery((query) => ({ ...query, value }));
},
disabled,
operator: query.operator,
}
)}
</Suspense>
</>
</ErrorBoundary>
)}
</Grid>
</Grid>

View File

@@ -75,8 +75,8 @@ export default function FiltersPopover({
);
const formattedValue = availableFilters?.valueFormatter
? availableFilters.valueFormatter(filter.value)
: filter.value;
? availableFilters.valueFormatter(filter.value, filter.operator)
: filter.value.toString();
return (
<Chip

View File

@@ -93,10 +93,9 @@ export default function ActionFab({
return resp;
};
const handleCallableAction = async (data: any) => {
const resp: any = await httpsCallable(
firebaseFunctions,
callableName
)(data);
const resp: any = await httpsCallable(firebaseFunctions, callableName, {
timeout: 550000,
})(data);
return resp.data;
};

View File

@@ -58,7 +58,7 @@ const CodeEditor = lazy(
import("@src/components/CodeEditor" /* webpackChunkName: "CodeEditor" */)
);
const Settings = ({ config, onChange }: ISettingsProps) => {
const Settings = ({ config, onChange, fieldName }: ISettingsProps) => {
const [projectId] = useAtom(projectIdAtom, globalScope);
const [roles] = useAtom(projectRolesAtom, globalScope);
const [settings] = useAtom(projectSettingsAtom, globalScope);
@@ -77,10 +77,12 @@ const Settings = ({ config, onChange }: ISettingsProps) => {
// ? ["requirements", "friction", "action", "undo", "customization"]
// : ["requirements", "friction", "action", "customization"];
const columnOptions = tableColumnsOrdered.map((c) => ({
label: c.name,
value: c.key,
}));
const columnOptions = tableColumnsOrdered
.map((c) => ({
label: c.name,
value: c.key,
}))
.filter((c) => c.value !== fieldName);
const formattedParamsJson = stringify(
Array.isArray(config.params) ? config.params : [],
@@ -145,6 +147,7 @@ const Settings = ({ config, onChange }: ISettingsProps) => {
<Grid item xs={12} sm={6}>
<MultiSelect
label="Required roles"
labelPlural="roles"
options={roles ?? []}
value={config.requiredRoles ?? []}
onChange={onChange("requiredRoles")}
@@ -158,6 +161,7 @@ const Settings = ({ config, onChange }: ISettingsProps) => {
<Grid item xs={12} sm={6}>
<MultiSelect
label="Required fields"
labelPlural="fields"
options={columnOptions}
value={config.requiredFields ?? []}
onChange={onChange("requiredFields")}

View File

@@ -0,0 +1,14 @@
import { IFilterCustomInputProps } from "@src/components/fields/types";
import DateTimeInput from "./SideDrawerField";
import DateInput from "@src/components/fields/Date/SideDrawerField";
export default function FilterCustomInput({
onChange,
operator,
...props
}: IFilterCustomInputProps) {
if (operator && operator.startsWith("date-"))
return <DateInput {...(props as any)} onChange={onChange} />;
return <DateTimeInput {...(props as any)} onChange={onChange} />;
}

View File

@@ -14,7 +14,7 @@ import { getFieldId } from "@src/components/SideDrawer/utils";
export interface IDateProps extends ISideDrawerFieldProps {}
export default function Date_({
export default function DateTime({
column,
value,
onChange,

View File

@@ -1,5 +1,5 @@
import { format } from "date-fns";
import { DATE_TIME_FORMAT } from "@src/constants/dates";
import { DATE_TIME_FORMAT, DATE_FORMAT } from "@src/constants/dates";
import { IFilterOperator } from "@src/components/fields/types";
export const filterOperators: IFilterOperator[] = [
@@ -7,60 +7,75 @@ export const filterOperators: IFilterOperator[] = [
label: "equals",
secondaryLabel: "==",
value: "time-minute-equal",
group: "Date & Time",
},
{
label: "not equal to",
secondaryLabel: "!=",
value: "!=",
group: "Date & Time",
},
{
label: "before",
secondaryLabel: "<",
value: "<",
group: "Date & Time",
},
{
label: "after",
secondaryLabel: ">",
value: ">",
group: "Date & Time",
},
{
label: "before or at",
secondaryLabel: "<=",
value: "<=",
group: "Date & Time",
},
{
label: "at or after",
secondaryLabel: ">=",
value: ">=",
group: "Date & Time",
},
{
label: "where date is is",
label: "where date is",
secondaryLabel: "date ==",
value: "date-equal",
group: "Date",
},
{
label: "where date is before",
secondaryLabel: "date <",
value: "date-before",
group: "Date",
},
{
label: "where date is after",
secondaryLabel: "date >",
value: "date-after",
group: "Date",
},
{
label: "where date is before or on",
secondaryLabel: "date <=",
value: "date-before-equal",
group: "Date",
},
{
label: "where date is on or after",
secondaryLabel: "date >=",
value: "date-after-equal",
group: "Date",
},
];
export const valueFormatter = (value: any) => {
if (value && value.toDate) return format(value.toDate(), DATE_TIME_FORMAT);
export const valueFormatter = (value: any, operator: string) => {
if (value && value.toDate)
return format(
value.toDate(),
operator.startsWith("date") ? DATE_FORMAT : DATE_TIME_FORMAT
);
return "";
};

View File

@@ -21,6 +21,12 @@ const SideDrawerField = lazy(
const Settings = lazy(
() => import("./Settings" /* webpackChunkName: "Settings-DateTime" */)
);
const FilterCustomInput = lazy(
() =>
import(
"./FilterCustomInput" /* webpackChunkName: "FilterCustomInput-DateTime" */
)
);
export const config: IFieldConfig = {
type: FieldType.dateTime,
@@ -34,7 +40,11 @@ export const config: IFieldConfig = {
TableCell: withHeavyCell(BasicCell, TableCell),
TableEditor: NullEditor as any,
SideDrawerField,
filter: { operators: filterOperators, valueFormatter },
filter: {
operators: filterOperators,
valueFormatter,
customInput: FilterCustomInput,
},
settings: Settings,
csvImportParser: (value) => parseJSON(value).getTime(),
csvExportFormatter: (value: any, config?: any) =>

View File

@@ -1,41 +0,0 @@
import { ISettingsProps } from "@src/components/fields/types";
import MultiSelect from "@rowy/multiselect";
const languages = [
"javascript",
"typescript",
"json",
"html",
"css",
"scss",
"shell",
"yaml",
"xml",
"ruby",
"python",
"php",
"markdown",
"rust",
"csharp",
"cpp",
"c",
"java",
"go",
"plaintext",
];
export default function Settings({ config, onChange }: ISettingsProps) {
return (
<MultiSelect
searchable
multiple={false}
options={languages}
value={config.language ?? "javascript"}
onChange={(value) => {
onChange("language")(value);
}}
label="Language"
labelPlural="languages"
/>
);
}

View File

@@ -6,10 +6,6 @@ import { Markdown as MarkdownIcon } from "@src/assets/icons";
import BasicCell from "./BasicCell";
import withSideDrawerEditor from "@src/components/Table/editors/withSideDrawerEditor";
const Settings = lazy(
() => import("./Settings" /* webpackChunkName: "Settings-markdown" */)
);
const SideDrawerField = lazy(
() =>
import(
@@ -29,6 +25,5 @@ export const config: IFieldConfig = {
TableCell: withBasicCell(BasicCell),
TableEditor: withSideDrawerEditor(BasicCell),
SideDrawerField,
settings: Settings,
};
export default config;

View File

@@ -1,41 +1,23 @@
import { IBasicCellProps } from "@src/components/fields/types";
import { useTheme } from "@mui/material";
import { resultColorsScale } from "@src/utils/color";
export default function Percentage({ value }: IBasicCellProps) {
const theme = useTheme();
if (typeof value === "number")
return (
<>
<div
style={{
backgroundColor: resultColorsScale(value).toHex(),
if (value === null || value === undefined) return null;
position: "absolute",
top: 0,
right: 0,
bottom: 0,
left: 0,
opacity: 0.5,
zIndex: 0,
}}
/>
<div
style={{
textAlign: "right",
color: theme.palette.text.primary,
position: "relative",
zIndex: 1,
}}
>
{Math.round(value * 100)}%
</div>
</>
);
return null;
const percentage = typeof value === "number" ? value : 0;
return (
<div
style={{
textAlign: "right",
color: theme.palette.text.primary,
position: "relative",
zIndex: 1,
}}
>
{Math.round(percentage * 100)}%
</div>
);
}

View File

@@ -0,0 +1,171 @@
import { useState } from "react";
import {
Box,
Checkbox,
Grid,
InputLabel,
MenuItem,
TextField,
Typography,
useTheme,
} from "@mui/material";
import ColorPickerInput from "@src/components/ColorPickerInput";
import { ISettingsProps } from "@src/components/fields/types";
import { Color, toColor } from "react-color-palette";
import { fieldSx } from "@src/components/SideDrawer/utils";
import { resultColorsScale, defaultColors } from "@src/utils/color";
const colorLabels: { [key: string]: string } = {
0: "Start",
1: "Middle",
2: "End",
};
export default function Settings({ onChange, config }: ISettingsProps) {
const colors: string[] = config.colors ?? defaultColors;
const [checkStates, setCheckStates] = useState<boolean[]>(
colors.map(Boolean)
);
const onCheckboxChange = (index: number, checked: boolean) => {
onChange("colors")(
colors.map((value: any, idx: number) =>
index === idx ? (checked ? value || defaultColors[idx] : null) : value
)
);
setCheckStates(
checkStates.map((value, idx) => (index === idx ? checked : value))
);
};
const handleColorChange = (index: number, color: Color): void => {
onChange("colors")(
colors.map((value, idx) => (index === idx ? color.hex : value))
);
};
return (
<>
<Grid container>
{checkStates.map((checked: boolean, index: number) => {
const colorHex = colors[index];
return (
<Grid
xs={12}
md={4}
item
sx={{
display: "flex",
alignItems: "end",
justifyContent: "center",
}}
>
<Checkbox
checked={checked}
sx={[
fieldSx,
{
width: "auto",
boxShadow: "none",
backgroundColor: "inherit",
"&:hover": {
backgroundColor: "inherit",
},
},
]}
onChange={() => onCheckboxChange(index, !checked)}
/>
<TextField
select
label={colorLabels[index]}
value={1}
fullWidth
disabled={!checkStates[index]}
>
<MenuItem value={1} sx={{ display: "none" }}>
{checked && (
<Box sx={{ display: "flex", alignItems: "center" }}>
<Box
sx={{
backgroundColor: colorHex,
width: 15,
height: 15,
mr: 1.5,
boxShadow: (theme) =>
`0 0 0 1px ${theme.palette.divider} inset`,
borderRadius: 0.5,
opacity: 0.5,
}}
/>
<Box>{colorHex}</Box>
</Box>
)}
</MenuItem>
{colorHex && (
<div>
<ColorPickerInput
value={toColor("hex", colorHex)}
onChangeComplete={(color) =>
handleColorChange(index, color)
}
disabled={!checkStates[index]}
/>
</div>
)}
</TextField>
</Grid>
);
})}
</Grid>
<Preview colors={config.colors} />
</>
);
}
const Preview = ({ colors }: { colors: any }) => {
const theme = useTheme();
return (
<InputLabel>
Preview:
<Box
sx={{
display: "flex",
textAlign: "center",
}}
>
{[0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1].map((value) => {
return (
<Box
sx={{
position: "relative",
width: "100%",
padding: "0.5rem 0",
color: theme.palette.text.primary,
}}
>
<Box
key={value}
sx={{
position: "absolute",
inset: 0,
backgroundColor: resultColorsScale(
value,
colors,
theme.palette.background.paper
).toHex(),
opacity: 0.5,
}}
/>
<Typography style={{ position: "relative", zIndex: 1 }}>
{Math.floor(value * 100)}%
</Typography>
</Box>
);
})}
</Box>
</InputLabel>
);
};

View File

@@ -1,7 +1,6 @@
import { ISideDrawerFieldProps } from "@src/components/fields/types";
import { TextField, InputAdornment, Box } from "@mui/material";
import { emphasize } from "@mui/material/styles";
import { TextField, InputAdornment, Box, useTheme } from "@mui/material";
import { resultColorsScale } from "@src/utils/color";
import { getFieldId } from "@src/components/SideDrawer/utils";
@@ -12,6 +11,8 @@ export default function Percentage({
onSubmit,
disabled,
}: ISideDrawerFieldProps) {
const { colors } = (column as any).config;
const theme = useTheme();
return (
<TextField
variant="filled"
@@ -34,11 +35,14 @@ export default function Percentage({
width: 20,
height: 20,
borderRadius: 0.5,
boxShadow: (theme) =>
`0 0 0 1px ${theme.palette.divider} inest`,
boxShadow: `0 0 0 1px ${theme.palette.divider} inset`,
backgroundColor:
typeof value === "number"
? resultColorsScale(value).toHex() + "!important"
? resultColorsScale(
value,
colors,
theme.palette.background.paper
).toHex() + "!important"
: undefined,
}}
/>

View File

@@ -0,0 +1,41 @@
import { IHeavyCellProps } from "@src/components/fields/types";
import { useTheme } from "@mui/material";
import { resultColorsScale } from "@src/utils/color";
export default function Percentage({ column, value }: IHeavyCellProps) {
const theme = useTheme();
const { colors } = (column as any).config;
const percentage = typeof value === "number" ? value : 0;
return (
<>
<div
style={{
backgroundColor: resultColorsScale(
percentage,
colors,
theme.palette.background.paper
).toHex(),
position: "absolute",
top: 0,
right: 0,
bottom: 0,
left: 0,
opacity: 0.5,
zIndex: 0,
}}
/>
<div
style={{
textAlign: "right",
color: theme.palette.text.primary,
position: "relative",
zIndex: 1,
}}
>
{Math.round(percentage * 100)}%
</div>
</>
);
}

View File

@@ -1,12 +1,20 @@
import { lazy } from "react";
import { IFieldConfig, FieldType } from "@src/components/fields/types";
import withBasicCell from "@src/components/fields/_withTableCell/withBasicCell";
import withHeavyCell from "@src/components/fields/_withTableCell/withHeavyCell";
import { Percentage as PercentageIcon } from "@src/assets/icons";
import BasicCell from "./BasicCell";
import TextEditor from "@src/components/Table/editors/TextEditor";
import { filterOperators } from "@src/components/fields/Number/Filter";
import BasicContextMenuActions from "@src/components/fields/_BasicCell/BasicCellContextMenuActions";
const BasicCell = lazy(
() => import("./BasicCell" /* webpackChunkName: "BasicCell-Percentage" */)
);
const TableCell = lazy(
() => import("./TableCell" /* webpackChunkName: "TableCell-Percentage" */)
);
const SideDrawerField = lazy(
() =>
import(
@@ -14,6 +22,10 @@ const SideDrawerField = lazy(
)
);
const Settings = lazy(
() => import("./Settings" /* webpackChunkName: "Settings-Percentage" */)
);
export const config: IFieldConfig = {
type: FieldType.percentage,
name: "Percentage",
@@ -22,11 +34,13 @@ export const config: IFieldConfig = {
initialValue: 0,
initializable: true,
icon: <PercentageIcon />,
requireConfiguration: true,
description: "Percentage stored as a number between 0 and 1.",
contextMenuActions: BasicContextMenuActions,
TableCell: withBasicCell(BasicCell),
TableCell: withHeavyCell(BasicCell, TableCell),
TableEditor: TextEditor,
SideDrawerField,
settings: Settings,
filter: {
operators: filterOperators,
},

View File

@@ -35,9 +35,9 @@ export interface IFieldConfig {
settingsValidator?: (config: Record<string, any>) => Record<string, string>;
filter?: {
operators: IFilterOperator[];
customInput?: React.ComponentType<{ onChange: (value: any) => void }>;
customInput?: React.ComponentType<IFilterCustomInputProps>;
defaultValue?: any;
valueFormatter?: (value: any) => string;
valueFormatter?: (value: any, operator: TableFilter["operator"]) => string;
};
sortKey?: string;
csvExportFormatter?: (value: any, config?: any) => string;
@@ -104,4 +104,11 @@ export interface IFilterOperator {
value: TableFilter["operator"];
label: string;
secondaryLabel?: React.ReactNode;
group?: string;
}
export interface IFilterCustomInputProps {
onChange: (value: any) => void;
operator: TableFilter["operator"];
[key: string]: any;
}

View File

@@ -232,7 +232,7 @@ export default function NavDrawer({
{...({ component: "button" } as any)}
style={{ textAlign: "left" }}
sx={{ mb: 1 }}
onClick={(e) => {
onClick={(e: any) => {
if (closeDrawer) closeDrawer(e);
openTableSettingsDialog({});
}}

View File

@@ -1,29 +1,45 @@
import { Link, useLocation } from "react-router-dom";
import { MenuItem, MenuItemProps } from "@mui/material";
import { spreadSx } from "@src/utils/ui";
export default function NavItem(props: MenuItemProps<typeof Link>) {
const linkProps = { target: "_blank", rel: "noopener noreferrer" };
export default function NavItem(
props: MenuItemProps<typeof Link | "a" | "button">
) {
const { pathname } = useLocation();
return (
<MenuItem
component={Link}
selected={pathname === props.to}
role="none"
tabIndex={0}
component={"to" in props ? Link : "href" in props ? "a" : "button"}
selected={"to" in props ? pathname === props.to : false}
{...props}
sx={{
"& .MuiListItemText-primary": {
typography: "button",
{...("href" in props ? linkProps : {})}
sx={[
{
overflow: "hidden",
textAlign: "left",
color: "text.secondary",
},
"& .MuiListItemIcon-root": { opacity: 0.87 },
"&:hover, &.Mui-selected": {
"& .MuiListItemText-primary": { color: "text.primary" },
"& .MuiSvgIcon-root": { color: "text.primary" },
},
"& .MuiListItemText-primary": {
typography: "button",
overflow: "hidden",
},
"& .MuiSvgIcon-root": {
color: "inherit",
opacity: 0.87,
display: "block",
},
...props.sx,
"&&::before": { left: "auto", right: 0 },
}}
"&:hover, &.Mui-selected": {
"& .MuiListItemText-primary": { color: "text.primary" },
"& .MuiSvgIcon-root": { color: "text.primary" },
},
},
...spreadSx(props.sx),
]}
/>
);
}

View File

@@ -1,12 +1,18 @@
import { colord } from "colord";
export const resultColors = {
No: "#ED4747",
Maybe: "#f3c900",
Yes: "#1fad5f",
};
export const defaultColors = ["#ED4747", "#F3C900", "#1FAD5F"];
export const resultColorsScale = (value: number) =>
export const resultColorsScale = (
value: number,
colors: any = defaultColors,
defaultColor: string = "#fff"
) =>
value <= 0.5
? colord(resultColors.No).mix(resultColors.Maybe, value * 2)
: colord(resultColors.Maybe).mix(resultColors.Yes, (value - 0.5) * 2);
? colord(colors[0] || defaultColor).mix(
colors[1] || defaultColor,
value * 2
)
: colord(colors[1] || defaultColor).mix(
colors[2] || defaultColor,
(value - 0.5) * 2
);

104
yarn.lock
View File

@@ -3100,7 +3100,7 @@
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78=
integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==
"@protobufjs/base64@^1.1.2":
version "1.1.2"
@@ -3115,12 +3115,12 @@
"@protobufjs/eventemitter@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70"
integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A=
integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==
"@protobufjs/fetch@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45"
integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=
integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==
dependencies:
"@protobufjs/aspromise" "^1.1.1"
"@protobufjs/inquire" "^1.1.0"
@@ -3128,27 +3128,27 @@
"@protobufjs/float@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1"
integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=
integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==
"@protobufjs/inquire@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089"
integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=
integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==
"@protobufjs/path@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d"
integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=
integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==
"@protobufjs/pool@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54"
integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=
integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==
"@protobufjs/utf8@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
"@react-dnd/asap@^4.0.0":
version "4.0.1"
@@ -3836,9 +3836,9 @@
integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==
"@types/long@^4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==
version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a"
integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==
"@types/mdast@^3.0.0":
version "3.0.10"
@@ -3862,21 +3862,16 @@
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
"@types/node@*":
"@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0":
version "18.0.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.0.tgz#67c7b724e1bcdd7a8821ce0d5ee184d3b4dd525a"
integrity sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==
"@types/node@^17.0.23":
version "17.0.26"
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.26.tgz#1bbff9b23ee5a64f87b4f30c0c854b112ee2e635"
integrity sha512-z/FG/6DUO7pnze3AE3TBGIjGGKkvCcGcWINe1C7cADY8hKLJPDYpzsNE37uExQ4md5RFtTCvg+M8Mu1Enyeg2A==
"@types/node@>=12.12.47", "@types/node@>=13.7.0":
version "16.4.13"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.4.13.tgz#7dfd9c14661edc65cccd43a29eb454174642370d"
integrity sha512-bLL69sKtd25w7p1nvg9pigE4gtKVpGTPojBFLMkGHXuUgap2sLqQt2qUnqmVCDfzGUL0DRNZP+1prIZJbMeAXg==
"@types/node@^17.0.23":
version "17.0.23"
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.23.tgz#3b41a6e643589ac6442bdbd7a4a3ded62f33f7da"
integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==
"@types/parse-json@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
@@ -4676,11 +4671,6 @@ astral-regex@^2.0.0:
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
async@0.9.x:
version "0.9.2"
resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=
async@^2.6.2:
version "2.6.3"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
@@ -4689,9 +4679,9 @@ async@^2.6.2:
lodash "^4.17.14"
async@^3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9"
integrity sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==
version "3.2.4"
resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
asynckit@^0.4.0:
version "0.4.0"
@@ -5439,7 +5429,7 @@ compression@^1.7.4:
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
concat-stream@~1.6.0:
version "1.6.2"
@@ -6215,20 +6205,13 @@ ee-first@1.1.1:
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
ejs@^3.1.5:
version "3.1.7"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.7.tgz#c544d9c7f715783dd92f0bddcf73a59e6962d006"
integrity sha512-BIar7R6abbUxDA3bfXrO4DSgwo8I+fB5/1zgujl3HLLjwd6+9iOnrT+t3grn2qbk9vOgBubXOFwX2m9axoFaGw==
ejs@^3.1.5, ejs@^3.1.6:
version "3.1.8"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.8.tgz#758d32910c78047585c7ef1f92f9ee041c1c190b"
integrity sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==
dependencies:
jake "^10.8.5"
ejs@^3.1.6:
version "3.1.6"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.6.tgz#5bfd0a0689743bb5268b3550cceeebbc1702822a"
integrity sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==
dependencies:
jake "^10.6.1"
electron-to-chromium@^1.3.649:
version "1.3.671"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.671.tgz#8feaed6eae42d279fa4611f58c42a5a1eb81b2a0"
@@ -6935,11 +6918,11 @@ file-selector@^0.1.12:
tslib "^2.0.1"
filelist@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.2.tgz#80202f21462d4d1c2e214119b1807c1bc0380e5b"
integrity sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==
version "1.0.4"
resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5"
integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==
dependencies:
minimatch "^3.0.4"
minimatch "^5.0.1"
filesize@^8.0.6:
version "8.0.7"
@@ -8133,16 +8116,6 @@ istanbul-reports@^3.1.3:
html-escaper "^2.0.0"
istanbul-lib-report "^3.0.0"
jake@^10.6.1:
version "10.8.4"
resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.4.tgz#f6a8b7bf90c6306f768aa82bb7b98bf4ca15e84a"
integrity sha512-MtWeTkl1qGsWUtbl/Jsca/8xSoK3x0UmS82sNbjqxxG/de/M/3b1DntdjHgPMC50enlTNwXOCRqPXLLt5cCfZA==
dependencies:
async "0.9.x"
chalk "^4.0.2"
filelist "^1.0.1"
minimatch "^3.0.4"
jake@^10.8.5:
version "10.8.5"
resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.5.tgz#f2183d2c59382cb274226034543b9c03b8164c46"
@@ -9754,12 +9727,7 @@ minimatch@^5.0.1, minimatch@^5.1.0:
dependencies:
brace-expansion "^2.0.1"
minimist@^1.1.1, minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.6:
minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
version "1.2.6"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
@@ -11047,9 +11015,9 @@ property-information@^6.0.0:
integrity sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w==
protobufjs@^6.10.0:
version "6.11.2"
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.2.tgz#de39fabd4ed32beaa08e9bb1e30d08544c1edf8b"
integrity sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==
version "6.11.3"
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.3.tgz#637a527205a35caa4f3e2a9a4a13ddffe0e7af74"
integrity sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==
dependencies:
"@protobufjs/aspromise" "^1.1.2"
"@protobufjs/base64" "^1.1.2"
@@ -12964,9 +12932,9 @@ tmp@^0.2.1:
rimraf "^3.0.0"
tmpl@1.0.x:
version "1.0.4"
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
version "1.0.5"
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==
to-fast-properties@^2.0.0:
version "2.0.0"