mirror of
				https://github.com/open-metadata/OpenMetadata.git
				synced 2025-11-03 20:19:31 +00:00 
			
		
		
		
	add query builder widget ui improvements (#18389)
* add query builder improvements * fix alert flicker (cherry picked from commit c8e2ed0653ac8eaf44f3fbfc788a091aceeefc10)
This commit is contained in:
		
							parent
							
								
									4af077fbd6
								
							
						
					
					
						commit
						69dc6b4c38
					
				@ -12,12 +12,16 @@
 | 
			
		||||
 */
 | 
			
		||||
import React, { FC } from 'react';
 | 
			
		||||
import { AdvanceSearchProvider } from '../../components/Explore/AdvanceSearchProvider/AdvanceSearchProvider.component';
 | 
			
		||||
import { AdvanceSearchProviderProps } from '../Explore/AdvanceSearchProvider/AdvanceSearchProvider.interface';
 | 
			
		||||
 | 
			
		||||
export const withAdvanceSearch =
 | 
			
		||||
  <P extends Record<string, unknown>>(Component: FC<P>) =>
 | 
			
		||||
  <P extends Record<string, unknown>>(
 | 
			
		||||
    Component: FC<P>,
 | 
			
		||||
    providerProps?: Omit<AdvanceSearchProviderProps, 'children'>
 | 
			
		||||
  ) =>
 | 
			
		||||
  (props: P) => {
 | 
			
		||||
    return (
 | 
			
		||||
      <AdvanceSearchProvider>
 | 
			
		||||
      <AdvanceSearchProvider {...providerProps}>
 | 
			
		||||
        <Component {...props} />
 | 
			
		||||
      </AdvanceSearchProvider>
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,7 @@
 | 
			
		||||
 */
 | 
			
		||||
import { InfoCircleOutlined } from '@ant-design/icons';
 | 
			
		||||
import { WidgetProps } from '@rjsf/utils';
 | 
			
		||||
import { Alert, Button, Col, Typography } from 'antd';
 | 
			
		||||
import { Alert, Button, Card, Col, Row, Skeleton, Typography } from 'antd';
 | 
			
		||||
import { t } from 'i18next';
 | 
			
		||||
import { debounce, isEmpty, isUndefined } from 'lodash';
 | 
			
		||||
import Qs from 'qs';
 | 
			
		||||
@ -29,6 +29,7 @@ import { getExplorePath } from '../../../../../../constants/constants';
 | 
			
		||||
import { EntityType } from '../../../../../../enums/entity.enum';
 | 
			
		||||
import { SearchIndex } from '../../../../../../enums/search.enum';
 | 
			
		||||
import { searchQuery } from '../../../../../../rest/searchAPI';
 | 
			
		||||
import { elasticSearchFormat } from '../../../../../../utils/QueryBuilderElasticsearchFormatUtils';
 | 
			
		||||
import { getJsonTreeFromQueryFilter } from '../../../../../../utils/QueryBuilderUtils';
 | 
			
		||||
import searchClassBase from '../../../../../../utils/SearchClassBase';
 | 
			
		||||
import { withAdvanceSearch } from '../../../../../AppRouter/withAdvanceSearch';
 | 
			
		||||
@ -44,7 +45,8 @@ const QueryBuilderWidget: FC<WidgetProps> = ({
 | 
			
		||||
}: WidgetProps) => {
 | 
			
		||||
  const { config, treeInternal, onTreeUpdate, onChangeSearchIndex } =
 | 
			
		||||
    useAdvanceSearch();
 | 
			
		||||
  const [searchResults, setSearchResults] = useState<number>(0);
 | 
			
		||||
  const [searchResults, setSearchResults] = useState<number | undefined>();
 | 
			
		||||
  const [isCountLoading, setIsCountLoading] = useState<boolean>(false);
 | 
			
		||||
  const entityType =
 | 
			
		||||
    (props.formContext?.entityType ?? schema?.entityType) || EntityType.ALL;
 | 
			
		||||
  const searchIndexMapping = searchClassBase.getEntityTypeSearchIndexMapping();
 | 
			
		||||
@ -54,6 +56,7 @@ const QueryBuilderWidget: FC<WidgetProps> = ({
 | 
			
		||||
  const fetchEntityCount = useCallback(
 | 
			
		||||
    async (queryFilter: Record<string, unknown>) => {
 | 
			
		||||
      try {
 | 
			
		||||
        setIsCountLoading(true);
 | 
			
		||||
        const res = await searchQuery({
 | 
			
		||||
          query: '',
 | 
			
		||||
          pageNumber: 0,
 | 
			
		||||
@ -67,6 +70,8 @@ const QueryBuilderWidget: FC<WidgetProps> = ({
 | 
			
		||||
        setSearchResults(res.hits.total.value ?? 0);
 | 
			
		||||
      } catch (_) {
 | 
			
		||||
        // silent fail
 | 
			
		||||
      } finally {
 | 
			
		||||
        setIsCountLoading(false);
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    []
 | 
			
		||||
@ -85,11 +90,20 @@ const QueryBuilderWidget: FC<WidgetProps> = ({
 | 
			
		||||
    return `${getExplorePath({})}${queryFilterString}`;
 | 
			
		||||
  }, [treeInternal]);
 | 
			
		||||
 | 
			
		||||
  const showFilteredResourceCount = useMemo(
 | 
			
		||||
    () =>
 | 
			
		||||
      outputType === QueryBuilderOutputType.ELASTICSEARCH &&
 | 
			
		||||
      !isUndefined(value) &&
 | 
			
		||||
      searchResults !== undefined &&
 | 
			
		||||
      !isCountLoading,
 | 
			
		||||
    [outputType, value, isCountLoading]
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const handleChange = (nTree: ImmutableTree, nConfig: Config) => {
 | 
			
		||||
    onTreeUpdate(nTree, nConfig);
 | 
			
		||||
 | 
			
		||||
    if (outputType === QueryBuilderOutputType.ELASTICSEARCH) {
 | 
			
		||||
      const data = QbUtils.elasticSearchFormat(nTree, config) ?? {};
 | 
			
		||||
      const data = elasticSearchFormat(nTree, config) ?? {};
 | 
			
		||||
      const qFilter = {
 | 
			
		||||
        query: data,
 | 
			
		||||
      };
 | 
			
		||||
@ -109,17 +123,21 @@ const QueryBuilderWidget: FC<WidgetProps> = ({
 | 
			
		||||
  }, [searchIndex]);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (
 | 
			
		||||
      !isEmpty(value) &&
 | 
			
		||||
      outputType === QueryBuilderOutputType.ELASTICSEARCH
 | 
			
		||||
    ) {
 | 
			
		||||
      const tree = QbUtils.checkTree(
 | 
			
		||||
        QbUtils.loadTree(
 | 
			
		||||
          getJsonTreeFromQueryFilter(JSON.parse(value || '')) as JsonTree
 | 
			
		||||
        ),
 | 
			
		||||
        config
 | 
			
		||||
      );
 | 
			
		||||
      onTreeUpdate(tree, config);
 | 
			
		||||
    if (!isEmpty(value)) {
 | 
			
		||||
      if (outputType === QueryBuilderOutputType.ELASTICSEARCH) {
 | 
			
		||||
        const tree = QbUtils.checkTree(
 | 
			
		||||
          QbUtils.loadTree(
 | 
			
		||||
            getJsonTreeFromQueryFilter(JSON.parse(value || '')) as JsonTree
 | 
			
		||||
          ),
 | 
			
		||||
          config
 | 
			
		||||
        );
 | 
			
		||||
        onTreeUpdate(tree, config);
 | 
			
		||||
      } else {
 | 
			
		||||
        const tree = QbUtils.loadFromJsonLogic(JSON.parse(value || ''), config);
 | 
			
		||||
        if (tree) {
 | 
			
		||||
          onTreeUpdate(tree, config);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
@ -127,50 +145,66 @@ const QueryBuilderWidget: FC<WidgetProps> = ({
 | 
			
		||||
    <div
 | 
			
		||||
      className="query-builder-form-field"
 | 
			
		||||
      data-testid="query-builder-form-field">
 | 
			
		||||
      <Query
 | 
			
		||||
        {...config}
 | 
			
		||||
        renderBuilder={(props) => (
 | 
			
		||||
          <div className="query-builder-container query-builder qb-lite">
 | 
			
		||||
            <Builder {...props} />
 | 
			
		||||
          </div>
 | 
			
		||||
        )}
 | 
			
		||||
        value={treeInternal}
 | 
			
		||||
        onChange={handleChange}
 | 
			
		||||
      />
 | 
			
		||||
      {outputType === QueryBuilderOutputType.ELASTICSEARCH &&
 | 
			
		||||
        !isUndefined(value) && (
 | 
			
		||||
          <Col span={24}>
 | 
			
		||||
            <Button
 | 
			
		||||
              className="w-full p-0 text-left"
 | 
			
		||||
              data-testid="view-assets-banner-button"
 | 
			
		||||
              disabled={false}
 | 
			
		||||
              href={queryURL}
 | 
			
		||||
              target="_blank"
 | 
			
		||||
              type="link">
 | 
			
		||||
              <Alert
 | 
			
		||||
                closable
 | 
			
		||||
                showIcon
 | 
			
		||||
                icon={<InfoCircleOutlined height={16} />}
 | 
			
		||||
                message={
 | 
			
		||||
                  <div className="d-flex flex-wrap items-center gap-1">
 | 
			
		||||
                    <Typography.Text>
 | 
			
		||||
                      {t('message.search-entity-count', {
 | 
			
		||||
                        count: searchResults,
 | 
			
		||||
                      })}
 | 
			
		||||
                    </Typography.Text>
 | 
			
		||||
      <Card className="query-builder-card">
 | 
			
		||||
        <Row gutter={[8, 8]}>
 | 
			
		||||
          <Col className="p-t-sm" span={24}>
 | 
			
		||||
            <Query
 | 
			
		||||
              {...config}
 | 
			
		||||
              renderBuilder={(props) => (
 | 
			
		||||
                <div className="query-builder-container query-builder qb-lite">
 | 
			
		||||
                  <Builder {...props} />
 | 
			
		||||
                </div>
 | 
			
		||||
              )}
 | 
			
		||||
              value={treeInternal}
 | 
			
		||||
              onChange={handleChange}
 | 
			
		||||
            />
 | 
			
		||||
 | 
			
		||||
                    <Typography.Text className="text-xs text-grey-muted">
 | 
			
		||||
                      {t('message.click-here-to-view-assets-on-explore')}
 | 
			
		||||
                    </Typography.Text>
 | 
			
		||||
                  </div>
 | 
			
		||||
                }
 | 
			
		||||
                type="info"
 | 
			
		||||
            {isCountLoading && (
 | 
			
		||||
              <Skeleton
 | 
			
		||||
                active
 | 
			
		||||
                className="m-t-sm"
 | 
			
		||||
                loading={isCountLoading}
 | 
			
		||||
                paragraph={false}
 | 
			
		||||
                title={{ style: { height: '32px' } }}
 | 
			
		||||
              />
 | 
			
		||||
            </Button>
 | 
			
		||||
            )}
 | 
			
		||||
 | 
			
		||||
            {showFilteredResourceCount && (
 | 
			
		||||
              <div className="m-t-sm">
 | 
			
		||||
                <Button
 | 
			
		||||
                  className="w-full p-0 text-left h-auto"
 | 
			
		||||
                  data-testid="view-assets-banner-button"
 | 
			
		||||
                  disabled={false}
 | 
			
		||||
                  href={queryURL}
 | 
			
		||||
                  target="_blank"
 | 
			
		||||
                  type="link">
 | 
			
		||||
                  <Alert
 | 
			
		||||
                    closable
 | 
			
		||||
                    showIcon
 | 
			
		||||
                    icon={<InfoCircleOutlined height={16} />}
 | 
			
		||||
                    message={
 | 
			
		||||
                      <div className="d-flex flex-wrap items-center gap-1">
 | 
			
		||||
                        <Typography.Text>
 | 
			
		||||
                          {t('message.search-entity-count', {
 | 
			
		||||
                            count: searchResults,
 | 
			
		||||
                          })}
 | 
			
		||||
                        </Typography.Text>
 | 
			
		||||
 | 
			
		||||
                        <Typography.Text className="text-xs text-grey-muted">
 | 
			
		||||
                          {t('message.click-here-to-view-assets-on-explore')}
 | 
			
		||||
                        </Typography.Text>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    }
 | 
			
		||||
                    type="info"
 | 
			
		||||
                  />
 | 
			
		||||
                </Button>
 | 
			
		||||
              </div>
 | 
			
		||||
            )}
 | 
			
		||||
          </Col>
 | 
			
		||||
        )}
 | 
			
		||||
        </Row>
 | 
			
		||||
      </Card>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default withAdvanceSearch(QueryBuilderWidget);
 | 
			
		||||
export default withAdvanceSearch(QueryBuilderWidget, { isExplorePage: false });
 | 
			
		||||
 | 
			
		||||
@ -10,6 +10,22 @@
 | 
			
		||||
 *  See the License for the specific language governing permissions and
 | 
			
		||||
 *  limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@import (reference) url('../../../../../../styles/variables.less');
 | 
			
		||||
 | 
			
		||||
.query-builder-card {
 | 
			
		||||
  background-color: @grey-6;
 | 
			
		||||
 | 
			
		||||
  .ant-alert-info {
 | 
			
		||||
    background-color: @blue-8;
 | 
			
		||||
    border-color: @blue-7;
 | 
			
		||||
 | 
			
		||||
    .ant-alert-icon {
 | 
			
		||||
      color: @blue-7;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.query-builder-form-field {
 | 
			
		||||
  .hide--line.one--child {
 | 
			
		||||
    margin-top: 0;
 | 
			
		||||
@ -39,4 +55,125 @@
 | 
			
		||||
      margin-bottom: 6px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .query-builder-container {
 | 
			
		||||
    .group-or-rule-container.rule-container {
 | 
			
		||||
      padding: 0px;
 | 
			
		||||
 | 
			
		||||
      .rule.group-or-rule {
 | 
			
		||||
        .rule--header {
 | 
			
		||||
          .ant-btn-group {
 | 
			
		||||
            margin: 0px;
 | 
			
		||||
            align-self: flex-start;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .group-or-rule-container.group-container {
 | 
			
		||||
      padding: 0px;
 | 
			
		||||
 | 
			
		||||
      .group.rule_group {
 | 
			
		||||
        .group--field {
 | 
			
		||||
          margin: 0px;
 | 
			
		||||
          flex: 0 1 25%;
 | 
			
		||||
 | 
			
		||||
          .ant-select {
 | 
			
		||||
            min-width: 100% !important; // override the inline min-width style of the select provided by antd
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      & > .group.group-or-rule {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
 | 
			
		||||
        & > .group--header {
 | 
			
		||||
          order: 9999;
 | 
			
		||||
 | 
			
		||||
          .group--actions.group--actions--tr {
 | 
			
		||||
            justify-content: flex-start;
 | 
			
		||||
            margin: 0px;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .action.action--ADD-GROUP {
 | 
			
		||||
            display: none;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .rule-container .ant-btn-group {
 | 
			
		||||
            visibility: visible;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .action.action--ADD-RULE {
 | 
			
		||||
            position: static;
 | 
			
		||||
            margin-top: 8px;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .rule--body--wrapper {
 | 
			
		||||
          .rule--body {
 | 
			
		||||
            margin: 0px;
 | 
			
		||||
            display: flex;
 | 
			
		||||
            gap: 16px;
 | 
			
		||||
 | 
			
		||||
            .group--field,
 | 
			
		||||
            .rule--field,
 | 
			
		||||
            .rule--operator,
 | 
			
		||||
            .rule--value,
 | 
			
		||||
            .widget--widget {
 | 
			
		||||
              margin: 0px;
 | 
			
		||||
              flex: 1;
 | 
			
		||||
 | 
			
		||||
              .ant-col {
 | 
			
		||||
                padding: 0px !important; // remove padding from ant-col inline styling by antd
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .rule--operator,
 | 
			
		||||
            .rule--value .rule--widget {
 | 
			
		||||
              width: 100%;
 | 
			
		||||
 | 
			
		||||
              .ant-select {
 | 
			
		||||
                min-width: 100% !important; // override the inline min-width style of the select provided by antd
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      & > .group.group-or-rule.rule_group {
 | 
			
		||||
        flex-direction: row;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .group--children {
 | 
			
		||||
      padding: 0px;
 | 
			
		||||
      margin: 0px;
 | 
			
		||||
 | 
			
		||||
      .group-or-rule-container.group-container,
 | 
			
		||||
      .group-or-rule-container.rule-container {
 | 
			
		||||
        .group.group-or-rule,
 | 
			
		||||
        .rule.group-or-rule {
 | 
			
		||||
          background: inherit;
 | 
			
		||||
          padding: 0px;
 | 
			
		||||
          border: none;
 | 
			
		||||
 | 
			
		||||
          .group--header {
 | 
			
		||||
            .group--conjunctions {
 | 
			
		||||
              display: none;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          &:not(:first-child) {
 | 
			
		||||
            padding: 16px 8px;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .rule-container .ant-btn-group {
 | 
			
		||||
        visibility: visible;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -52,6 +52,8 @@
 | 
			
		||||
@blue-4: #f1f9ff;
 | 
			
		||||
@blue-5: #f2f6fc;
 | 
			
		||||
@blue-6: #eff5ff;
 | 
			
		||||
@blue-7: #3062d4;
 | 
			
		||||
@blue-8: #f5f8ff;
 | 
			
		||||
@partial-success-1: #06a4a4;
 | 
			
		||||
@partial-success-2: #bdeeee;
 | 
			
		||||
@black: #000000;
 | 
			
		||||
@ -112,9 +114,8 @@
 | 
			
		||||
 | 
			
		||||
// 172px - navbar height
 | 
			
		||||
@entity-details-tab-height: calc(100vh - 172px - @om-navbar-height);
 | 
			
		||||
@users-page-tabs-height: calc(
 | 
			
		||||
  100vh - @om-navbar-height - 58px
 | 
			
		||||
); /* navbar+tab_height+padding = 64+46+12  */
 | 
			
		||||
@users-page-tabs-height: calc(100vh - @om-navbar-height - 58px);
 | 
			
		||||
/* navbar+tab_height+padding = 64+46+12  */
 | 
			
		||||
 | 
			
		||||
// 142px - navbar height
 | 
			
		||||
@glossary-page-height: calc(100vh - 142px - @om-navbar-height);
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,7 @@ import { SearchIndex } from '../enums/search.enum';
 | 
			
		||||
import { getAggregateFieldOptions } from '../rest/miscAPI';
 | 
			
		||||
import { renderAdvanceSearchButtons } from './AdvancedSearchUtils';
 | 
			
		||||
import { getCombinedQueryFilterObject } from './ExplorePage/ExplorePageUtils';
 | 
			
		||||
import { renderQueryBuilderFilterButtons } from './QueryBuilderUtils';
 | 
			
		||||
 | 
			
		||||
class AdvancedSearchClassBase {
 | 
			
		||||
  baseConfig = AntdConfig as BasicConfig;
 | 
			
		||||
@ -408,7 +409,9 @@ class AdvancedSearchClassBase {
 | 
			
		||||
        operatorLabel: t('label.condition') + ':',
 | 
			
		||||
        showNot: false,
 | 
			
		||||
        valueLabel: t('label.criteria') + ':',
 | 
			
		||||
        renderButton: renderAdvanceSearchButtons,
 | 
			
		||||
        renderButton: isExplorePage
 | 
			
		||||
          ? renderAdvanceSearchButtons
 | 
			
		||||
          : renderQueryBuilderFilterButtons,
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,12 @@
 | 
			
		||||
 *  See the License for the specific language governing permissions and
 | 
			
		||||
 *  limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
import { CloseOutlined } from '@ant-design/icons';
 | 
			
		||||
import { Button } from 'antd';
 | 
			
		||||
import { t } from 'i18next';
 | 
			
		||||
import { isUndefined } from 'lodash';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { RenderSettings } from 'react-awesome-query-builder';
 | 
			
		||||
import {
 | 
			
		||||
  EsBoolQuery,
 | 
			
		||||
  EsExistsQuery,
 | 
			
		||||
@ -262,9 +267,7 @@ export const getJsonTreePropertyFromQueryFilter = (
 | 
			
		||||
          ...acc,
 | 
			
		||||
          ...getCommonFieldProperties(
 | 
			
		||||
            parentPath,
 | 
			
		||||
            Object.keys(
 | 
			
		||||
              (curr.bool?.must_not as EsWildCard)?.wildcard
 | 
			
		||||
            )[0] as string,
 | 
			
		||||
            Object.keys((curr.bool?.must_not as EsWildCard)?.wildcard)[0],
 | 
			
		||||
            'not_like',
 | 
			
		||||
            Object.values((curr.bool?.must_not as EsWildCard)?.wildcard)[0]
 | 
			
		||||
              ?.value
 | 
			
		||||
@ -311,3 +314,34 @@ export const getJsonTreeFromQueryFilter = (
 | 
			
		||||
    return {};
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const renderQueryBuilderFilterButtons: RenderSettings['renderButton'] = (
 | 
			
		||||
  props
 | 
			
		||||
) => {
 | 
			
		||||
  const type = props?.type;
 | 
			
		||||
 | 
			
		||||
  if (type === 'delRule') {
 | 
			
		||||
    return (
 | 
			
		||||
      <Button
 | 
			
		||||
        className="action action--DELETE"
 | 
			
		||||
        data-testid="delete-condition-button"
 | 
			
		||||
        icon={<CloseOutlined />}
 | 
			
		||||
        onClick={props?.onClick}
 | 
			
		||||
      />
 | 
			
		||||
    );
 | 
			
		||||
  } else if (type === 'addRule') {
 | 
			
		||||
    return (
 | 
			
		||||
      <Button
 | 
			
		||||
        className="action action--ADD-RULE"
 | 
			
		||||
        data-testid="add-condition-button"
 | 
			
		||||
        type="primary"
 | 
			
		||||
        onClick={props?.onClick}>
 | 
			
		||||
        {t('label.add-entity', {
 | 
			
		||||
          entity: t('label.condition'),
 | 
			
		||||
        })}
 | 
			
		||||
      </Button>
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return <></>;
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user