import { IBundle } from "@staticdeploy/core" ; import Cascader from "antd/lib/cascader" ; import Form , { FormItemProps } from "antd/lib/form" ; import classnames from "classnames" ; import dayjs from "dayjs" ; import find from "lodash/find" ; import keys from "lodash/keys" ; import map from "lodash/map" ; import setWith from "lodash/setWith" ; import sortBy from "lodash/sortBy" ; import values from "lodash/values" ; import React from "react" ; import { Field , WrappedFieldProps } from "redux-form" ; interface IIntermediateMap { [ bundleName ] : { [ bundleTag ] : { [ bundleId ] : IBundle ; } ; } ; } interface IProps { name : string ; bundles : IBundle [ ] ; className ? : string ; label ? : FormItemProps [ "label" ] ; disabled ? : boolean ; placeholder ? : string ; } export class WrappedBundleIdField extends React . Component < WrappedFieldProps & IProps > { getOptions ( ) { const intermediateMap = { } ; this . props . bundles . forEach ( ( bundle ) => setWith ( intermediateMap , [ bundle . name , bundle . tag , bundle . id ] , bundle , Object ) ) ; const bundleNames = keys ( intermediateMap ) . sort ( ) ; return bundleNames . map ( ( bundleName ) => { const bundleTags = keys ( intermediateMap [ bundleName ] ) . sort ( ) ; return { value : bundleName , label : bundleName , children : bundleTags . map ( ( bundleTag ) => { const bundles = sortBy ( values ( intermediateMap [ bundleName ] [ bundleTag ] ) , "createdAt" ) . reverse ( ) ; return { value : bundleTag , label : bundleTag , children : bundles . map ( ( bundle ) => ( { value : bundle . id , label : `${ bundle . id } (${ dayjs ( bundle . createdAt ) . fromNow ( true ) })` , } ) ) , } ; } ) , } ; } ) ; } getValue ( ) { const selectedBundle = find ( this . props . bundles , { id : this . props . input . value , } ) as IBundle | undefined ; return selectedBundle ? [ selectedBundle . name , selectedBundle . tag , selectedBundle . id ] : undefined ; } render ( ) { const error = this . props . meta . error ; const displayError = this . props . meta . touched && error ; return ( < Form . Item label = { this . props . label } wrapperCol = { { span : 24 } } className = { classnames ( "c-BundleIdField" , this . props . className ) } validateStatus = { displayError ? "error" : undefined } help = { displayError ? error : undefined } > < Cascader options = { this . getOptions ( ) } value = { this . getValue ( ) } onChange = { ( [ , , bundleId ] ) => this . props . input . onChange ( bundleId || null ) } onBlur = { this . props . input . onBlur } disabled = { this . props . disabled } placeholder = { this . props . placeholder } displayRender = { ( _labels , selectedOptions ) => { const [ bundleName , bundleTag , bundleId ] = map ( selectedOptions , "value" ) ; return bundleName ? `${ bundleName }:${ bundleTag } (${ bundleId })` : null ; } } /> < /Form.Item>); } } export default class BundleIdField extends React . Component < IProps > { render ( ) { return ( < Field name = { this . props . name } component = { WrappedBundleIdField as any } props = { this . props as any } / > ) ; } }