windmill-labs / windmill

Open-source developer platform to power your entire infra and turn scripts into webhooks, workflows and UIs. Fastest workflow engine (13x vs Airflow). Open-source alternative to Retool and Temporal.
https://windmill.dev
Other
9.99k stars 473 forks source link

bug: The row data obtained by AgGrid Table Button is incorrect. #4246

Closed J1ufan closed 2 months ago

J1ufan commented 2 months ago

Describe the bug

After using the Table Actions button in AgGrid Tables to modify the data in the table and refresh the table data, the row data (row.value) obtained by the button when operating the table data again is incorrect

To reproduce

Described above

Expected behavior

.

Screenshots

No response

Browser information

No response

Application version

No response

Additional Context

No response

rubenfiszel commented 2 months ago

The only data that you can modify directly is data stored as a field of the state global variable, e.g: state.foo = { ... }

And to modify it in a frontend script, you will need to do your modification and then re-assign that state field. For instance:

state.foo.bar = 42
state.foo = state.foo
J1ufan commented 2 months ago

Below is my business process

  1. Get the data in Mysql through Python script, use AgGridTable to render and add Button
  2. After clicking Button, execute Python to update the data in Mysql, and use on success in Event handlers to refresh AgGrid Table,
  3. When I click Button again, the row.values ​​I get is not the data of the row where the button is located

Is this caused by the reason you mentioned?

rubenfiszel commented 2 months ago

What you're doing should work. Could you build a minimal app that does not depend on any external resource and that expose this behavior. We will investigate

J1ufan commented 2 months ago

Ok, I'll try it and reply later.

rubenfiszel commented 2 months ago

I investigated with the information available and likely found the issue.

If you're self-hosted, pull main in 20minutes, if you're on cloud, we will deploy in an hour

J1ufan commented 2 months ago

OK, I'll update and try again.

J1ufan commented 2 months ago

I just tried again in the cloud and the problem persists. cloud version:EE v1.380.0-1-g6c9e32af1

  1. Select the data with id 7 for the first click image

  2. After the update is successful, refresh the table and select the data with id 12 to click. At this time, row.value gets the data with id 9.image

variable(u/vursd/data):

[{"id": 1, "name": "A cell with a long name", "age": 42, "status": "inactive"}, {"id": 2, "name": "A briefer cell", "age": 84, "status": "inactive"}, {"id": 3, "name": "Moderate length name", "age": 30, "status": "active"}, {"id": 4, "name": "Short name", "age": 55, "status": "inactive"}, {"id": 5, "name": "Another longish cell name", "age": 67, "status": "inactive"}, {"id": 6, "name": "Sample name", "age": 29, "status": "inactive"}, {"id": 7, "name": "Unique identifier", "age": 31, "status": "inactive"}, {"id": 8, "name": "Brief cell", "age": 44, "status": "inactive"}, {"id": 9, "name": "Lengthy name example", "age": 52, "status": "inactive"}, {"id": 10, "name": "Simple name", "age": 36, "status": "inactive"}, {"id": 11, "name": "Another cell name", "age": 48, "status": "inactive"}, {"id": 12, "name": "Name example", "age": 60, "status": "active"}, {"id": 13, "name": "Descriptive cell", "age": 27, "status": "inactive"}, {"id": 14, "name": "Concise name", "age": 33, "status": "inactive"}, {"id": 15, "name": "Detail cell name", "age": 45, "status": "active"}, {"id": 16, "name": "Shorter name", "age": 37, "status": "inactive"}, {"id": 17, "name": "Informative name", "age": 50, "status": "active"}, {"id": 18, "name": "Minimal name", "age": 40, "status": "inactive"}, {"id": 19, "name": "Extended cell name", "age": 39, "status": "inactive"}, {"id": 20, "name": "Brief name", "age": 53, "status": "inactive"}]

App Export:

grid:
  - "3":
      fixed: true
      x: 0
      y: 0
      fullHeight: false
      w: 6
      h: 2
    "12":
      fixed: true
      x: 0
      y: 0
      fullHeight: false
      w: 12
      h: 2
    data:
      type: containercomponent
      configuration: {}
      customCss:
        container:
          class: "!p-0"
          style: ""
      actions: []
      numberOfSubgrids: 1
      id: topbar
    id: topbar
  - "3":
      fixed: false
      x: 0
      y: 2
      fullHeight: false
      w: 2
      h: 8
    "12":
      fixed: false
      x: 0
      y: 2
      fullHeight: false
      w: 12
      h: 15
    data:
      type: containercomponent
      configuration: {}
      customCss:
        container:
          class: ""
          style: ""
      actions: []
      numberOfSubgrids: 1
      id: a
    id: a
fullscreen: false
unusedInlineScripts: []
hiddenInlineScripts: []
theme:
  type: path
  path: f/app_themes/theme_0
subgrids:
  topbar-0:
    - "3":
        fixed: false
        x: 0
        y: 0
        fullHeight: false
        w: 6
        h: 1
      "12":
        fixed: false
        x: 0
        y: 0
        fullHeight: false
        w: 6
        h: 1
      data:
        type: textcomponent
        configuration:
          style:
            type: static
            value: Body
          copyButton:
            type: static
            value: false
          tooltip:
            type: evalv2
            value: ""
            fieldType: text
            expr: "`Author: ${ctx.author}`"
            connections:
              - componentId: ctx
                id: author
          disableNoText:
            type: static
            value: true
            fieldType: boolean
        componentInput:
          type: templatev2
          fieldType: template
          eval: ${ctx.summary}
          connections:
            - id: summary
              componentId: ctx
        customCss:
          text:
            class: text-xl font-semibold whitespace-nowrap truncate
            style: ""
          container:
            class: ""
            style: ""
        actions: []
        horizontalAlignment: left
        verticalAlignment: center
        id: title
      id: title
    - "3":
        fixed: false
        x: 0
        y: 1
        fullHeight: false
        w: 3
        h: 1
      "12":
        fixed: false
        x: 6
        y: 0
        fullHeight: false
        w: 6
        h: 1
      data:
        type: recomputeallcomponent
        configuration: {}
        customCss:
          container:
            style: ""
            class: ""
        actions: []
        menuItems: []
        horizontalAlignment: right
        verticalAlignment: center
        id: recomputeall
      id: recomputeall
  a-0:
    - "3":
        fixed: false
        x: 0
        y: 0
        fullHeight: false
        w: 2
        h: 1
      "12":
        fixed: false
        x: 0
        y: 0
        fullHeight: false
        w: 3
        h: 1
      data:
        type: selectcomponent
        configuration:
          items:
            type: evalv2
            value:
              - value: foo
                label: Foo
              - value: bar
                label: Bar
            expr: '[{"value":"active","label":"active"},{"value":"inactive","label":"inactive"}]'
            connections: []
          create:
            type: static
            value: false
          placeholder:
            type: static
            value: Select an item
          disabled:
            type: static
            value: false
          defaultValue:
            type: static
          preselectFirst:
            type: static
            value: true
          fullWidth:
            type: static
            value: true
        customCss:
          input:
            style: ""
            tooltip: https://github.com/rob-balfre/svelte-select/blob/master/docs/theming_variables.md
            class: ""
        recomputeIds: []
        actions: []
        verticalAlignment: center
        id: b
        onSelect: []
      id: b
    - "3":
        fixed: false
        x: 0
        y: 1
        fullHeight: false
        w: 3
        h: 10
      "12":
        fixed: false
        x: 0
        y: 1
        fullHeight: false
        w: 12
        h: 13
      data:
        type: aggridcomponent
        configuration:
          columnDefs:
            type: static
            value:
              - field: id
                flex: 1
              - field: name
                editable: true
                flex: 1
              - field: age
                flex: 1
              - field: status
                editable: true
                flex: 1
            expr: ""
            connections: []
          flex:
            type: static
            value: true
          allEditable:
            type: static
            value: false
          multipleSelectable:
            type: static
            value: false
          rowMultiselectWithClick:
            type: static
            value: true
          pagination:
            type: static
            value: false
          selectFirstRowByDefault:
            type: static
            value: true
          extraConfig:
            type: static
            value: {}
          compactness:
            type: static
            value: normal
          wrapActions:
            type: static
            value: false
          footer:
            type: static
            value: true
          customActionsHeader:
            type: static
        componentInput:
          type: runnable
          fieldType: array
          subFieldType: object
          value:
            - id: 1
              name: A cell with a long name
              age: 42
            - id: 2
              name: A briefer cell
              age: 84
          connections: []
          expr: ""
          runnable:
            type: runnableByName
            name: Inline Script 0
            inlineScript:
              content: |
                import wmill
                import json

                raw_data = wmill.get_variable("u/vursd/data")

                def main(status: str):
                    data = json.loads(raw_data)
                    print(data)
                    return [item for item in data if item["status"] == status]
              language: python3
              path: u/vursd/free_app/Inline_Script_0
              schema:
                $schema: https://json-schema.org/draft/2020-12/schema
                properties:
                  status:
                    default: null
                    description: ""
                    originalType: string
                    type: string
                required:
                  - status
                type: object
          fields:
            status:
              type: evalv2
              value: ""
              fieldType: string
              expr: b.result
              connections:
                - componentId: b
                  id: result
          autoRefresh: true
          recomputeOnInputChanged: true
        customCss:
          container:
            class: ""
            style: ""
        actions:
          - type: buttoncomponent
            configuration:
              label:
                type: static
                value: active
              color:
                type: static
                value: blue
              size:
                type: static
                value: xs
              fillContainer:
                type: static
                value: false
              disabled:
                type: static
                value: false
              beforeIcon:
                type: static
                value: ""
              afterIcon:
                type: static
                value: ""
              triggerOnAppLoad:
                type: static
                value: false
              onSuccess:
                type: oneOf
                selected: none
                configuration:
                  none: {}
                  gotoUrl:
                    url:
                      type: static
                      value: ""
                    newTab:
                      type: static
                      value: true
                  setTab:
                    setTab:
                      type: static
                      value: []
                  sendToast:
                    message:
                      type: static
                      value: ""
                  openModal:
                    modalId:
                      type: static
                      value: ""
                  closeModal:
                    modalId:
                      type: static
                      value: ""
                  open:
                    id:
                      type: static
                      value: ""
                  close:
                    id:
                      type: static
                      value: ""
                  clearFiles:
                    id:
                      type: static
                      value: ""
              onError:
                type: oneOf
                selected: errorOverlay
                configuration:
                  errorOverlay: {}
                  gotoUrl:
                    url:
                      type: static
                      value: ""
                    newTab:
                      type: static
                      value: true
                  setTab:
                    setTab:
                      type: static
                      value: []
                  sendErrorToast:
                    message:
                      type: static
                      value: An error occured
                    appendError:
                      type: static
                      value: true
                  open:
                    id:
                      type: static
                      value: ""
                  close:
                    id:
                      type: static
                      value: ""
              confirmationModal:
                type: oneOf
                selected: none
                configuration:
                  none: {}
                  confirmationModal:
                    title:
                      type: static
                      value: Title
                    description:
                      type: static
                      value: Are you sure?
                    confirmationText:
                      type: static
                      value: Confirm
            componentInput:
              type: runnable
              fieldType: any
              fields:
                x:
                  type: evalv2
                  value: null
                  fieldType: integer
                  connections:
                    - componentId: row
                      id: value
                  expr: row.value.id
              runnable:
                type: runnableByName
                name: Inline Script 1
                inlineScript:
                  content: |
                    import wmill
                    import json

                    data = json.loads(wmill.get_variable("u/vursd/data"))

                    def main(x: int):
                        for row in data:
                            if row["id"] == x:
                                row["status"] = "active"
                        wmill.set_variable("u/vursd/data", json.dumps(data))
                        json.dumps(data)
                        return None
                  language: python3
                  path: u/vursd/inspirational_app/Inline_Script_1
                  schema:
                    $schema: https://json-schema.org/draft/2020-12/schema
                    properties:
                      x:
                        default: null
                        description: ""
                        originalType: string
                        type: integer
                    required:
                      - x
                    type: object
              autoRefresh: false
              recomputeOnInputChanged: false
            customCss:
              button:
                style: ""
                class: ""
              container:
                style: ""
                class: ""
            recomputeIds: []
            actions: []
            horizontalAlignment: center
            verticalAlignment: center
            id: c_a
          - type: buttoncomponent
            configuration:
              label:
                type: static
                value: inactive
              color:
                type: static
                value: blue
              size:
                type: static
                value: xs
              fillContainer:
                type: static
                value: false
              disabled:
                type: static
                value: false
              beforeIcon:
                type: static
                value: ""
              afterIcon:
                type: static
                value: ""
              triggerOnAppLoad:
                type: static
                value: false
              onSuccess:
                type: oneOf
                selected: none
                configuration:
                  none: {}
                  gotoUrl:
                    url:
                      type: static
                      value: ""
                    newTab:
                      type: static
                      value: true
                  setTab:
                    setTab:
                      type: static
                      value: []
                  sendToast:
                    message:
                      type: static
                      value: ""
                  openModal:
                    modalId:
                      type: static
                      value: ""
                  closeModal:
                    modalId:
                      type: static
                      value: ""
                  open:
                    id:
                      type: static
                      value: ""
                  close:
                    id:
                      type: static
                      value: ""
                  clearFiles:
                    id:
                      type: static
                      value: ""
              onError:
                type: oneOf
                selected: errorOverlay
                configuration:
                  errorOverlay: {}
                  gotoUrl:
                    url:
                      type: static
                      value: ""
                    newTab:
                      type: static
                      value: true
                  setTab:
                    setTab:
                      type: static
                      value: []
                  sendErrorToast:
                    message:
                      type: static
                      value: An error occured
                    appendError:
                      type: static
                      value: true
                  open:
                    id:
                      type: static
                      value: ""
                  close:
                    id:
                      type: static
                      value: ""
              confirmationModal:
                type: oneOf
                selected: none
                configuration:
                  none: {}
                  confirmationModal:
                    title:
                      type: static
                      value: Title
                    description:
                      type: static
                      value: Are you sure?
                    confirmationText:
                      type: static
                      value: Confirm
            componentInput:
              type: runnable
              fieldType: any
              fields:
                x:
                  type: evalv2
                  value: null
                  fieldType: integer
                  connections:
                    - componentId: row
                      id: value
                  expr: row.value.id
              runnable:
                type: runnableByName
                name: Inline Script 2
                inlineScript:
                  content: |
                    import wmill
                    import json

                    data = json.loads(wmill.get_variable("u/vursd/data"))

                    def main(x: int):
                        for row in data:
                            if row["id"] == x:
                                row["status"] = "inactive"
                        wmill.set_variable("u/vursd/data", json.dumps(data))
                        print(json.dumps(data))
                        return None
                  language: python3
                  path: u/vursd/inspirational_app/Inline_Script_2
                  schema:
                    $schema: https://json-schema.org/draft/2020-12/schema
                    properties:
                      x:
                        default: null
                        description: ""
                        originalType: string
                        type: integer
                    required:
                      - x
                    type: object
              autoRefresh: false
              recomputeOnInputChanged: false
            customCss:
              button:
                style: ""
                class: ""
              container:
                style: ""
                class: ""
            recomputeIds: []
            actions: []
            horizontalAlignment: center
            verticalAlignment: center
            id: c_b
        id: c
      id: c
hideLegacyTopBar: true
norefreshbar: false
rubenfiszel commented 2 months ago

We hadn't bumped the cloud. Try in 5 more minutes. Can't import your app as it relies on a variable specific to you

J1ufan commented 2 months ago

Still doesn't work, the current version number is EE v1.380.0-5-g3cf4f00dc. I provided the variable values ​​above, but you need to modify the content of the inline script to use it.

J1ufan commented 2 months ago

My bad. I logged into the cloud again and tried again. It worked fine.

Thanks for your help