Skip to content

Smart action hook previousValue wrongly set #1010

@FrancisRoc

Description

@FrancisRoc

Expected behavior

changedField.previousValue should be properly set on the 'Number of values' field whatever the position of that field is (See context it will be more clear)

Actual behavior

If my 'Number of values' number input field is not at the 4th position (index = 3) the hook previous value is always null and it seems that whatever the field that is at the 4th position in the array has it's previous value set instead of my number input

Failure Logs

None

Context

Please help this makes no sense to me. Also note that all fields before the prblematic one is not added or removed dynamically so that can't really change the position on 'Number of values' field

Smart action:

export enum EnterpriseCollectionFields {
  Name = 'Name',
  OfferCard = 'Offer mobility card',
  Type = 'Spending rules type',
  ShortDescription = 'Short Description (Summary)',
  Description = 'Description',
  Value = 'Value',
  DailyLimit = 'Daily limit',
  TransactionLimit = 'Transaction limit',
  MonthlyAllocation = 'Monthly allocation'
}

export declare enum SpendingRuleType {
    StripeMerchant = "stripeMerchant",
    StripeCategory = "stripeCategory",
    CommutifiPlan = "commutifiPlan",
    Wallet = "wallet"
}

{
      name: 'Create Wallet',
      type: 'single',
      fields: [
        {
          field: EnterpriseCollectionFields.OfferCard,
          description:
            'Weather this wallet will setup a Commutifi card or not. Then rules like Stripe categories can be applied',
          type: 'Boolean',
          hook: 'onOfferCardChanged',
          isRequired: true,
          defaultValue: false
        },
        {
          field: EnterpriseCollectionFields.Type,
          description: 'Type of spending rule restrictions you want to add',
          type: 'Enum',
          enums: Object.values(SpendingRuleType),
          hook: 'onTypeChanged',
          isRequired: true
        },
        {
          field: 'Number of values',
          description: 'How many plans or stripe categories you want to add ?',
          type: 'Number',
          defaultValue: 1,
          hook: 'onNbValueChange'
        },
        {
          field: EnterpriseCollectionFields.Value,
          description:
            'Commutifi Plan ids, Stripe categories or leave empty if you are making a global rule for the wallet (Ex. monthly limit only or days limit)',
          type: 'String',
          reference: 'plans.id'
        },
        {
          field: EnterpriseCollectionFields.Name,
          description: 'Wallet Name that employee will see',
          type: 'String',
          isRequired: true
        },
        {
          field: EnterpriseCollectionFields.Description,
          description:
            'Long Wallet description. Markdown available in wallet detail view but we can only use a simple text here ...',
          type: 'String',
          isRequired: true
        },
        {
          field: EnterpriseCollectionFields.ShortDescription,
          description: 'Quick 50 max characters description of the wallet',
          type: 'String',
          isRequired: true,
          hook: 'onDescriptionChange'
        },

        {
          field: EnterpriseCollectionFields.DailyLimit,
          description: 'Daily max amount spent (in cents)',
          type: 'Number'
        },
        {
          field: EnterpriseCollectionFields.TransactionLimit,
          description: 'Max amount PER transaction (in cents)',
          type: 'Number'
        }
      ],
      hooks: {
        change: {
          onOfferCardChanged: ({ fields, changedField }) => {
            if (changedField.value === true) {
              fields.push({
                previousValue: undefined,
                value: undefined,
                field: EnterpriseCollectionFields.MonthlyAllocation,
                type: 'Number',
                isRequired: true
              })
            } else {
              const index = fields.findIndex(
                (f) => f.field === EnterpriseCollectionFields.MonthlyAllocation
              )
              fields.splice(index, 1)
            }
            return fields
          },
          onTypeChanged: ({ fields, changedField }) => {
            const fieldsIndexToMutate = []
            fields.forEach((field, i) =>
              field.field.startsWith(EnterpriseCollectionFields.Value)
                ? fieldsIndexToMutate.push(i)
                : null
            )

            switch (changedField.value) {
              case SpendingRuleType.CommutifiPlan:
                fieldsIndexToMutate.forEach((index) => {
                  const field = fields[index]
                  field.isRequired = true
                  field.type = 'String'
                  field.reference = 'plans.id'
                  field.enums = null
                  // @ts-ignore
                  field.widgetEdit = {
                    name: 'belongsto typeahead',
                    parameters: {}
                  }
                })
                break
              case SpendingRuleType.StripeMerchant:
                fieldsIndexToMutate.forEach((index) => {
                  const field = fields[index]
                  field.isRequired = true
                  field.type = 'String'
                  field.reference = null
                  field.enums = null
                  // @ts-ignore
                  field.widgetEdit = {
                    name: 'text editor',
                    parameters: {}
                  }
                })
                break
              case SpendingRuleType.Wallet:
                fieldsIndexToMutate.forEach((index) => {
                  const field = fields[index]
                  field.isRequired = false
                  field.type = 'String'
                  field.reference = null
                  field.enums = null
                  // @ts-ignore
                  field.widgetEdit = {
                    name: 'text editor',
                    parameters: {}
                  }
                })
                break

              default:
                break
            }
            return fields
          },
          onNbValueChange: ({ changedField, fields }) => {
            if (changedField.value < 0) {
              return fields
            }
            const previousValue = changedField.previousValue ?? 1
            const value = changedField.value ?? 1
            const valueFieldIndex = fields.findIndex((field) =>
              field.field.startsWith(EnterpriseCollectionFields.Value)
            )
            const index =
              valueFieldIndex >= 0
                ? valueFieldIndex
                : fields.findIndex(
                    (field) => field.field === 'Number of values'
                  ) + 1
            if (previousValue < value) {
              const newFieldAmount = value - previousValue
              fields.splice(
                index + previousValue,
                0,
                // times function is from lodash
                ...times(newFieldAmount, (i) => ({
                  previousValue: undefined,
                  value: undefined,
                  ...walletPlanValueField,
                  field: `${EnterpriseCollectionFields.Value}${
                    previousValue + i
                  }`
                }))
              )
            } else if (previousValue > value) {
              const deleteFieldAmount = previousValue - value
              fields.splice(index + value, deleteFieldAmount)
            }

            return fields
          },
          onDescriptionChange: ({ fields, changedField }) => {
            if (
              typeof changedField.value === 'string' &&
              changedField.value.length > 50
            ) {
              changedField.value.substring(0, 50)
            }
            return fields
          }
        }
      }
    }

In that configuration ⬆️ I can't get the number input to work with adding value fields properly because the previous value is set on the wrong item in the fields array
image

But the position in the schema is right
image

Screen record of bad behavior (Number of values is 3rd in array -> index 2)

bad-previous-value

Screen record of good behavior (Number of values is 4th in array -> index 3)

good-previous-value

  • Package Version: "forest-express-sequelize": "~8.5.10",
  • Express Version: "express": "~4.17.1"
  • Sequelize Version: "sequelize": "~5.15.1",
  • Database Dialect: Postgres
  • Database Version: "pg": "~8.2.2",

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions