lodash#uniqueId TypeScript Examples

The following examples show how to use lodash#uniqueId. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: store.ts    From vue3-treeview with MIT License 6 votes vote down vote up
export function createState(props: ITreeProps): string {
    const { nodes, config } = toRefs(props);

    const state: IState = {
        id: uniqueId(),
        nodes: computed(() => nodes.value),
        config: computed(() => config.value),
        focusable: ref(null),
        focusFunc: new Map<string, Function>(),
        dragged: ref({
            node: null,
            element: null,
            wrapper: null,
            parentId: null
        }),
    };
    states.set(state.id, state);

    return state.id;
}
Example #2
Source File: index.ts    From querybook with Apache License 2.0 6 votes vote down vote up
/*
 *   @code {string} sql code we are parsing
 *   @code {string} mode analysis we are looking for, can either autocomplete or lint
 */
export function analyzeCode(
    code: string,
    mode = 'autocomplete',
    language = 'hive'
): Promise<ICodeAnalysis> {
    if (!sqlEditorWorker) {
        sqlEditorWorker = new Worker(
            new URL('./sql-editor.worker.ts', import.meta.url)
        );
        sqlEditorWorker.addEventListener(
            'message',
            (response) => {
                const { id, codeAnalysis } = JSON.parse(response.data);

                if (id in onCompletePromisesById) {
                    onCompletePromisesById[id](codeAnalysis);
                    delete onCompletePromisesById[id];
                }
            },
            false
        );
    }

    return new Promise((resolve, reject) => {
        const id = uniqueId('req');
        onCompletePromisesById[id] = resolve;

        sqlEditorWorker.postMessage({
            code,
            mode,
            id,
            language,
        });
    });
}
Example #3
Source File: Checkbox.tsx    From mysterium-vpn-desktop with MIT License 6 votes vote down vote up
Checkbox: React.FC<CheckboxProps> = ({ children, ...rest }) => {
    const inputId = uniqueId("checkbox")
    return (
        <Container>
            <Input id={inputId} type="checkbox" {...rest} />
            <Label htmlFor={inputId}>{children}</Label>
        </Container>
    )
}
Example #4
Source File: InjectRandomIds.ts    From gio-design with Apache License 2.0 6 votes vote down vote up
/**
 * 解决 SVG 组件 ID 重复问题的高阶组件
 * @param Component 需要传入的 SVG 组件
 * @returns 注入随机 ID 后的 SVG 组件
 */
export default function InjectRandomIds<P>(
  Component: ComponentType<P>
): ComponentType<P & RefAttributes<SVGSVGElement>> {
  return function WrapperComponent(props) {
    const componentRef = useRef<SVGSVGElement>();
    useLayoutEffect(() => {
      if (!componentRef.current) return;
      const elementsWithId = componentRef.current.querySelectorAll('svg [id]');
      const elementsWithFill = componentRef.current.querySelectorAll('svg [fill^=url\\(\\#]');
      elementsWithId.forEach((element) => {
        const id = element.getAttribute('id');
        const elementsWithFillSameId = filter(elementsWithFill, (item) => item.getAttribute('fill') === `url(#${id})`);
        elementsWithFillSameId.forEach((node) => {
          if (node) {
            const newId = `${id}__${uniqueId()}`;
            element.setAttribute('id', newId);
            node.setAttribute('fill', `url(#${newId})`);
          }
        });
      });
    }, []);
    return React.createElement(Component, { ...props, ref: componentRef });
  };
}
Example #5
Source File: pipeline-node.tsx    From erda-ui with GNU Affero General Public License v3.0 6 votes vote down vote up
renderObject = (dataSource: object) => {
  return map(dataSource, (value: any, key: string) => {
    const type = value instanceof Array ? 'array' : typeof value;
    let isObject = false;
    if (type === 'array' && (!value || (value && value.length === 0))) {
      return null;
    } else if (!value && value !== '') {
      return null;
    }

    switch (type) {
      case 'array':
      case 'object':
        isObject = true;
        break;
      default:
        break;
    }
    return (
      <div key={uniqueId(`pv-obj-${key}`)}>
        <span className={isObject ? 'object-key' : ''}>{i18nMap[key] || key}: </span>
        <span className={isObject ? 'object-value' : ''}>{renderDataSource(value)}</span>
      </div>
    );
  });
}
Example #6
Source File: BrickTree.tsx    From next-basics with GNU General Public License v3.0 6 votes vote down vote up
function getTreeNodes(list: BrickTreeNodeProps[]): DataNode[] {
  return list.map((item) => {
    const { children, icon: _icon, key, ...itemProps } = item;
    let icon: React.ReactNode;

    if (_icon) {
      if (isMenuIcon(_icon)) {
        icon = <GeneralIcon icon={_icon} />;
      } else {
        icon = <Icon component={_icon} />;
      }
    }

    return {
      ...itemProps,
      icon,
      key: key ?? uniqueId("tree-node-"),
      children: children && getTreeNodes(children),
    };
  });
}
Example #7
Source File: Uploader.ts    From easy-email with MIT License 6 votes vote down vote up
public async uploadFiles(files: File[]) {
    const results = files.map((file) => ({ file }));
    const uploadList: UploadItem[] = results.map((item) => ({
      url: '',
      status: 'pending',
      idx: `uploader-${uniqueId()}`,
    }));

    // 开始上传
    this.handler.start.map((fn) => fn(uploadList));

    await PromiseEach(
      results.map(async (file, index) => {
        try {
          const url = await this.uploadFile(file);
          uploadList[index].url = url;
          uploadList[index].status = 'done';
        } catch (error) {
          uploadList[index].status = 'error';
        } finally {
          this.handler.progress.map((fn) => fn(uploadList));
        }
      })
    );

    // 上传完成
    this.handler.end.map((fn) => fn(uploadList));
  }
Example #8
Source File: manifest.ts    From ow-mod-manager with MIT License 6 votes vote down vote up
export function manifestPartialToFull(partialManifest: Partial<Manifest>) {
  const missingAttributes: string[] = [];

  function getAttribute(key: keyof Manifest, isUnique?: boolean): string {
    const value = partialManifest[key];
    if (value) {
      return value as string;
    }
    missingAttributes.push(key);
    return `[Missing ${key}]${isUnique ? uniqueId() : ''}`;
  }

  const manifest: Manifest = {
    name: getAttribute('name'),
    author: getAttribute('author'),
    uniqueName: getAttribute('uniqueName', true),
    version: getAttribute('version'),
    dependencies: partialManifest.dependencies ?? [],
    warning: partialManifest.warning,
    patcher: partialManifest.patcher,
    conflicts: partialManifest.conflicts,
    pathsToPreserve: partialManifest.pathsToPreserve,
  };

  return {
    manifest,
    missingAttributes,
  };
}
Example #9
Source File: UploadImg.tsx    From next-basics with GNU General Public License v3.0 6 votes vote down vote up
export function transformToImageList(value: UploadImgValue): ImageItem[] {
  let imageList: ImageItem[] = [];

  if (value?.images) {
    imageList = map(cloneDeep(value.images), (img) => {
      img.uid = img.uid ?? uniqueId("-img");
      return img;
    });
  }
  return imageList;
}
Example #10
Source File: property-view.tsx    From erda-ui with GNU Affero General Public License v3.0 5 votes vote down vote up
private renderArray(dataSource: object) {
    return map(dataSource, (value: any, key: string) => {
      return <div key={uniqueId(`pv-array-${key}`)}>{this.renderDataSource(value)}</div>;
    });
  }
Example #11
Source File: Cascader.stories.tsx    From gio-design with Apache License 2.0 5 votes vote down vote up
defaultOptions = [
  {
    label: '苹果',
    value: 'apple',
    id: uniqueId(),
    description: uniqueId(),
    items: [
      {
        label: '切',
        value: 'cut',
        id: uniqueId(),
        description: uniqueId(),
        items: [
          {
            label: '坏了',
            value: 'bad',
            id: uniqueId(),
            description: uniqueId(),
          },
          {
            label: '没坏',
            value: 'good',
            id: uniqueId(),
          },
        ],
      },
      {
        label: '掰开',
        value: 'bye',
        id: uniqueId(),
        items: [
          {
            label: '坏了',
            value: 'bad',
            id: uniqueId(),
          },
          {
            label: '没坏',
            value: 'good',
            id: uniqueId(),
          },
        ],
      },
    ],
  },
]
Example #12
Source File: pipeline-node.tsx    From erda-ui with GNU Affero General Public License v3.0 5 votes vote down vote up
renderValue = (value: any) => {
  return <span key={uniqueId(`pv-v-${value}`)}>{value}</span>;
}
Example #13
Source File: index.tsx    From next-basics with GNU General Public License v3.0 5 votes vote down vote up
private _id = uniqueId("foldBrickButton");
Example #14
Source File: useUniqueKeyState.ts    From jitsu with MIT License 5 votes vote down vote up
useUniqueKeyState = (idPrefix?: string): [string, () => void] => {
  const [state, setState] = useState(uniqueId(idPrefix))
  const handleGenerateNewState = useCallback<() => void>(() => {
    setState(uniqueId(idPrefix))
  }, [])
  return [state, handleGenerateNewState]
}
Example #15
Source File: add-modal.tsx    From erda-ui with GNU Affero General Public License v3.0 5 votes vote down vote up
convertFormData = (_formData?: Obj) => {
  if (_formData) {
    const handleContent = [];
    const qsContent = qs.parse(_formData?.config?.body?.content);
    for (const [key, val] of Object.entries(qsContent)) {
      handleContent.push({
        _tb_key: key,
        _tb_value: val?.toString(),
        uniKey: uniqueId(),
      });
    }

    return {
      retry: _formData.config?.retry || 2,
      bodyType:
        _formData.config?.body?.type === jsonType || _formData.config?.body?.type === textType
          ? raw
          : _formData.config?.body?.type,
      frequency: _formData.config?.interval || TIME_LIMITS[0],
      apiMethod: _formData.config?.method || HTTP_METHOD_LIST[0],
      body:
        _formData.config?.body?.type === formType
          ? { ..._formData.config?.body, content: handleContent }
          : _formData.config?.body || {
              content: '',
              type: noneType,
            },
      headers: _formData.config?.headers || {},
      url: _formData.config?.url || '',
      query: qs.parseUrl(_formData.config?.url || '')?.query,
      condition: _formData.config?.triggering || [
        {
          key: 'http_code',
          operate: '>=',
          value: 400,
        },
      ],
      textOrJson: convertType(_formData.config?.body?.type),
    };
  } else {
    return {
      condition: [
        {
          key: 'http_code',
          operate: '>=',
          value: 400,
        },
      ],
      showMore: false,
      query: {},
      retry: 2,
      frequency: TIME_LIMITS[0],
      apiMethod: HTTP_METHOD_LIST[0],
      body: { content: '', type: 'none' },
      headers: {},
      url: '',
      textOrJson: 'text',
      bodyType: 'none',
    };
  }
}
Example #16
Source File: DraggableList.tsx    From querybook with Apache License 2.0 5 votes vote down vote up
export function DraggableList<T extends { id: any }>({
    renderItem,
    items,
    onMove,
    className,
    canDrop,

    itemType,
}: IDraggableListProps<T>) {
    const [hoverItemsVersion, resetHoverItemsVersion] = useState(0);
    const draggableItemType = useMemo(
        () => itemType ?? uniqueId('DraggableItem'),
        [itemType]
    );

    const [hoverItems, setHoverItems] = useState(items);

    const handleHoverMove = useCallback(
        (fromIndex: number, toIndex: number) => {
            setHoverItems((oldHoverItems) =>
                arrayMove(oldHoverItems, fromIndex, toIndex)
            );
        },
        []
    );

    useEffect(() => {
        setHoverItems(items);
    }, [items, hoverItemsVersion]);

    const resetHoverItems = useCallback(() => {
        resetHoverItemsVersion((v) => v + 1);
    }, []);

    const idToOriginalIndex = useMemo(
        () =>
            items.reduce((hash, item, idx) => {
                hash[item.id] = idx;
                return hash;
            }, {}),
        [items]
    );

    const renderedChildren = hoverItems.map((itemProps, idx) => (
        <DraggableItem
            key={itemProps.id}
            onHoverMove={handleHoverMove}
            onMove={onMove}
            index={idx}
            originalIndex={idToOriginalIndex[itemProps.id]}
            draggableItemType={draggableItemType}
            itemInfo={itemProps}
            canDrop={canDrop}
            resetHoverItems={resetHoverItems}
        >
            {renderItem(idx, itemProps)}
        </DraggableItem>
    ));
    return (
        <ul className={'DraggableList ' + (className ?? '')}>
            {renderedChildren}
        </ul>
    );
}
Example #17
Source File: EventStreamGraph.tsx    From next-basics with GNU General Public License v3.0 5 votes vote down vote up
constructor(options?: {
    onEventNodeClick?: (eventNode: EventStreamNode) => void;
  }) {
    this.onEventNodeClick = options?.onEventNodeClick;
    this.canvas = create("div").attr("class", styles.canvas);
    this.linksLayer = this.canvas
      .append("svg")
      .attr("class", styles.linksLayer)
      .style("overflow", "visible");
    this.nodesLayer = this.canvas
      .append("div")
      .attr("class", styles.nodesLayer);
    this.defs = this.linksLayer.append("defs");
    this.arrowMarkerId = uniqueId("arrow-");
    this.defs
      .append("marker")
      .attr("id", this.arrowMarkerId)
      .attr("class", styles.arrowMarker)
      .attr("viewBox", "0 0 10 10")
      .attr("refX", 5)
      .attr("refY", 5)
      .attr("markerWidth", 10)
      .attr("markerHeight", 10)
      .attr("orient", "auto")
      .append("path")
      .attr("d", "M 0 0 L 10 5 L 0 10 z");
    this.linksContainer = this.linksLayer.append("g");
    this.links = this.linksContainer.selectAll("g");
    this.nodesContainer = this.nodesLayer
      .append("div")
      .attr("class", styles.nodesContainer);
    this.nodes = this.nodesContainer.selectAll(`.${styles.nodeWrapper}`);

    this.canvas.call(
      drag<HTMLDivElement, any>()
        .on("start", () => {
          this.canvas.classed(styles.grabbing, true);
        })
        .on("drag", (event: D3DragEvent<HTMLDivElement, unknown, unknown>) => {
          const { dx, dy } = event;
          this.transform(-dx, -dy);
        })
        .on("end", () => {
          this.canvas.classed(styles.grabbing, false);
        })
    );

    this.canvas
      .on("wheel", function (event: WheelEvent) {
        event.preventDefault();
      })
      .on("wheel.zoom", (event: WheelEvent) => {
        event.stopPropagation();
        const { deltaX, deltaY, ctrlKey } = event;
        // macOS trackPad pinch event is emitted as a wheel.zoom and event.ctrlKey set to true
        if (ctrlKey) {
          return;
        }
        this.transform(deltaX, deltaY);
      });
  }
Example #18
Source File: index.tsx    From erda-ui with GNU Affero General Public License v3.0 5 votes vote down vote up
convertToColumnData = (data?: object): IItemData[] => {
  return map(data, (v, k) => {
    return { [ROW_KEY]: String(k).trim(), [ROW_VALUE]: String(v).trim(), uniKey: uniqueId() };
  });
}
Example #19
Source File: CustomTemplateContext.ts    From next-core with GNU General Public License v3.0 5 votes vote down vote up
readonly id = uniqueId("tpl-ctx-");
Example #20
Source File: PresentCheck.tsx    From pancake-toolkit with GNU General Public License v3.0 5 votes vote down vote up
Icon: React.FC<SvgProps> = (props) => {
  const id = uniqueId("svg");

  return (
    <Svg viewBox="0 0 64 64" {...props}>
      <g clipPath={`url(#${id})`}>
        <g opacity="0.5">
          <path
            fillRule="evenodd"
            clipRule="evenodd"
            d="M22.9614 22.6577C22.1497 21.837 20.8799 22.1545 20.6502 23.2356C20.4793 24.0399 20.9887 24.8972 21.775 25.1283L26.8237 26.6119L25.8006 25.5283L22.9614 22.6577ZM17.0022 22.0363C17.8377 18.1041 22.4563 16.9493 25.4089 19.9345L28.2841 22.8415L34.1925 29.0996L28.1494 30.7189C27.8283 30.8049 27.4835 30.7985 27.1491 30.7002L21.0935 28.9207C18.2337 28.0803 16.3806 24.9621 17.0022 22.0363Z"
            fill="#7A6EAA"
          />
          <path
            fillRule="evenodd"
            clipRule="evenodd"
            d="M34.5943 19.5405C34.887 18.4239 36.1454 18.064 36.8848 18.8854C37.435 19.4965 37.4224 20.4937 36.8571 21.0869L33.2266 24.8961L33.5708 23.4462L34.5943 19.5405ZM39.4444 16.0228C36.7547 13.0352 32.1775 14.3444 31.1131 18.4059L30.0766 22.3611L28.0888 30.735L34.132 29.1157C34.4531 29.0297 34.7485 28.8517 34.989 28.5994L39.3434 24.0306C41.3999 21.8728 41.4456 18.2458 39.4444 16.0228Z"
            fill="#7A6EAA"
          />
          <path
            fillRule="evenodd"
            clipRule="evenodd"
            d="M19.4563 42.0674L47.2386 34.6231L50.6382 47.3106C51.0042 48.6763 50.1937 50.08 48.828 50.4459L25.9913 56.565C24.6256 56.9309 23.2219 56.1205 22.8559 54.7548L19.4563 42.0674ZM49.0488 31.4878L53.111 46.648C53.8429 49.3793 52.222 52.1868 49.4906 52.9187L26.6538 59.0378C23.9225 59.7696 21.115 58.1487 20.3832 55.4174L16.321 40.2572L49.0488 31.4878Z"
            fill="#7A6EAA"
          />
          <path d="M36.1074 37.606L30.6528 39.0675L35.3736 56.686L40.8283 55.2244L36.1074 37.606Z" fill="#7A6EAA" />
          <path d="M17.9272 46.1213L19.5837 52.3033L52.3115 43.5339L50.6551 37.3519L17.9272 46.1213Z" fill="#7A6EAA" />
          <path
            fillRule="evenodd"
            clipRule="evenodd"
            d="M16.2885 33.8966L45.9617 25.9456C46.6446 25.7627 47.3464 26.1679 47.5294 26.8507L48.4404 30.2508C48.6234 30.9336 48.2182 31.6355 47.5353 31.8185L17.8621 39.7694C17.1793 39.9524 16.4774 39.5471 16.2944 38.8643L15.3834 35.4642C15.2004 34.7814 15.6056 34.0795 16.2885 33.8966ZM45.2991 23.4729C47.3477 22.924 49.4533 24.1396 50.0022 26.1882L50.9132 29.5882C51.4621 31.6367 50.2464 33.7423 48.1979 34.2912L18.5247 42.2422C16.4762 42.7911 14.3706 41.5754 13.8217 39.5269L12.9106 36.1268C12.3617 34.0783 13.5774 31.9727 15.6259 31.4238L45.2991 23.4729Z"
            fill="#7A6EAA"
          />
          <path d="M33.2085 26.7876L27.7539 28.2492L30.6526 39.0675L36.1073 37.606L33.2085 26.7876Z" fill="#7A6EAA" />
          <path
            d="M47.6246 14.7703V14.3912C47.6246 13.8593 47.731 13.4137 47.9437 13.0547C48.1698 12.6956 48.4691 12.3431 48.8414 11.9974C49.1872 11.6649 49.5264 11.379 49.8588 11.1396C50.1913 10.9002 50.464 10.6475 50.6767 10.3815C50.8895 10.1155 50.9959 9.80299 50.9959 9.44391C50.9959 8.92524 50.8097 8.55951 50.4374 8.34672C50.0783 8.12063 49.4732 8.00759 48.622 8.00759C48.0634 8.00759 47.5115 8.08073 46.9662 8.22703C46.421 8.36002 45.9555 8.53291 45.5698 8.7457V6.05259C46.0619 5.81321 46.6404 5.62037 47.3054 5.47408C47.9836 5.32778 48.7217 5.25464 49.5197 5.25464C51.0624 5.25464 52.2394 5.59377 53.0507 6.27203C53.8619 6.937 54.2675 7.85465 54.2675 9.02498C54.2675 9.76974 54.1146 10.3749 53.8087 10.8403C53.5028 11.2925 53.0573 11.758 52.4721 12.2368C51.9801 12.649 51.5678 13.0081 51.2353 13.314C50.9028 13.6066 50.7366 14.0056 50.7366 14.5109V14.7703L47.6246 14.7703ZM47.4849 18.3012V15.9871L50.8563 15.9871V18.3012L47.4849 18.3012Z"
            fill="#7A6EAA"
          />
          <path
            d="M10.6586 50.2406L10.5388 50.0331C10.3706 49.7418 10.2881 49.4643 10.291 49.2004C10.3013 48.9324 10.3538 48.6448 10.4483 48.3378C10.5325 48.0465 10.6278 47.7827 10.7342 47.5466C10.8405 47.3104 10.9099 47.0859 10.9424 46.873C10.9748 46.6602 10.9342 46.4554 10.8207 46.2588C10.6568 45.9749 10.4393 45.8335 10.1681 45.8347C9.90008 45.8244 9.53305 45.9538 9.06706 46.2228C8.76126 46.3994 8.48221 46.6139 8.22993 46.8664C7.97344 47.1115 7.77325 47.3533 7.62936 47.5917L6.7781 46.1173C6.97184 45.8307 7.22761 45.5422 7.54542 45.252C7.87052 44.9575 8.2515 44.6841 8.68836 44.4319C9.53297 43.9443 10.2845 43.7579 10.9431 43.8728C11.5974 43.9804 12.1095 44.3546 12.4795 44.9954C12.7149 45.4031 12.8224 45.7827 12.8021 46.1343C12.7776 46.4785 12.6808 46.8742 12.5117 47.3213C12.3726 47.7025 12.2604 48.0294 12.1751 48.302C12.0855 48.5672 12.1206 48.8382 12.2804 49.1149L12.3624 49.2569L10.6586 50.2406ZM11.6982 52.2178L10.9668 50.9509L12.8125 49.8853L13.544 51.1522L11.6982 52.2178Z"
            fill="#7A6EAA"
          />
          <path
            d="M8.75569 24.6564L8.59567 24.3793C8.37108 23.9903 8.26079 23.6196 8.26479 23.2672C8.27852 22.9091 8.34854 22.5251 8.47485 22.115C8.58734 21.7259 8.71461 21.3737 8.85667 21.0582C8.99873 20.7428 9.09141 20.4429 9.13471 20.1586C9.17802 19.8743 9.12387 19.6008 8.97227 19.3382C8.7533 18.959 8.46275 18.7701 8.10061 18.7717C7.74259 18.758 7.25237 18.9308 6.62997 19.2902C6.22152 19.526 5.84882 19.8125 5.51186 20.1497C5.16928 20.4771 4.90189 20.8001 4.70971 21.1185L3.57272 19.1492C3.83148 18.7664 4.17311 18.3811 4.59759 17.9934C5.03181 17.6001 5.54066 17.235 6.12416 16.8981C7.25226 16.2468 8.2561 15.9979 9.13567 16.1514C10.0096 16.2951 10.6937 16.7949 11.1878 17.6507C11.5022 18.1953 11.6458 18.7023 11.6187 19.1718C11.5859 19.6316 11.4566 20.1601 11.2308 20.7573C11.0451 21.2665 10.8952 21.7031 10.7812 22.0671C10.6616 22.4215 10.7085 22.7834 10.9218 23.1529L11.0313 23.3426L8.75569 24.6564ZM10.1443 27.2974L9.16732 25.6052L11.6326 24.1819L12.6096 25.874L10.1443 27.2974Z"
            fill="#7A6EAA"
          />
        </g>
      </g>
      <defs>
        <clipPath id="clip_present_0">
          <rect width="64" height="64" fill="white" />
        </clipPath>
      </defs>
    </Svg>
  );
}
Example #21
Source File: UploadFilesV2.tsx    From next-basics with GNU General Public License v3.0 5 votes vote down vote up
export function addUid(value: UploadFileValueItem[]): FileItem[] {
  let fileList: FileItem[] = [];
  fileList = map(value, (file) => {
    file.uid = file.uid ?? uniqueId("-file");
    return file;
  });
  return fileList;
}
Example #22
Source File: utils.tsx    From erda-ui with GNU Affero General Public License v3.0 5 votes vote down vote up
transformConfigRecursively = (fieldsConfig: Field[], componentMap: Map<CT, string>) => {
  const propertiesArray: SchemaField[] = map(fieldsConfig, (item) => {
    const {
      name,
      title,
      label,
      type = 'string',
      customProps,
      wrapperProps,
      defaultValue,
      component,
      required,
      validator,
      items,
      gridConfig,
      layoutConfig,
      display,
      valuePropName,
      noPropertyLayoutWrapper = false,
      componentName: _componentName,
      properties: fieldProperties,
    } = item;

    let componentName = '';
    if (componentMap.has(component)) {
      componentName = componentMap.get(component)!;
    } else {
      componentName = _componentName ?? uniqueId('component-');
      if (valuePropName) {
        componentMap.set(connect(component, mapProps({ value: valuePropName })), componentName);
      } else {
        componentMap.set(component, componentName);
      }
    }

    let _items = {}; // for array fields
    if (items) {
      const _properties = transformConfigRecursively(items, componentMap);
      _items = {
        type: 'object',
        properties: {
          layout: {
            type: 'void',
            'x-component': 'FormLayout',
            'x-component-props': { ...defaultLayoutConfig, ...layoutConfig },
            properties: {
              grid: {
                type: 'void',
                'x-component': 'FormGrid',
                'x-component-props': {
                  maxColumns: gridConfig?.minColumns ? gridConfig.minColumns : 1,
                  ...gridConfig,
                },
                properties: _properties,
              },
            },
          },
        },
      };
    }

    let _properties;
    if (fieldProperties) {
      _properties = transformConfigRecursively(fieldProperties, componentMap);
      if (!noPropertyLayoutWrapper) {
        _properties = {
          layout: {
            type: 'void',
            'x-component': 'FormLayout',
            'x-component-props': { ...defaultLayoutConfig, ...layoutConfig },
            properties: {
              grid: {
                type: 'void',
                'x-component': 'FormGrid',
                'x-component-props': {
                  maxColumns: gridConfig?.minColumns ? gridConfig.minColumns : 1,
                  ...gridConfig,
                },
                properties: _properties,
              },
            },
          },
        };
      }
    }

    return {
      name,
      title: title ?? label,
      type,
      required,
      items: _properties ? undefined : _items,
      default: defaultValue,
      'x-validator': validator,
      'x-decorator': _properties ? undefined : 'FormItem',
      'x-component': componentName,
      'x-component-props': customProps,
      'x-display': display,
      'x-decorator-props': _properties ? { ...wrapperProps } : { colon: false, ...wrapperProps },
      properties: _properties,
    };
  });

  const properties = reduce(
    propertiesArray,
    (acc, item) => {
      const { name, ...rest } = item;
      acc[name] = rest;
      return acc;
    },
    {} as Obj<Omit<SchemaField, 'name'>>,
  );
  return properties as Obj<Omit<SchemaField, 'name'>>;
}
Example #23
Source File: SourceEditorFormConfigurationConfigurableLoadableFields.tsx    From jitsu with MIT License 4 votes vote down vote up
SourceEditorFormConfigurationConfigurableLoadableFields: React.FC<Props> = memo(
  ({
    editorMode,
    initialValues,
    sourceDataFromCatalog,
    hideFields: _hideFields,
    patchConfig,
    handleSetControlsDisabled,
    handleSetTabsDisabled,
    setValidator,
    setFormReference,
    handleResetOauth,
    handleReloadStreams,
  }) => {
    const [form] = Form.useForm()
    const [availableAirbyteImageVersions, setAvailableAirbyteImageVersions] = useState<string[]>([])
    const airbyteImageVersion = useRef<string>(initialValues?.config?.image_version ?? "")

    const {
      isLoading: isLoadingParameters,
      data: fieldsParameters,
      error: loadingParametersError,
      reload: reloadParameters,
    } = usePolling<Parameter[]>(
      {
        configure: () => {
          const controlsDisableRequestId = uniqueId("configurableLoadableFields-")
          const imageVersion: string = airbyteImageVersion.current
          let availableImageVersions: string[] = []
          return {
            onBeforePollingStart: async () => {
              handleSetControlsDisabled(true, controlsDisableRequestId)
              editorMode === "edit" && handleSetTabsDisabled(["streams"], "disable")
              availableImageVersions = (await pullAvailableAirbyteImageVersions(sourceDataFromCatalog.id)) || []
              setAvailableAirbyteImageVersions(availableImageVersions)
            },
            pollingCallback: (end, fail) => async () => {
              try {
                const response = await pullAirbyteSpec(
                  sourceDataFromCatalog.id,
                  imageVersion || availableImageVersions[0]
                )
                if (response?.message) throw new Error(response?.message)
                if (response?.status && response?.status !== "pending") {
                  const result = transformAirbyteSpecResponse(response)
                  end(result)
                }
              } catch (error) {
                fail(error)
              }
            },
            onAfterPollingEnd: () => {
              handleSetControlsDisabled(false, controlsDisableRequestId)
              editorMode === "edit" && handleSetTabsDisabled(["streams"], "enable")
            },
          }
        },
      },
      { interval_ms: 2000 }
    )

    const hideFields = useMemo<string[]>(() => {
      if (!fieldsParameters) return _hideFields
      const oauthFieldsParametersNames = fieldsParameters.reduce<string[]>((result, current) => {
        if (current.type.typeName === "oauthSecret") result.push(current.id)
        return result
      }, [])
      return [..._hideFields, ...oauthFieldsParametersNames]
    }, [_hideFields, fieldsParameters])

    const handleFormValuesChange = useCallback(
      (values: PlainObjectWithPrimitiveValues): void => {
        patchConfig(CONFIG_INTERNAL_STATE_KEY, values, { resetErrorsCount: true })
      },
      [patchConfig]
    )

    const handleFormValuesChangeForm = useCallback<FormProps<PlainObjectWithPrimitiveValues>["onValuesChange"]>(
      (changedValues, allValues) => {
        patchConfig(CONFIG_INTERNAL_STATE_KEY, allValues, { resetErrorsCount: true })
        handleIfAirbyteVersionChanged(changedValues)
      },
      [patchConfig]
    )

    const handleIfAirbyteVersionChanged = async (changedFormValues: PlainObjectWithPrimitiveValues): Promise<void> => {
      const newImageVersion = changedFormValues[AIRBYTE_IMAGE_VERSION_FIELD_ID]
      if (newImageVersion && typeof newImageVersion === "string") {
        airbyteImageVersion.current = newImageVersion
        handleResetOauth()
        await reloadParameters()
        handleReloadStreams()
      }
    }

    const handleSetInitialFormValues = useCallback(
      (values: PlainObjectWithPrimitiveValues): void => {
        patchConfig(CONFIG_INTERNAL_STATE_KEY, values, { doNotSetStateChanged: true })
      },
      [patchConfig]
    )

    /**
     * set validator and form reference to parent component after the first render
     */
    useEffect(() => {
      const validateGetErrorsCount: ValidateGetErrorsCount = async () => {
        let errorsCount = 0
        try {
          await form.validateFields()
        } catch (error) {
          errorsCount = +error?.errorFields?.length
        }
        return errorsCount
      }

      setValidator(() => validateGetErrorsCount)
      setFormReference(CONFIG_FORM_KEY, form, handleFormValuesChange)
    }, [])

    return loadingParametersError ? (
      <Row>
        <Col span={4} />
        <Col span={20}>
          <ErrorCard
            title={`Failed to load the source specification data`}
            descriptionWithContacts={null}
            stackTrace={loadingParametersError.stack}
            className={`form-fields-card`}
          />
        </Col>
      </Row>
    ) : isLoadingParameters ? (
      <Row>
        <Col span={4} />
        <Col span={20}>
          <LoadableFieldsLoadingMessageCard
            title="Loading the source configuration"
            longLoadingMessage="Loading the spec takes longer than usual. This might happen if you are configuring such source for the first time - Jitsu will need some time to pull a docker image with the connector code"
            showLongLoadingMessageAfterMs={5000}
            className={`form-fields-card`}
          />
        </Col>
      </Row>
    ) : (
      <Form form={form} onValuesChange={handleFormValuesChangeForm}>
        <AirbyteVersionSelection
          key={`Stream Version Selection`}
          defaultValue={airbyteImageVersion.current}
          options={availableAirbyteImageVersions}
        />
        <ConfigurableFieldsForm
          fieldsParamsList={fieldsParameters || []}
          form={form}
          initialValues={initialValues}
          availableOauthBackendSecrets={"all_from_config"}
          hideFields={hideFields}
          setFormValues={handleFormValuesChange}
          setInitialFormValues={handleSetInitialFormValues}
        />
      </Form>
    )
  }
)
Example #24
Source File: templatesLibrary.ts    From prompts-ai with MIT License 4 votes vote down vote up
templateGroups = [
    {name: 'Simple', templates: [
            {
                id: uniqueId('template_'),
                name: 'Top 10 Women',
                actionPayload: {
                    prompt: 'Top 10 most important women in human history, and their greatest achievements:\n' +
                        '\n' +
                        '1.',
                    stopSymbols: ['11.'],
                    tabIndex: TabIndex.basic,
                    examples: []
                }
            },
            {
                id: uniqueId('template_'),
                name: 'Email Generation',
                actionPayload: {
                    prompt: 'The following email explains two things:\n' +
                        '1) The writer, Andy, is going to miss work.\n' +
                        '2) The receiver, Betty, is Andy\'s boss and can email if anything needs to be done.\n' +
                        '\n' +
                        'From: ',
                    stopSymbols: [],
                    tabIndex: TabIndex.basic,
                    examples: []
                },
            },
            {
                id: uniqueId('template_'),
                name: 'Federalist Paper (Memory)',
                actionPayload: {
                    prompt: 'FEDERALIST No. 79. The Judiciary Continued\n' +
                        '\n' +
                        'HAMILTON\n' +
                        '\n' +
                        'To the People of the State of New York.\n' +
                        '\n' +
                        'IN THE course of the preceding papers,',
                    stopSymbols: [],
                    tabIndex: TabIndex.basic,
                    examples: []
                },
            },
            {
                id: uniqueId('template_'),
                name: 'Simple Math',
                actionPayload: {
                    prompt: '2 * 4 =',
                    stopSymbols: ['\\n'],
                    tabIndex: TabIndex.basic,
                    examples: []
                },
            }
        ]},
    {name: 'Examples', templates: [
            {id: uniqueId('template_'), name: 'Company Classification', actionPayload: {
                    prompt: 'The following is a list of companies and the categories they fall into\n' +
                        '\n' +
                        'Facebook: Social media, Technology\n' +
                        'Uber: Transportation, Technology, Marketplace\n' +
                        'Mcdonalds: Food, Fast Food, Logistics, Restaurants\n' +
                        '{example}:',
                    tabIndex: TabIndex.multipleExamples,
                    stopSymbols: ['\\n'],
                    examples: [{text: 'Unilever', output: 'Consumer Goods, Food, Personal Care, Retail'}, {text: 'LinkedIn', output: 'Social Media, Technology, Business'}, {text: 'FedEx', output: 'Logistics, Transportation'}]
                }},
            {id: uniqueId('template_'), name: 'Alliteration Generator', actionPayload: {
                prompt: 'Find synonyms for words that can create alliterations.\n' +
                    '\n' +
                    'Sentence: The dog went to the store.\n' +
                    'Alliteration: The dog drove to the department.\n' +
                    '\n' +
                    'Sentence: David wears a hat everyday.\n' +
                    'Alliteration: David dons a derby daily.\n' +
                    '\n' +
                    'Sentence: The soap dries over night.\n' +
                    'Alliteration: The soap shrivels succeeding sunset.\n' +
                    '\n' +
                    'Sentence: {example}\n' +
                    'Alliteration:',
                examples: [{text: 'A person was running to the church.', output: ''},
                     {text: 'A person cooked a great meal.', output: ''}],
                tabIndex: 0,
                stopSymbols: ['\\n'],
                }},
            {id: uniqueId('template_'), name: 'Song Generation', actionPayload: {
                    stopSymbols: ["\\n\\n"],
                    prompt: 'VERSE:\n' +
                        'Alas my love,\n' +
                        'You do me wrong,\n' +
                        'To cast me off discourteously,\n' +
                        'for i have loved you so long,\n' +
                        'delighting in your company.\n' +
                        '\n' +
                        'CHORDS:\n' +
                        'Alas[Am] my[C] love,\n' +
                        'you [G]do [Em]me wrong,\n' +
                        'to [Am]cast me off dis[E]courteously,\n' +
                        'for [Am]i have[C] loved[G] you [Em]so long,\n' +
                        'de[Am]lighting in[E7] your [Am]company.\n' +
                        '\n' +
                        'VERSE:\n' +
                        '{example}\n' +
                        '\n' +
                        'CHORDS:',
                    examples: [
                        {text: 'My pangolin heart\n' +
                            'has scales of bone\n' +
                            'black and streaked with red\n' +
                            'hidden like a forgotten gem\n' +
                            'in the dusk', output: ''},
                        {text: 'Country roads, take me home\n' +
                                'To the place I belong\n' +
                                'West Virginia, mountain mama\n' +
                                'Take me home, country roads',
                        output: ''}
                    ],
                    tabIndex: TabIndex.multipleExamples,
                }},
            {id: uniqueId('template_'), name: 'Sentence => Email', actionPayload: {
                    prompt: '```\n' +
                        'Thank John for the book. \n' +
                        '\n' +
                        '````\n' +
                        '\n' +
                        'Dear John,\n' +
                        '\n' +
                        'Thank you so much for the book. I really appreciate it. \n' +
                        '\n' +
                        'I hope to hang out soon. \n' +
                        '\n' +
                        'Your friend, \n' +
                        '\n' +
                        'Sarah\n' +
                        '\n' +
                        '###\n' +
                        '\n' +
                        'Tell TechCorp I appreciate the great service.\n' +
                        '\n' +
                        '````\n' +
                        '\n' +
                        'To Whom it May Concern, \n' +
                        '\n' +
                        'I want you to know that I appreciate the great service at TechCorp.\n' +
                        '\n' +
                        'The staff is outstanding and I enjoy every visit. \n' +
                        '\n' +
                        'Sincerely, \n' +
                        '\n' +
                        'Bill Johnson\n' +
                        '\n' +
                        '###\n' +
                        '\n' +
                        'Invoice Kelly Watkins $500 for design consultation.\n' +
                        '\n' +
                        '````\n' +
                        '\n' +
                        'Dear Ms. Watkins, \n' +
                        '\n' +
                        'This is my invoice for $500 for design consultation. \n' +
                        '\n' +
                        'It was a pleasure to work with you. \n' +
                        '\n' +
                        'Sincerely, \n' +
                        '\n' +
                        'Emily Fields\n' +
                        '\n' +
                        '###\n' +
                        '\n' +
                        'Invite Amanda and Paul to the company event Friday night. \n' +
                        '\n' +
                        '```\n' +
                        'Dear Amanda and Paul,\n' +
                        '\n' +
                        'I hope this finds you doing well. \n' +
                        '\n' +
                        'I want to invite you to our company event on Friday night. \n' +
                        '\n' +
                        'It will be a great opportunity for networking and there will be food and drinks. \n' +
                        '\n' +
                        'Should be fun. \n' +
                        '\n' +
                        'Best, \n' +
                        '\n' +
                        'Ryan\n' +
                        '\n' +
                        '###\n' +
                        '\n' +
                        '{example}\n' +
                        '\n' +
                        '```\n',
                    stopSymbols: ['###'],
                    examples: [
                        {'text': 'Ask RAM Co. if they have new storage units in stock.', 'output': ''}
                    ],
                    tabIndex: TabIndex.multipleExamples
                }},
            {id: uniqueId('template_'), name: 'Book Review', actionPayload: {
                    prompt: 'Title: Lovely War\n' +
                        'Rating: 3/5\n' +
                        'Quotes:\n' +
                        '- "It was time for James and Hazel to get properly acquainted. Time to see if the magic of music and moonlight and graceful movement were all that they had shared, or if a grimy gray London dawn and a cheap cup of coffee could make them feel the same way."\n' +
                        '- "Annihilation has its own je ne sais quoi. We’re all guilty of it. So spare me the sermons."\n' +
                        '- "His mother’s letters are full of urgent warning. She grew up in Mississippi. \n' +
                        'She knows about lynching. Aubrey wonders if he’ll die in his country before he \n' +
                        'ever gets the chance to die for his country. Either way, he’d rather not."\n' +
                        '- "Whatever boost sixty captured miles might have brought to German morale was \n' +
                        'erased by the chocolate in the BEF’s packs. War is morale. War is supply. War is \n' +
                        'chocolate."\n' +
                        'Thoughts:\n' +
                        '- Pacing felt awkward\n' +
                        '- WW1 history felt accurate\n' +
                        '- Didn\'t care too much for the story of the Gods\n' +
                        'Review: A good book with well rounded characters, but the pacing felt super \n' +
                        'awkward. The titles of the chapters showed which Greek God was speaking, but I was more interested in the WW1 tales than their relationships.\n' +
                        '\n' +
                        '\'\'\'\n' +
                        '{example}\n' +
                        'Review:',
                    examples: [
                        {text: 'Title: Goodbye, Things\n' +
                                'Rating: 4/5\n' +
                                'Thoughts:\n' +
                                '- very cleanly written\n' +
                                '- read easily\n' +
                                '- author did good research', output: ''},
                        {text: 'Title: Deep Work: Rules for Focused Success in a Distracted World\n' +
                                'Rating: 5/5\n' +
                                'Thoughts:\n' +
                                '- Great read, got me to refocus my goals around my schedule.\n' +
                                '- Got me to delete a social media I used too much\n' +
                                '- I like that Cal Newport is a computer scientist as well', output: ''}
                    ],
                    tabIndex: TabIndex.multipleExamples,
                    stopSymbols: ['\\n\\n']
                }},
            {id: uniqueId('template_'), name: 'Headline Generation', actionPayload: {
                    prompt: 'Topic: Britain, coronavirus, beaches\n' +
                        'Headline: Videos show crowded beaches in Britain\n' +
                        '\n' +
                        'Topic: Apple, Big Sur, software\n' +
                        'Headline: Apple promises faster software update installation with macOS Big Sur\n' +
                        '\n' +
                        'Topic: Artic, climate change, satellite\n' +
                        'Headline: A Satellite Lets Scientists See Antarctica’s Melting Like Never Before\n' +
                        '\n' +
                        'Topic: {example}\n' +
                        'Headline:',
                    examples: [
                        {text: 'Chicago, restaurants, summer', output: ''}
                    ],
                    tabIndex: TabIndex.multipleExamples,
                    stopSymbols: ['\\n']
                }},
            {id: uniqueId('template_'), name: 'Product Name Generator', actionPayload: {
                    prompt: 'This is a product name generator. It takes a product\'s description and seed words, then outputs a list of potential product names.\n' +
                        '\n' +
                        'Product description: A complete home gym that can fit in any apartment.\n' +
                        'Seed words: intelligent, aspirational, luxury, futuristic\n' +
                        'Product names: InfinityHome, Quantum, FlexFit, Flight, FutureFit\n' +
                        '\n' +
                        'Product description: An affordable electric bike.\n' +
                        'Seed words: Easy, eco-friendly, practical, dependable\n' +
                        'Product names: Pegasus, Swifty, SunRunner, Wave, Amp\n' +
                        '\n' +
                        '{example}\n' +
                        'Product names:',
                    examples: [
                        {text: 'Product description: A zero carbohydrate cereal that tastes great.\n' +
                                'Seed words: fitness, healthy, keto, clean, tasty', output: ''}
                    ],
                    tabIndex: TabIndex.multipleExamples,
                    stopSymbols: ['\\n']
                }},
            {id: uniqueId('template_'), name: 'Rhyming', actionPayload: {
                    prompt: 'A homophone is defined as a word that is pronounced the same as another word but \n' +
                        'differs in meaning.\n' +
                        '\n' +
                        'Here is a list of homophones:\n' +
                        '1. Accept/Except\n' +
                        '2. Affect/Effect\n' +
                        '3. Allude/Elude\n' +
                        '4. Alter/Altar\n' +
                        '5. A lot/Allot\n' +
                        '\n' +
                        'Here\'s a list of homophones starting with the letter "{example}":\n',
                    examples: [
                        {text: "b", output: ""}
                    ],
                    stopSymbols: [],
                    tabIndex: TabIndex.multipleExamples
                }},
            {id: uniqueId('template_'), name: 'Q&A', actionPayload: {
                    prompt: "Q: What is the definition of a linearly independent list?\n" +
                        "A: A linearly independent list is a list of vectors that cannot be\n" +
                        " expressed as a linear combination of other vectors in the list.\n" +
                        " \n" +
                        "Q: What is a basis of a vector space?\n" +
                        "A: A basis of a vector space is a linearly independent list of vectors\n" +
                        " that spans the vector space.\n" +
                        "\n" +
                        "Q: What is a spanning list of vectors in a vector space?\n" +
                        "A: A spanning list of vectors in a vector space is list of vectors in\n" +
                        " the vector space such that every vector in the vector space can be\n" +
                        " written as a linear combination of the vectors in the spanning list.\n" +
                        " \n" +
                        "Q: {example}\n" +
                        "A:",
                    examples: [
                        {text: "What is an eigenvector of a linear transformation f?", output: ""},
                        {text: "What is the definition of a linear transformation?", output: ""},
                        {text: "Is the vector space of univariate polynomials over a finite field a finite-dimensional vector space?",
                            output: ""},
                        {text: "What is the maximum number of eigenvalues of an operator on a 5-dimensional vector space?", output: ""},
                        {text: "Can the length of a spanning list for a vector space be longer than any linearly independent list of vectors in that space?",
                            output: ""},

                    ],
                    stopSymbols: ["\\n"],
                    tabIndex: TabIndex.multipleExamples
                }},
            {id: uniqueId('template_'), name: 'Summarization', actionPayload: {
                    prompt: '```\n' +
                        'My second grader asked me what this passage means:\n' +
                        '\n' +
                        '"""\n' +
                        '\n' +
                        '{example}\n' +
                        '\n' +
                        '"""\n' +
                        '\n' +
                        'I rephrased it for him, in plain language a second grader can understand:\n' +
                        '\n' +
                        '"""\n',
                    examples: [
                        {text: "Overnight trading for the NYSE Index futures was a bit volatile, " +
                                "dropping by about 3% to the downside before moving sharply back to the upside. " +
                                "Gold futures were unchanged and the E-mini NASDAQ 100 futures remained near " +
                                "unchanged. The yield on the 10-year Treasury bond finished unchanged from its " +
                                "close of 2.45% earlier today.",
                            output: ""},
                        {text: "This Nondisclosure Agreement (the \"Agreement\") is entered into by and between _______________ with its principal offices at _______________, (\"Disclosing Party\") and _______________, located at _______________ (\"Receiving Party\") for the purpose of preventing the unauthorized disclosure of Confidential Information as defined below. The parties agree to enter into a confidential relationship concerning the disclosure of certain proprietary and confidential information (\"Confidential Information\"). 1. Definition of Confidential Information. For purposes of this Agreement, \"Confidential Information\" shall include all information or material that has or could have commercial value or other utility in the business in which Disclosing Party is engaged. If Confidential Information is in written form, the Disclosing Party shall label or stamp the materials with the word \"Confidential\" or some similar warning. If Confidential Information is transmitted orally, the Disclosing Party shall promptly provide writing indicating that such oral communication constituted Confidential Information. 2. Exclusions from Confidential Information. Receiving Party's obligations under this Agreement do not extend to information that is: (a) publicly known at the time of disclosure or subsequently becomes publicly known through no fault of the Receiving Party; (b) discovered or created by the Receiving Party before disclosure by Disclosing Party; (c) learned by the Receiving Party through legitimate means other than from the Disclosing Party or Disclosing Party's representatives; or (d) is disclosed by Receiving Party with Disclosing Party's prior written approval.",
                            output: ""},
                    ],
                    stopSymbols: ['"""'],
                    tabIndex: TabIndex.multipleExamples
                }},
            {id: uniqueId('template_'), name: 'Code Translation', actionPayload: {
                    prompt: 'Python:\n' +
                        'list[::-1]\n' +
                        'Ruby:\n' +
                        'list.reverse\n' +
                        '\n' +
                        'Python:\n' +
                        'list[1:4]\n' +
                        'Ruby:\n' +
                        'list[1..4]\n' +
                        '\n' +
                        'Python:\n' +
                        'print("Hello World")\n' +
                        'Ruby:\n' +
                        'puts "Hello World"\n' +
                        '\n' +
                        'Python:\n' +
                        'fruits = ["apple","banana","cherry"]\n' +
                        'for x in fruits:\n' +
                        'print(x)\n' +
                        'Ruby:\n' +
                        'fruit = ["apple", "banana", "cherry"]\n' +
                        'each {|x| print x } \n' +
                        '\n' +
                        'Python:\n' +
                        '{example}\n' +
                        'Ruby:\n',
                    examples: [
                        {text: 'fruits = ["apple","banana","cherry"]\n' +
                                'a = list(fruits)\n' +
                                'print(a)\n' +
                                'a.reverse()\n' +
                                'print(a)', output: ""}
                    ],
                    stopSymbols: ["Python:"],
                    tabIndex: TabIndex.multipleExamples
                }},
            {id: uniqueId('template_'), name: 'Translation', actionPayload: {
                    prompt: 'English: I do not speak French.\n' +
                        'French: Je ne parle pas français.\n' +
                        '\n' +
                        'English: See you later!\n' +
                        'French: À tout à l\'heure!\n' +
                        '\n' +
                        'English: Where is a good restaurant?\n' +
                        'French: Où est un bon restaurant?\n' +
                        '\n' +
                        'English: {example}\n' +
                        'French:',
                    examples: [
                        {text: "What rooms do you have available?", output: ""}
                    ],
                    stopSymbols: ['\\n'],
                    tabIndex: TabIndex.multipleExamples
                }},
            {id: uniqueId('template_'), name: 'Estimation', actionPayload: {
                    prompt: 'Lower and upper bound for each quantity:\n' +
                        '\tNumber of cars in New York: 1500000 to 2500000\n' +
                        '\tNumber of cars in San Francicso: 300000 to 600000\n' +
                        '\tHeight of Empire State building: 1400 to 1500 feet\n' +
                        '\tLength of average car: 4 to 4.5 meters\n' +
                        '\tPopulation of Germany: 80 to 85 million\n' +
                        '\t{example}:',
                    examples: [
                        {text: "How much does the iPhone XI cost?", output: ""}
                    ],
                    stopSymbols: ['\\n'],
                    tabIndex: TabIndex.multipleExamples
                }},
        ]
    },
    {name: 'Variations', templates: [
            {id: uniqueId('template_'), name: 'React Components', actionPayload: {
                prompt: 'import React from \'react\';\n' +
                    '\n' +
                    'const ThreeButtonComponent=()=>(',
                examples: [], tabIndex: TabIndex.variations
                }},
            {id: uniqueId('template_'), name: 'Analogies Generator', actionPayload: {
                    prompt: 'Neural networks are like',
                    stopSymbols: ['.'],
                    examples: [], tabIndex: TabIndex.variations
                }},
            {id: uniqueId('template_'), name: 'Idea Generator', actionPayload: {
                    prompt: 'Here is a list of 100 interesting ideas for new movie plots. Each plot is ' +
                        'described with a title and a summary paragraph:\n' +
                        '\n' +
                        '1. The Bird. \n' +
                        'A woman realizes that her pet bird is actually highly intelligent and able to communicate. The bird turns out to be a secret agent working for the CIA. The woman has to keep the bird\'s secret.\n' +
                        '\n' +
                        '2.',
                    stopSymbols: ['3'],
                    examples: [], tabIndex: TabIndex.variations
                }},
            {id: uniqueId('template_'), name: 'Tweet Generation', actionPayload: {
                prompt: 'My favorite programming tweets:\n' +
                    '-------\n' +
                    'I asked @ilyasut how to set neural network init. He accidentally replied with a poem:\n' +
                    'You want to be on the edge of chaos\n' +
                    'Too small, and the init will be too stable, with vanishing gradients\n' +
                    'Too large, and you\'ll be unstable, due to exploding gradients\n' +
                    'You want to be on the edge\n' +
                    '-------\n' +
                    'I\'ve been programming for 10 years now. Still feels like magic out of a fantasy: say the words exactly right, and watch your intent get carried out; say the words slightly wrong, and things go haywire. Feeling of wonder and joy hasn\'t faded one bit.\n' +
                    '-------\n' +
                    'Web programming is the science of coming up with increasingly complicated ways of concatenating strings.\n' +
                    '-------\n' +
                    'If you ever feel alone in this world, read your firewall logs. Problem solved :)\n' +
                    '-------\n' +
                    'Always wanted to travel back in time to try fighting a younger version of yourself? Software development is the career for you!\n' +
                    '-------\n' +
                    'After 17 years as a professional developer, it seems that the answer to every programming question is "it depends"\n' +
                    '-------\n',
                    stopSymbols: ['\\n-'], examples: [], tabIndex: TabIndex.variations
                }},
            {id: uniqueId('template_'), name: 'Poem Generator', actionPayload: {
                    prompt: 'Who trusted God was love indeed\n' +
                        'And love Creation’s final law\n' +
                        'Tho’ Nature, red in tooth and claw\n' +
                        'With ravine, shriek’d against his creed.\n' +
                        'The hills are shadows, and they flow\n' +
                        'From form to form, and nothing stands;T\n' +
                        'hey melt like mist, the solid lands,\n' +
                        'Like clouds they shape themselves and go.\n' +
                        '----\n',
                    stopSymbols: ['--'], examples: [], tabIndex: TabIndex.variations
                }},
        ]},
    {
        name: 'Conversations',
        templates: [
            {id: uniqueId('template_'), name: 'Mark Zuckerberg', actionPayload: {
                    prompt: 'The following is a transcript of a conversation between Steve, a computer science student, ' +
                    'and Mark Zuckerberg. Mark Zuckerberg is an American media magnate, internet entrepreneur, and philanthropist. ' +
                    'He is known for co-founding Facebook, Inc. and serves as its chairman, chief executive officer,' +
                    ' and controlling shareholder.\n',
                    stopSymbols: ['\\n'],
                    examples: [],
                    tabIndex: TabIndex.conversations,
                    startSequence: '\nMark:',
                    restartSequence: '\nSteve: ',
                }},
            {id: uniqueId('template_'), name: 'AI Assistant', actionPayload: {
                    prompt: 'The following is a conversation with an AI assistant. The assistant is helpful, creative, clever, and very friendly.\n',
                    stopSymbols: ['\\n'],
                    examples: [],
                    tabIndex: TabIndex.conversations,
                    startSequence: '\nAI:',
                    restartSequence: '\nHuman: ',
                }}
        ]
    }
]
Example #25
Source File: index.tsx    From ExpressLRS-Configurator with GNU General Public License v3.0 4 votes vote down vote up
SplitButton: FunctionComponent<SplitButtonProps> = ({
  options,
  onButtonClick,
  ...props
}) => {
  const [open, setOpen] = React.useState(false);
  const anchorRef = React.useRef<HTMLDivElement | null>(null);
  const [selectedIndex, setSelectedIndex] = React.useState(0);
  const [splitButtonMenuId] = useState(() => uniqueId('split-button-menu-'));

  const handleClick = () => {
    onButtonClick(options[selectedIndex].value);
  };

  const handleMenuItemClick = (event: any, index: number) => {
    setSelectedIndex(index);
    setOpen(false);
  };

  const handleToggle = () => {
    setOpen((prevOpen) => !prevOpen);
  };

  const handleClose = (event: any) => {
    if (
      anchorRef.current &&
      event.target &&
      anchorRef.current.contains(event.target)
    ) {
      return;
    }

    setOpen(false);
  };

  return (
    <>
      <ButtonGroup {...props} ref={anchorRef}>
        <Button onClick={handleClick}>{options[selectedIndex].label}</Button>
        <Button
          size="small"
          aria-controls={open ? splitButtonMenuId : undefined}
          aria-expanded={open ? 'true' : undefined}
          aria-label="select button"
          aria-haspopup="menu"
          onClick={handleToggle}
        >
          <ArrowDropDownIcon />
        </Button>
      </ButtonGroup>
      <Popper
        open={open}
        anchorEl={anchorRef.current}
        role={undefined}
        transition
        disablePortal
        style={{ zIndex: 2 }}
      >
        {({ TransitionProps, placement }) => (
          <Grow
            {...TransitionProps}
            style={{
              transformOrigin:
                placement === 'bottom' ? 'center top' : 'center bottom',
            }}
          >
            <Paper>
              <ClickAwayListener onClickAway={handleClose}>
                <MenuList id={splitButtonMenuId}>
                  {options.map((option, index) => (
                    <MenuItem
                      key={option.value}
                      selected={index === selectedIndex}
                      onClick={(event) => handleMenuItemClick(event, index)}
                    >
                      {option.label}
                    </MenuItem>
                  ))}
                </MenuList>
              </ClickAwayListener>
            </Paper>
          </Grow>
        )}
      </Popper>
    </>
  );
}
Example #26
Source File: SourceEditor.tsx    From jitsu with MIT License 4 votes vote down vote up
SourceEditor: React.FC<CommonSourcePageProps> = ({ editorMode }) => {
  const history = useHistory()
  const allSourcesList = sourcesStore.list
  const { source, sourceId } = useParams<{ source?: string; sourceId?: string }>()

  const sourceDataFromCatalog = useMemo<CatalogSourceConnector>(() => {
    let sourceType = source
      ? source
      : sourceId
      ? sourcesStore.list.find(src => src.sourceId === sourceId)?.sourceProtoType
      : undefined

    return sourceType
      ? sourcesCatalog.find((source: CatalogSourceConnector) => snakeCase(source.id) === snakeCase(sourceType))
      : undefined
  }, [sourceId, allSourcesList])

  const [initialSourceData, setInitialSourceData] = useState<SourceEditorInitialSourceData>(
    () =>
      sourceEditorUtils.reformatCatalogIntoSelectedStreams(allSourcesList.find(src => src.sourceId === sourceId)) ??
      createInitialSourceData(sourceDataFromCatalog)
  )

  const [state, setState] = useState<SourceEditorState>(initialState)

  const [controlsDisabled, setControlsDisabled] = useState<boolean | string>(false)
  const [tabsDisabled, setTabsDisabled] = useState<SourceEditorDisabledTabs>(null)
  const [showDocumentation, setShowDocumentation] = useState<boolean>(false)

  const handleSetControlsDisabled = useCallback((disabled: boolean | string, disableRequestId: string): void => {
    const tooltipMessage: string | undefined = typeof disabled === "string" ? disabled : undefined
    if (disabled) {
      setControlsDisabled(disabled)
      disableControlsRequestsRegistry.set(disableRequestId, { tooltipMessage })
    } else {
      disableControlsRequestsRegistry.delete(disableRequestId)
      // enable back only if controls are not disabled by any other callers
      if (disableControlsRequestsRegistry.size === 0) {
        setControlsDisabled(disabled)
      } else {
        // set the tooltip message by a last `disable` caller
        let disabled: boolean | string = true
        disableControlsRequestsRegistry.forEach(({ tooltipMessage }) => {
          if (tooltipMessage) disabled = tooltipMessage
        })
        setControlsDisabled(disabled)
      }
    }
  }, [])

  const handleSetTabsDisabled = useCallback<SetSourceEditorDisabledTabs>((tabKeys, action) => {
    setTabsDisabled(state => {
      const newState = new Set(state)
      tabKeys.forEach(key => (action === "disable" ? newState.add(key) : newState.delete(key)))
      return newState
    })
  }, [])

  const handleBringSourceData = () => {
    let sourceEditorState = state
    setState(state => {
      sourceEditorState = state
      return state
    })
    return sourceEditorUtils.getSourceDataFromState(sourceEditorState, sourceDataFromCatalog, initialSourceData)
  }

  const validateCountErrors = async (): Promise<number> => {
    const configurationErrorsCount = await state.configuration.validateGetErrorsCount()
    const streamsErrorsCount = await state.streams.validateGetErrorsCount()

    setState(state => {
      const newState = cloneDeep(state)
      newState.configuration.errorsCount = configurationErrorsCount
      newState.streams.errorsCount = streamsErrorsCount
      return newState
    })

    return configurationErrorsCount + streamsErrorsCount
  }

  const validateAllForms = async () => {
    const someFieldsErrored = !!(await validateCountErrors())
    if (someFieldsErrored) throw new Error("some values are invalid")
  }

  const getTestConnectionResponse = async (): Promise<TestConnectionResponse> => {
    const sourceData = handleBringSourceData()
    const testResult = await sourcePageUtils.testConnection(sourceData, true)
    return testResult
  }

  const assertCanConnect = async (config?: {
    testConnectionResponse?: TestConnectionResponse
    ignoreErrors?: string[]
  }): Promise<void> => {
    const response = config?.testConnectionResponse ?? (await getTestConnectionResponse())
    if (!response.connected && !config?.ignoreErrors?.includes(response.connectedErrorType))
      throw new ErrorDetailed({
        message: response.connectedErrorMessage,
        name: response.connectedErrorType,
        payload: response.connectedErrorPayload,
      })
  }

  const handleValidateAndTestConnection: HandleValidateTestConnection = async (methodConfig): Promise<void> => {
    await validateAllForms()
    const controlsDisableRequestId = uniqueId("validateAndTest-")
    handleSetControlsDisabled("Validating source configuration", controlsDisableRequestId)
    try {
      await assertCanConnect({ ignoreErrors: methodConfig?.ignoreErrors })
    } finally {
      handleSetControlsDisabled(false, controlsDisableRequestId)
    }
  }

  const handleSave = useCallback<HandleSaveSource>(
    async methodConfig => {
      let sourceEditorState = null
      setState(state => {
        sourceEditorState = state // hack for getting the most recent state in the async function
        return { ...state, stateChanged: false }
      })

      if (editorMode === "edit") await validateAllForms()

      const sourceData = handleBringSourceData()
      const testConnectionResults = await sourcePageUtils.testConnection(sourceData, true)

      await assertCanConnect({
        testConnectionResponse: testConnectionResults,
        ignoreErrors: methodConfig?.ignoreErrors,
      })

      let sourceDataToSave: SourceData = {
        ...sourceData,
        ...testConnectionResults,
      }

      let savedSourceData: SourceData = sourceDataToSave
      if (editorMode === "add") {
        savedSourceData = await flowResult(sourcesStore.add(sourceDataToSave))
      }
      if (editorMode === "edit") {
        await flowResult(sourcesStore.replace(sourceDataToSave))
      }
      await connectionsHelper.updateDestinationsConnectionsToSource(
        savedSourceData.sourceId,
        savedSourceData.destinations
      )

      handleLeaveEditor({ goToSourcesList: true })

      if (savedSourceData.connected) {
        actionNotification.success(editorMode === "add" ? "New source has been added!" : "Source has been saved")
      } else {
        actionNotification.warn(
          `Source has been saved, but test has failed with '${firstToLower(
            savedSourceData.connectedErrorMessage
          )}'. Data from this source will not be available`
        )
      }
    },
    [editorMode, state]
  )

  const handleLeaveEditor = useCallback<(options?: { goToSourcesList?: boolean }) => void>(options => {
    options.goToSourcesList ? history.push(projectRoute(sourcesPageRoutes.root)) : history.goBack()
  }, [])

  const handleValidateStreams = async (): Promise<void> => {
    const streamsErrorsCount = await state.streams.validateGetErrorsCount()
    if (streamsErrorsCount) throw new Error("some streams settings are invalid")
  }

  return (
    <SourceEditorView
      state={state}
      controlsDisabled={controlsDisabled}
      tabsDisabled={tabsDisabled}
      editorMode={editorMode}
      showDocumentationDrawer={showDocumentation}
      initialSourceData={initialSourceData}
      sourceDataFromCatalog={sourceDataFromCatalog}
      setSourceEditorState={setState}
      handleSetControlsDisabled={handleSetControlsDisabled}
      handleSetTabsDisabled={handleSetTabsDisabled}
      setShowDocumentationDrawer={setShowDocumentation}
      handleBringSourceData={handleBringSourceData}
      handleSave={handleSave}
      setInitialSourceData={setInitialSourceData}
      handleLeaveEditor={handleLeaveEditor}
      handleValidateAndTestConnection={handleValidateAndTestConnection}
      handleValidateStreams={handleValidateStreams}
      handleReloadStreams={state.streams.forceReloadStreamsList}
    />
  )
}
Example #27
Source File: preset.ts    From ovineherd with Apache License 2.0 4 votes vote down vote up
getSettingApis = () => {
  const appConfId = getAppInfo().id
  let envList = []

  const appInfo = getReqOption({
    apiType: relation.app.appInfo.apiType,
    apiName: ApiName.one,
    id: appConfId,
  })

  const editAppInfo = getReqOption(
    {
      apiType: relation.app.appInfo.apiType,
      apiName: ApiName.edit,
    },
    {
      onSuccess: (source, option) => {
        syncAppInfo(option.data)
        return source
      },
    }
  )

  const checkEnvData = (data: any): any => {
    if (!data.name || !data.value) {
      return {
        status: -1,
        msg: '请填写变量名与变量值',
      }
    }

    if (!data.id) {
      if (envList.find((i) => i.name === data.name)) {
        return {
          status: -1,
          msg: '权限 KEY 不能重复',
        }
      }
    }
    if (!/[_A-Z0-9]/.test(data.name)) {
      return {
        status: -1,
        msg: '[变量名格式不正确] 请使用大写字母作为变量名',
      }
    }

    return ''
  }

  const envCtrl = async (type: string): Promise<any> => {
    const reqOpt = {
      id: appConfId,
      apiType: relation.app.appInfo.apiType,
    }

    switch (type) {
      case 'get': {
        const { app_env_constants } = await requestByOption({
          ...reqOpt,
          apiName: ApiName.one,
          onlyData: true,
        })
        return app_env_constants
      }
      case 'save': {
        setOvineConstants(envList)
        const saveRes = await requestByOption({
          ...reqOpt,
          apiName: ApiName.edit,
          app_env_constants: JSON.stringify(
            envList.map((i) => {
              return pick(i, ['name', 'value', 'desc'])
            })
          ),
        })
        return saveRes
      }

      default:
        return ''
    }
  }

  const listEnv = {
    url: 'fakeListEnv',
    onFakeRequest: async () => {
      envList = []
      const envArr = await envCtrl('get')
      if (envArr) {
        envList = JSON.parse(envArr) || []
        envList.map((i) => {
          i.id = uniqueId()
          return i
        })
      }
      return {
        data: {
          constants: envList,
        },
      }
    },
  }

  const editEnv = {
    url: 'PUT fakeEditEnv',
    onFakeRequest: async (option) => {
      const { id } = option.data
      const checkRes = checkEnvData(option.data)
      if (checkRes) {
        return checkRes
      }
      const idx = findIndex(envList, { id })
      if (idx !== -1) {
        envList[idx] = option.data
      }
      await envCtrl('save')
      return {
        status: 0,
        msg: '修改成功',
      }
    },
  }

  const delEnv = {
    url: 'PUT fakeDelEnv',
    onFakeRequest: async (option) => {
      const { id } = option.data
      remove(envList, { id })
      await envCtrl('save')
      return {
        status: 0,
        msg: '已删除',
      }
    },
  }

  const addEnv = {
    url: 'POST fakeAddEnv',
    onFakeRequest: async (option) => {
      const checkRes = checkEnvData(option.data)
      if (checkRes) {
        return checkRes
      }
      envList.push(option.data)
      await envCtrl('save')
      return {
        status: 0,
        msg: '保存成功',
      }
    },
  }

  const onOrderChange = {
    onChange: (curr, prev) => {
      if (curr.length && curr.length === prev.length) {
        if (curr.map((i) => i.id).join(',') !== prev.map((i) => i.id).join(',')) {
          envList = curr
          envCtrl('save')
        }
      }
    },
  }

  return {
    appInfo,
    editAppInfo,
    listEnv,
    editEnv,
    delEnv,
    addEnv,
    onOrderChange,
  }
}
Example #28
Source File: SourceEditorFormStreamsLoadable.tsx    From jitsu with MIT License 4 votes vote down vote up
SourceEditorFormStreamsLoadable: React.FC<Props> = ({
  editorMode,
  initialSourceData,
  sourceDataFromCatalog,
  setSourceEditorState,
  handleSetControlsDisabled,
  handleBringSourceData,
}) => {
  const previouslySelectedStreams = useMemo<Array<StreamConfig>>(
    () => initialSourceData?.config?.selected_streams ?? [],
    [initialSourceData]
  )

  const pullAllStreams = useMemo<PullAllStreams>(() => {
    switch (sourceDataFromCatalog.protoType) {
      case "airbyte":
        return pullAllAirbyteStreams
      case "singer":
        return pullAllSingerStreams
      default:
        throw new Error(
          `Can not display streams list. Expected source of type 'airbyte' or 'singer' but received '${sourceDataFromCatalog.protoType}'`
        )
    }
  }, [])

  const controlsDisableRequestId = uniqueId("streams-")
  const {
    isLoading,
    data,
    error,
    reload: reloadStreamsList,
  } = usePolling<StreamData[]>({
    configure: () => ({
      pollingCallback: (end, fail) => async () => {
        try {
          const result = await pullAllStreams(sourceDataFromCatalog, handleBringSourceData)
          if (result !== undefined) end(result)
        } catch (error) {
          fail(error)
        }
      },
      onBeforePollingStart: () => {
        handleSetControlsDisabled("Loading streams list", controlsDisableRequestId)
      },
      onAfterPollingEnd: () => {
        handleSetControlsDisabled(false, controlsDisableRequestId)
      },
    }),
  })

  const selectAllFieldsByDefault: boolean = editorMode === "add"

  const [initiallySelectedStreams, unavailableStreams] = useMemo<[StreamConfig[], StreamConfig[]]>(() => {
    const unavailableStreams: StreamConfig[] = []
    const initiallySelectedStreams = selectAllFieldsByDefault
      ? data
        ? data.map(sourceEditorUtils.streamDataToSelectedStreamsMapper)
        : []
      : data
      ? previouslySelectedStreams.filter(previouslySelectedStream => {
          const streamIsAvailable = data.some(stream =>
            sourceEditorUtils.streamsAreEqual(
              sourceEditorUtils.streamDataToSelectedStreamsMapper(stream),
              previouslySelectedStream
            )
          )
          if (!streamIsAvailable) unavailableStreams.push(previouslySelectedStream)
          return streamIsAvailable
        })
      : previouslySelectedStreams
    return [initiallySelectedStreams, unavailableStreams]
  }, [selectAllFieldsByDefault, previouslySelectedStreams, data])

  useEffect(() => {
    setSourceEditorState(state => {
      const newState = cloneDeep(state)
      newState.streams.errorsCount = error ? 1 : 0
      return newState
    })
  }, [error])

  useEffect(() => {
    const forceReloadStreamsList = reloadStreamsList
    setSourceEditorState(state => {
      const newState = { ...state, streams: { ...state.streams, forceReloadStreamsList } }
      return newState
    })
  }, [])

  return (
    <>
      {data && !error && !isLoading && (
        <>
          {!!unavailableStreams.length && <StreamsUnavailableWarning unavailableStreams={unavailableStreams} />}
          <SourceEditorFormStreamsLoadableForm
            allStreams={data}
            initiallySelectedStreams={initiallySelectedStreams}
            selectAllFieldsByDefault={selectAllFieldsByDefault}
            hide={isLoading || !!error}
            setSourceEditorState={setSourceEditorState}
          />
        </>
      )}
      {isLoading ? (
        <Row>
          <Col span={24}>
            <LoadableFieldsLoadingMessageCard
              title="Loading the list of streams"
              longLoadingMessage="This operation may take up to 3 minutes if you are configuring streams of this source type for the first time."
              showLongLoadingMessageAfterMs={10000}
            />
          </Col>
        </Row>
      ) : error ? (
        <Row>
          <Col span={24}>
            <ErrorCard
              title={`Source configuration validation failed`}
              description={
                error && error.name !== PARSING_STREAMS_ERROR_NAME
                  ? `Connection is not configured.${error.stack ? " See more details in the error stack." : ""}`
                  : `Internal error. Please, file an issue.`
              }
              stackTrace={error?.stack}
              className={"form-fields-card"}
            />
          </Col>
        </Row>
      ) : !data ? (
        <Row>
          <Col span={24}>
            <ErrorCard
              title={`Source configuration validation failed`}
              description={`Internal error. Please, file an issue.`}
              className={"form-fields-card"}
            />
          </Col>
        </Row>
      ) : null}
    </>
  )
}
Example #29
Source File: ignoreArea.helper.ts    From frontend with Apache License 2.0 4 votes vote down vote up
invertIgnoreArea = (
  imageWidth: number,
  imageHeight: number,
  ignoreArea?: IgnoreArea
): IgnoreArea[] => {
  if (!ignoreArea) {
    return [];
  }

  const ignoreArea1 = {
    x: 0,
    y: 0,
    width: ignoreArea.x,
    height: ignoreArea.y,
    id: uniqueId(),
  };

  const ignoreArea2 = {
    x: ignoreArea.x,
    y: 0,
    width: ignoreArea.width,
    height: ignoreArea.y,
    id: uniqueId(),
  };

  const ignoreArea3 = {
    x: ignoreArea.x + ignoreArea.width,
    y: 0,
    width: imageWidth - (ignoreArea1.width + ignoreArea2.width),
    height: ignoreArea.y,
    id: uniqueId(),
  };

  const ignoreArea4 = {
    x: ignoreArea1.x,
    y: ignoreArea1.y + ignoreArea1.height,
    width: ignoreArea1.width,
    height: ignoreArea.height,
    id: uniqueId(),
  };

  const ignoreArea5 = {
    x: ignoreArea3.x,
    y: ignoreArea3.y + ignoreArea3.height,
    width: ignoreArea3.width,
    height: ignoreArea.height,
    id: uniqueId(),
  };

  const ignoreArea6 = {
    x: ignoreArea4.x,
    y: ignoreArea4.y + ignoreArea4.height,
    width: ignoreArea1.width,
    height: imageHeight - (ignoreArea1.height + ignoreArea.height),
    id: uniqueId(),
  };

  const ignoreArea7 = {
    x: ignoreArea.x,
    y: ignoreArea.y + ignoreArea.height,
    width: ignoreArea.width,
    height: ignoreArea6.height,
    id: uniqueId(),
  };

  const ignoreArea8 = {
    x: ignoreArea5.x,
    y: ignoreArea5.y + ignoreArea5.height,
    width: ignoreArea5.width,
    height: ignoreArea6.height,
    id: uniqueId(),
  };

  return [
    ignoreArea1,
    ignoreArea2,
    ignoreArea3,
    ignoreArea4,
    ignoreArea5,
    ignoreArea6,
    ignoreArea7,
    ignoreArea8,
  ];
}