hugegraph-hubble/hubble-fe/src/components/graph-management/data-analyze/algorithm/LoopDetection.tsx (374 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with this * work for additional information regarding copyright ownership. The ASF * licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ import React, { useContext } from 'react'; import { observer } from 'mobx-react'; import { Button, Radio, Input, Select, Switch } from 'hubble-ui'; import { useTranslation } from 'react-i18next'; import { styles } from '../QueryAndAlgorithmLibrary'; import { Tooltip as CustomTooltip } from '../../../common'; import DataAnalyzeStore from '../../../../stores/GraphManagementStore/dataAnalyzeStore/dataAnalyzeStore'; import { Algorithm } from '../../../../stores/factory/dataAnalyzeStore/algorithmStore'; import { GraphManagementStoreContext } from '../../../../stores'; import { calcAlgorithmFormWidth } from '../../../../utils'; import QuestionMarkIcon from '../../../../assets/imgs/ic_question_mark.svg'; const LoopDetection = observer(() => { const graphManagementStore = useContext(GraphManagementStoreContext); const dataAnalyzeStore = useContext(DataAnalyzeStore); const algorithmAnalyzerStore = dataAnalyzeStore.algorithmAnalyzerStore; const { t } = useTranslation(); const formWidth = calcAlgorithmFormWidth( graphManagementStore.isExpanded, 340, 400 ); const isValidExec = Object.values( algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage ).every((value) => value === '') && algorithmAnalyzerStore.loopDetectionParams.source !== '' && algorithmAnalyzerStore.loopDetectionParams.max_depth !== ''; return ( <div className="query-tab-content-form"> <div className="query-tab-content-form-row"> <div className="query-tab-content-form-item"> <div className="query-tab-content-form-item-title"> <i>*</i> <span> {t('data-analyze.algorithm-forms.loop-detection.options.source')} </span> </div> <Input width={formWidth} size="medium" disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'} placeholder={t( 'data-analyze.algorithm-forms.loop-detection.placeholder.input-source-id' )} errorLocation="layer" errorMessage={ algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage .source } value={algorithmAnalyzerStore.loopDetectionParams.source} onChange={(e: any) => { algorithmAnalyzerStore.mutateLoopDetectionParams( 'source', e.value as string ); algorithmAnalyzerStore.validateLoopDetectionParams('source'); }} originInputProps={{ onBlur() { algorithmAnalyzerStore.validateLoopDetectionParams('source'); } }} /> </div> <div className="query-tab-content-form-item"> <div className="query-tab-content-form-item-title"> <span> {t('data-analyze.algorithm-forms.loop-detection.options.label')} </span> </div> <Select size="medium" trigger="click" value={algorithmAnalyzerStore.loopDetectionParams.label} notFoundContent={t( 'data-analyze.algorithm-forms.loop-detection.placeholder.no-edge-types' )} disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'} width={formWidth} onChange={(value: string) => { algorithmAnalyzerStore.mutateLoopDetectionParams('label', value); }} > <Select.Option value="__all__" key="__all__"> {t('data-analyze.algorithm-forms.loop-detection.pre-value')} </Select.Option> {dataAnalyzeStore.edgeTypes.map(({ name }) => ( <Select.Option value={name} key={name}> {name} </Select.Option> ))} </Select> </div> </div> <div className="query-tab-content-form-row"> <div className="query-tab-content-form-item"> <div className="query-tab-content-form-item-title"> <i>*</i> <span> {t( 'data-analyze.algorithm-forms.loop-detection.options.direction' )} </span> </div> <Radio.Group disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'} value={algorithmAnalyzerStore.loopDetectionParams.direction} onChange={(e: React.ChangeEvent<HTMLSelectElement>) => { algorithmAnalyzerStore.mutateLoopDetectionParams( 'direction', e.target.value ); }} > <Radio value="BOTH">both</Radio> <Radio value="OUT">out</Radio> <Radio value="IN">in</Radio> </Radio.Group> </div> <div className="query-tab-content-form-item"> <div className="query-tab-content-form-item-title"> <span> {t( 'data-analyze.algorithm-forms.loop-detection.options.max_degree' )} </span> <CustomTooltip trigger="hover" placement="bottom-start" modifiers={{ offset: { offset: '0, 8' } }} tooltipWrapperProps={{ className: 'tooltips-dark', style: { zIndex: 7 } }} tooltipWrapper={t( 'data-analyze.algorithm-forms.loop-detection.hint.max-degree' )} childrenProps={{ src: QuestionMarkIcon, alt: 'hint', style: { marginLeft: 5 } }} childrenWrapperElement="img" /> </div> <Input width={formWidth} size="medium" disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'} placeholder={t( 'data-analyze.algorithm-forms.loop-detection.placeholder.input-positive-integer-or-negative-one-max-degree' )} errorLocation="layer" errorMessage={ algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage .max_degree } value={algorithmAnalyzerStore.loopDetectionParams.max_degree} onChange={(e: any) => { algorithmAnalyzerStore.mutateLoopDetectionParams( 'max_degree', e.value as string ); algorithmAnalyzerStore.validateLoopDetectionParams('max_degree'); }} originInputProps={{ onBlur() { algorithmAnalyzerStore.validateLoopDetectionParams( 'max_degree' ); } }} /> </div> </div> <div className="query-tab-content-form-row"> <div className="query-tab-content-form-item"> <div className="query-tab-content-form-item-title"> <i>*</i> <span> {t( 'data-analyze.algorithm-forms.loop-detection.options.max_depth' )} </span> <CustomTooltip trigger="hover" placement="bottom-start" modifiers={{ offset: { offset: '0, 8' } }} tooltipWrapperProps={{ className: 'tooltips-dark', style: { zIndex: 7 } }} tooltipWrapper={t( 'data-analyze.algorithm-forms.loop-detection.hint.max-depth' )} childrenProps={{ src: QuestionMarkIcon, alt: 'hint', style: { marginLeft: 5 } }} childrenWrapperElement="img" /> </div> <Input width={formWidth} size="medium" disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'} placeholder={t( 'data-analyze.algorithm-forms.loop-detection.placeholder.input-positive-integer' )} errorLocation="layer" errorMessage={ algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage .max_depth } value={algorithmAnalyzerStore.loopDetectionParams.max_depth} onChange={(e: any) => { algorithmAnalyzerStore.mutateLoopDetectionParams( 'max_depth', e.value as string ); algorithmAnalyzerStore.validateLoopDetectionParams('max_depth'); }} originInputProps={{ onBlur() { algorithmAnalyzerStore.validateLoopDetectionParams('max_depth'); } }} /> </div> <div className="query-tab-content-form-item"> <div className="query-tab-content-form-item-title"> <span> {t('data-analyze.algorithm-forms.loop-detection.options.limit')} </span> </div> <Input width={formWidth} size="medium" disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'} placeholder={t( 'data-analyze.algorithm-forms.loop-detection.placeholder.input-positive-integer-or-negative-one-limit' )} errorLocation="layer" errorMessage={ algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage .limit } value={algorithmAnalyzerStore.loopDetectionParams.limit} onChange={(e: any) => { algorithmAnalyzerStore.mutateLoopDetectionParams( 'limit', e.value as string ); algorithmAnalyzerStore.validateLoopDetectionParams('limit'); }} originInputProps={{ onBlur() { algorithmAnalyzerStore.validateLoopDetectionParams('limit'); } }} /> </div> </div> <div className="query-tab-content-form-row"> <div className="query-tab-content-form-item"> <div className="query-tab-content-form-item-title"> <i>*</i> <span> {t( 'data-analyze.algorithm-forms.loop-detection.options.source_in_ring' )} </span> </div> <Switch size="medium" disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'} checked={algorithmAnalyzerStore.loopDetectionParams.source_in_ring} onChange={(checked: boolean) => { algorithmAnalyzerStore.mutateLoopDetectionParams( 'source_in_ring', checked ); }} /> </div> <div className="query-tab-content-form-item"> <div className="query-tab-content-form-item-title"> <span> {t( 'data-analyze.algorithm-forms.loop-detection.options.capacity' )} </span> </div> <Input width={formWidth} size="medium" disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'} placeholder={t( 'data-analyze.algorithm-forms.loop-detection.placeholder.input-positive-integer-or-negative-one-capacity' )} errorLocation="layer" errorMessage={ algorithmAnalyzerStore.validateLoopDetectionParamsErrorMessage .capacity } value={algorithmAnalyzerStore.loopDetectionParams.capacity} onChange={(e: any) => { algorithmAnalyzerStore.mutateLoopDetectionParams( 'capacity', e.value as string ); algorithmAnalyzerStore.validateLoopDetectionParams('capacity'); }} originInputProps={{ onBlur() { algorithmAnalyzerStore.validateLoopDetectionParams('capacity'); } }} /> </div> </div> <div className="query-tab-content-form-row" style={{ marginLeft: 92, justifyContent: 'flex-start' }} > <Button type="primary" style={styles.primaryButton} disabled={ !isValidExec || dataAnalyzeStore.requestStatus.fetchGraphs === 'pending' } onClick={async () => { algorithmAnalyzerStore.switchCollapse(true); dataAnalyzeStore.switchGraphLoaded(false); const timerId = dataAnalyzeStore.addTempExecLog(); await dataAnalyzeStore.fetchGraphs({ url: 'rings', type: Algorithm.loopDetection }); await dataAnalyzeStore.fetchExecutionLogs(); window.clearTimeout(timerId); }} > {t('data-analyze.manipulations.execution')} </Button> <Button style={styles.primaryButton} disabled={dataAnalyzeStore.requestStatus.fetchGraphs === 'pending'} onClick={() => { algorithmAnalyzerStore.resetLoopDetectionParams(); }} > {t('data-analyze.manipulations.reset')} </Button> </div> </div> ); }); export default LoopDetection;