Skip to content
Snippets Groups Projects
Unverified Commit ef256e31 authored by Benoit Vinay's avatar Benoit Vinay Committed by GitHub
Browse files

Various fixes for errors seen in the console while browsing (#21060)

* shouldNotForwardTransientProp method created for emotion

* BadgeIcon html attributes clean up

* Usage of transient property $hasMargin in Badge for BadgeIcon

* HTML attribute cleanup for LinkRoot

* React key added to ButtonBar child if not defined

* Properties for TableInfoPopover properly typed

* Misc

* analyticsContext property set as non required as non of the parents enforce it or pass a value

* Clean up attributes for SVG in Icon

* CSS fix for share icon special case in Icon

* Checkbox controlled component default value fix

* Misc clean up

* index file for collection side bar

* Collections collectionID type fix

* collection type in NewCollectionItemMenu fix

* Misc

* TokenField fix for value

* noPopover passed properly to WidgetStatusIcon

* Updates to controlled input/checkbox

* VS Code workspace file added to gitignore

* shouldNotForwardTransientProp renamed to shouldForwardNonTransientProp

* AddAggregationButton defaultProps updates

* propTypes for TableInfoPopover added back
parent 5958d0ff
No related branches found
No related tags found
No related merge requests found
Showing
with 60 additions and 33 deletions
...@@ -80,3 +80,4 @@ dev/src/dev/nocommit/ ...@@ -80,3 +80,4 @@ dev/src/dev/nocommit/
.lsp/* .lsp/*
!.lsp/config.edn !.lsp/config.edn
.clj-kondo/.cache .clj-kondo/.cache
*.code-workspace
...@@ -10,7 +10,7 @@ import { ...@@ -10,7 +10,7 @@ import {
import { Container } from "./Collections.styled"; import { Container } from "./Collections.styled";
const propTypes = { const propTypes = {
collectionId: PropTypes.number, collectionId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
currentUserId: PropTypes.number, currentUserId: PropTypes.number,
handleToggleMobileSidebar: PropTypes.func.isRequired, handleToggleMobileSidebar: PropTypes.func.isRequired,
list: PropTypes.array, list: PropTypes.array,
......
...@@ -2,13 +2,13 @@ import React from "react"; ...@@ -2,13 +2,13 @@ import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { t } from "ttag"; import { t } from "ttag";
import * as Urls from "metabase/lib/urls"; import { newQuestion, newDashboard, newCollection } from "metabase/lib/urls";
import EntityMenu from "metabase/components/EntityMenu"; import EntityMenu from "metabase/components/EntityMenu";
import { ANALYTICS_CONTEXT } from "metabase/collections/constants"; import { ANALYTICS_CONTEXT } from "metabase/collections/constants";
const propTypes = { const propTypes = {
collection: PropTypes.func, collection: PropTypes.object,
list: PropTypes.arrayOf(PropTypes.object), list: PropTypes.arrayOf(PropTypes.object),
}; };
...@@ -17,19 +17,19 @@ function NewCollectionItemMenu({ collection }) { ...@@ -17,19 +17,19 @@ function NewCollectionItemMenu({ collection }) {
{ {
icon: "insight", icon: "insight",
title: t`Question`, title: t`Question`,
link: Urls.newQuestion({ mode: "notebook", collectionId: collection.id }), link: newQuestion({ mode: "notebook", collectionId: collection.id }),
event: `${ANALYTICS_CONTEXT};New Item Menu;Question Click`, event: `${ANALYTICS_CONTEXT};New Item Menu;Question Click`,
}, },
{ {
icon: "dashboard", icon: "dashboard",
title: t`Dashboard`, title: t`Dashboard`,
link: Urls.newDashboard(collection.id), link: newDashboard(collection.id),
event: `${ANALYTICS_CONTEXT};New Item Menu;Dashboard Click`, event: `${ANALYTICS_CONTEXT};New Item Menu;Dashboard Click`,
}, },
{ {
icon: "folder", icon: "folder",
title: t`Collection`, title: t`Collection`,
link: Urls.newCollection(collection.id), link: newCollection(collection.id),
event: `${ANALYTICS_CONTEXT};New Item Menu;Collection Click`, event: `${ANALYTICS_CONTEXT};New Item Menu;Collection Click`,
}, },
]; ];
......
export { default } from "./CollectionSidebar";
...@@ -45,7 +45,7 @@ function Badge({ ...@@ -45,7 +45,7 @@ function Badge({
activeColor={activeColor} activeColor={activeColor}
{...props} {...props}
> >
{icon && <BadgeIcon {...getIconProps(icon)} hasMargin={!!children} />} {icon && <BadgeIcon {...getIconProps(icon)} $hasMargin={!!children} />}
{children && <span className="text-wrap">{children}</span>} {children && <span className="text-wrap">{children}</span>}
</MaybeLink> </MaybeLink>
); );
......
...@@ -5,6 +5,7 @@ import { css } from "@emotion/react"; ...@@ -5,6 +5,7 @@ import { css } from "@emotion/react";
import { color } from "metabase/lib/colors"; import { color } from "metabase/lib/colors";
import Icon from "metabase/components/Icon"; import Icon from "metabase/components/Icon";
import Link from "metabase/core/components/Link"; import Link from "metabase/core/components/Link";
import { shouldForwardNonTransientProp } from "metabase/lib/styling/emotion";
const propTypes = { const propTypes = {
to: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), to: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
...@@ -33,6 +34,8 @@ export const MaybeLink = styled(RawMaybeLink)` ...@@ -33,6 +34,8 @@ export const MaybeLink = styled(RawMaybeLink)`
} }
`; `;
export const BadgeIcon = styled(Icon)` export const BadgeIcon = styled(Icon, {
margin-right: ${props => (props.hasMargin ? "5px" : 0)}; shouldForwardProp: shouldForwardNonTransientProp,
})`
margin-right: ${props => (props.$hasMargin ? "5px" : 0)};
`; `;
/* eslint-disable react/prop-types */ /* eslint-disable react/prop-types */
import React from "react"; import React, { Children } from "react";
import { import {
ButtonBarCenter, ButtonBarCenter,
ButtonBarLeft, ButtonBarLeft,
...@@ -12,6 +12,8 @@ function normalizeArray(array) { ...@@ -12,6 +12,8 @@ function normalizeArray(array) {
array = array.filter(a => a); array = array.filter(a => a);
if (array.length === 0) { if (array.length === 0) {
array = null; array = null;
} else {
array = Children.toArray(array);
} }
} }
return array; return array;
......
/* eslint-disable react/prop-types */ /* eslint-disable react/prop-types */
import React, { useState } from "react"; import React, { useState } from "react";
import * as Urls from "metabase/lib/urls"; import { extractCollectionId } from "metabase/lib/urls";
import { PageWrapper } from "metabase/collections/components/Layout"; import { PageWrapper } from "metabase/collections/components/Layout";
import CollectionContent from "metabase/collections/containers/CollectionContent"; import CollectionContent from "metabase/collections/containers/CollectionContent";
import CollectionSidebar from "metabase/collections/containers/CollectionSidebar/CollectionSidebar"; import CollectionSidebar from "metabase/collections/containers/CollectionSidebar";
import { ContentBox } from "./CollectionLanding.styled"; import { ContentBox } from "./CollectionLanding.styled";
const CollectionLanding = ({ params: { slug }, children }) => { const CollectionLanding = ({ params: { slug }, children }) => {
...@@ -16,7 +16,7 @@ const CollectionLanding = ({ params: { slug }, children }) => { ...@@ -16,7 +16,7 @@ const CollectionLanding = ({ params: { slug }, children }) => {
const handleToggleMobileSidebar = () => const handleToggleMobileSidebar = () =>
setShouldDisplayMobileSidebar(!shouldDisplayMobileSidebar); setShouldDisplayMobileSidebar(!shouldDisplayMobileSidebar);
const collectionId = Urls.extractCollectionId(slug); const collectionId = extractCollectionId(slug);
const isRoot = collectionId === "root"; const isRoot = collectionId === "root";
return ( return (
......
...@@ -7,6 +7,7 @@ import Tooltip from "metabase/components/Tooltip"; ...@@ -7,6 +7,7 @@ import Tooltip from "metabase/components/Tooltip";
import { loadIcon } from "metabase/icon_paths"; import { loadIcon } from "metabase/icon_paths";
import { color as c } from "metabase/lib/colors"; import { color as c } from "metabase/lib/colors";
import { stripLayoutProps } from "metabase/lib/utils"; import { stripLayoutProps } from "metabase/lib/utils";
import { shouldForwardNonTransientProp } from "metabase/lib/styling/emotion";
const MISSING_ICON_NAME = "unknown"; const MISSING_ICON_NAME = "unknown";
...@@ -28,7 +29,7 @@ export const IconWrapper = styled.div<IconWrapperProps>` ...@@ -28,7 +29,7 @@ export const IconWrapper = styled.div<IconWrapperProps>`
// special cases for certain icons // special cases for certain icons
// Icon-share has a taller viewbox than most so to optically center // Icon-share has a taller viewbox than most so to optically center
// the icon we need to translate it upwards // the icon we need to translate it upwards
"> .icon.icon-share": { & > .icon.icon-share {
transform: translateY(-2px); transform: translateY(-2px);
} }
${hover}; ${hover};
...@@ -115,7 +116,7 @@ class BaseIcon extends Component<IconProps> { ...@@ -115,7 +116,7 @@ class BaseIcon extends Component<IconProps> {
); );
} else if (icon.svg) { } else if (icon.svg) {
return ( return (
<svg <StyledSVG
{...svgProps} {...svgProps}
dangerouslySetInnerHTML={{ __html: icon.svg }} dangerouslySetInnerHTML={{ __html: icon.svg }}
ref={forwardedRef} ref={forwardedRef}
...@@ -123,9 +124,9 @@ class BaseIcon extends Component<IconProps> { ...@@ -123,9 +124,9 @@ class BaseIcon extends Component<IconProps> {
); );
} else if (icon.path) { } else if (icon.path) {
return ( return (
<svg {...svgProps} ref={forwardedRef}> <StyledSVG {...svgProps} ref={forwardedRef}>
<path d={icon.path} /> <path d={icon.path} />
</svg> </StyledSVG>
); );
} else { } else {
console.warn(`Icon "${name}" must have an img, svg, or path`); console.warn(`Icon "${name}" must have an img, svg, or path`);
...@@ -134,6 +135,10 @@ class BaseIcon extends Component<IconProps> { ...@@ -134,6 +135,10 @@ class BaseIcon extends Component<IconProps> {
} }
} }
const StyledSVG = styled("svg", {
shouldForwardProp: shouldForwardNonTransientProp,
})``;
const BaseIconWithRef = forwardRef<HTMLElement, IconProps>( const BaseIconWithRef = forwardRef<HTMLElement, IconProps>(
function BaseIconWithRef(props, ref) { function BaseIconWithRef(props, ref) {
return <BaseIcon {...props} forwardedRef={ref} />; return <BaseIcon {...props} forwardedRef={ref} />;
......
import React from "react"; import React, { ReactElement } from "react";
import PropTypes from "prop-types";
import { hideAll } from "tippy.js"; import { hideAll } from "tippy.js";
import TippyPopover, { import TippyPopover, {
...@@ -8,6 +7,7 @@ import TippyPopover, { ...@@ -8,6 +7,7 @@ import TippyPopover, {
import { isVirtualCardId } from "metabase/lib/saved-questions/saved-questions"; import { isVirtualCardId } from "metabase/lib/saved-questions/saved-questions";
import { WidthBoundTableInfo } from "./TableInfoPopover.styled"; import { WidthBoundTableInfo } from "./TableInfoPopover.styled";
import PropTypes from "prop-types";
export const POPOVER_DELAY: [number, number] = [500, 300]; export const POPOVER_DELAY: [number, number] = [500, 300];
...@@ -18,7 +18,7 @@ interface TableSubset { ...@@ -18,7 +18,7 @@ interface TableSubset {
const propTypes = { const propTypes = {
table: PropTypes.shape({ table: PropTypes.shape({
id: PropTypes.oneOf([PropTypes.number, PropTypes.string]), id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
description: PropTypes.string, description: PropTypes.string,
}).isRequired, }).isRequired,
children: PropTypes.node, children: PropTypes.node,
...@@ -26,10 +26,12 @@ const propTypes = { ...@@ -26,10 +26,12 @@ const propTypes = {
offset: PropTypes.arrayOf(PropTypes.number), offset: PropTypes.arrayOf(PropTypes.number),
}; };
type Props = { table: TableSubset } & Pick< type Props = {
ITippyPopoverProps, table: TableSubset;
"children" | "placement" | "offset" | "delay" children: ReactElement;
>; placement: string;
offset: number[];
} & Pick<ITippyPopoverProps, "children" | "placement" | "offset" | "delay">;
const className = "table-info-popover"; const className = "table-info-popover";
......
...@@ -495,6 +495,7 @@ export default class TokenField extends Component { ...@@ -495,6 +495,7 @@ export default class TokenField extends Component {
placeholder = null; placeholder = null;
} }
const isControlledInput = !!this.onInputChange;
const valuesList = ( const valuesList = (
<ul <ul
className={cx( className={cx(
...@@ -534,9 +535,10 @@ export default class TokenField extends Component { ...@@ -534,9 +535,10 @@ export default class TokenField extends Component {
// set size to be small enough that it fits in a parameter. // set size to be small enough that it fits in a parameter.
size={10} size={10}
placeholder={placeholder} placeholder={placeholder}
value={inputValue} value={isControlledInput ? inputValue : undefined}
defaultValue={isControlledInput ? undefined : inputValue}
onKeyDown={this.onInputKeyDown} onKeyDown={this.onInputKeyDown}
onChange={this.onInputChange} onChange={isControlledInput ? this.onInputChange : undefined}
onFocus={this.onInputFocus} onFocus={this.onInputFocus}
onBlur={this.onInputBlur} onBlur={this.onInputBlur}
onPaste={this.onInputPaste} onPaste={this.onInputPaste}
......
...@@ -54,15 +54,17 @@ const CheckBox = forwardRef(function Checkbox( ...@@ -54,15 +54,17 @@ const CheckBox = forwardRef(function Checkbox(
}: CheckBoxProps, }: CheckBoxProps,
ref: Ref<HTMLLabelElement>, ref: Ref<HTMLLabelElement>,
): JSX.Element { ): JSX.Element {
const isControlledCheckBoxInput = !!onChange;
return ( return (
<CheckBoxRoot ref={ref} {...props}> <CheckBoxRoot ref={ref} {...props}>
<CheckBoxInput <CheckBoxInput
type="checkbox" type="checkbox"
checked={checked} checked={isControlledCheckBoxInput ? !!checked : undefined}
defaultChecked={isControlledCheckBoxInput ? undefined : !!checked}
size={size} size={size}
disabled={disabled} disabled={disabled}
autoFocus={autoFocus} autoFocus={autoFocus}
onChange={onChange} onChange={isControlledCheckBoxInput ? onChange : undefined}
onFocus={onFocus} onFocus={onFocus}
onBlur={onBlur} onBlur={onBlur}
/> />
......
...@@ -2,8 +2,11 @@ import styled from "@emotion/styled"; ...@@ -2,8 +2,11 @@ import styled from "@emotion/styled";
import { display, space, hover, color } from "styled-system"; import { display, space, hover, color } from "styled-system";
import { Link } from "react-router"; import { Link } from "react-router";
import { color as colors } from "metabase/lib/colors"; import { color as colors } from "metabase/lib/colors";
import { shouldForwardNonTransientProp } from "metabase/lib/styling/emotion";
export const LinkRoot = styled(Link)` export const LinkRoot = styled(Link, {
shouldForwardProp: shouldForwardNonTransientProp,
})`
${display}; ${display};
${space}; ${space};
${hover}; ${hover};
......
import isPropValid from "@emotion/is-prop-valid";
export function shouldForwardNonTransientProp(propName: string): boolean {
return !propName.startsWith("$") && isPropValid(propName);
}
...@@ -181,7 +181,7 @@ export default class ParameterValueWidget extends Component { ...@@ -181,7 +181,7 @@ export default class ParameterValueWidget extends Component {
isFullscreen={isFullscreen} isFullscreen={isFullscreen}
hasValue={hasValue} hasValue={hasValue}
noReset={noReset} noReset={noReset}
noPopover={noPopover} noPopover={!!noPopover}
isFocused={isFocused} isFocused={isFocused}
setValue={setValue} setValue={setValue}
/> />
...@@ -216,7 +216,7 @@ export default class ParameterValueWidget extends Component { ...@@ -216,7 +216,7 @@ export default class ParameterValueWidget extends Component {
isFullscreen={isFullscreen} isFullscreen={isFullscreen}
hasValue={hasValue} hasValue={hasValue}
noReset={noReset} noReset={noReset}
noPopover={noPopover} noPopover={!!noPopover}
isFocused={isFocused} isFocused={isFocused}
setValue={setValue} setValue={setValue}
/> />
......
...@@ -17,7 +17,7 @@ const propTypes = { ...@@ -17,7 +17,7 @@ const propTypes = {
const LABEL = t`Add a metric`; const LABEL = t`Add a metric`;
export const AddAggregationButton = ({ query, shouldShowLabel }) => { export const AddAggregationButton = ({ query, shouldShowLabel = false }) => {
return ( return (
<PopoverWithTrigger <PopoverWithTrigger
triggerElement={ triggerElement={
......
...@@ -8,7 +8,7 @@ import { PLUGIN_COLLECTIONS } from "metabase/plugins"; ...@@ -8,7 +8,7 @@ import { PLUGIN_COLLECTIONS } from "metabase/plugins";
const propTypes = { const propTypes = {
collection: PropTypes.object, collection: PropTypes.object,
analyticsContext: PropTypes.string.isRequired, analyticsContext: PropTypes.string,
className: PropTypes.string, className: PropTypes.string,
}; };
...@@ -25,6 +25,7 @@ function CollectionBadge({ collection, analyticsContext, className }) { ...@@ -25,6 +25,7 @@ function CollectionBadge({ collection, analyticsContext, className }) {
if (!collection) { if (!collection) {
return null; return null;
} }
const isRegular = PLUGIN_COLLECTIONS.isRegularCollection(collection); const isRegular = PLUGIN_COLLECTIONS.isRegularCollection(collection);
const icon = { const icon = {
...collection.getIcon(), ...collection.getIcon(),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment