Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui): Present items as a hierarchical list #406

Merged
merged 9 commits into from
Oct 1, 2024

Conversation

rouk1
Copy link
Contributor

@rouk1 rouk1 commented Sep 27, 2024

A new UI component is introduced: a tree accordion 🪗

It can have as many nested level as needed and is collapsible.

Transforming a list of keys to tree structure is now done in the report store. It's implemented in the keysAsTree function.

  1. The function starts by initializing an empty array tree to hold the root nodes of the tree structure.
  2. It gets all the keys from the items object (or an empty object if items is null).
  3. The function then iterates over each key:
    a. It splits the key into segments, filtering out any empty segments.
    b. It identifies the root segment (first part of the path).
    c. It checks if a node for this root segment already exists in the tree. If not, it creates a new node and adds it to the tree.
    d. It then iterates through the remaining segments of the key:
    • For each segment, it builds the full path up to that point.
    • It checks if a child node with this path already exists.
    • If not, it creates a new child node and adds it to the current node's children.
    • It then moves to this child node for the next iteration.
  4. After building the basic structure, it defines an addSelf function:
  • This function recursively goes through the tree.
  • If a node's name matches a key in the original list and it has children, it adds a "(self)" node as the first child.
  • This handles cases where a path is both a key itself and has child keys.
  1. Finally, it applies the addSelf function to each root node in the tree.
  2. The function returns the completed tree structure.

Usage:

<script setup lang="ts">
import TreeAccordion, { type TreeAccordionNode } from "@/components/TreeAccordion.vue";

const fileTreeNodes: TreeAccordionNode[] = [
  {
    name: "fraud",
    children: [{ name: "fraud/accuracy" }, { name: "fraud/accuracy3" }],
  },
  {
    name: "fraud2",
    children: [{ name: "fraud2/accuracy" }, { name: "fraud2/accuracy3" }],
  },
  {
    name: "nested",
    children: [
      {
        name: "nested/fraud2/accuracy",
        children: [
          { name: "nested/fraud2/accuracy/self" },
          { name: "nested/fraud2/accuracy/self2" },
          { name: "nested/fraud2/accuracy/self3" },
        ],
      },
      { name: "nested/fraud2/accuracy3", children: [] },
    ],
  },
];
</script>

<template>
  <TreeAccordion :nodes="fileTreeNodes" />
</template
accordion.mp4

Fixes #335

@rouk1 rouk1 linked an issue Sep 27, 2024 that may be closed by this pull request
Copy link
Contributor

github-actions bot commented Sep 27, 2024

Coverage Report for ./frontend

Status Category Percentage Covered / Total
🔵 Lines 83.4% 1236 / 1482
🔵 Statements 83.4% 1236 / 1482
🔵 Functions 57.14% 48 / 84
🔵 Branches 84.11% 143 / 170
File Coverage
File Stmts % Branch % Funcs % Lines Uncovered Lines
Changed Files
frontend/src/components/TreeAccordion.vue 65% 100% 0% 65% 16-18, 20-23
frontend/src/components/TreeAccordionItem.vue 85.5% 93.33% 14.28% 85.5% 17-21, 37-41
frontend/src/stores/report.ts 88.46% 82.85% 92.3% 88.46% 42-43, 51-57, 72-73, 87, 127-129
frontend/src/views/ComponentsView.vue 89.07% 100% 0% 89.07% 28-30, 32-34, 40-49, 51-55, 57-61
frontend/src/views/ReportBuilderView.vue 61.79% 83.33% 0% 61.79% 1, 18-29, 31-33, 35-41, 43-45, 47-51, 53-55
Generated in workflow #34 for commit 3bdf179 by the Vitest Coverage Report Action

@tuscland
Copy link
Member

Two suggestions:

  • What about "TreeView" as component name?
  • I was wondering if TreeAccordionNode is aware of the convention of using / character as path separator. Also, it seems the example skipping from nested to nested/fraud2/accuracy, suggests the names have rightfully no role in the structure of the tree. Can you explain how the node display name is computed in this PRs example (e.g. nested/fraud2/accuracy)?

@rouk1
Copy link
Contributor Author

rouk1 commented Sep 30, 2024

* What about "TreeView" as component name?

View is reserved because we follow the smart / dumb pattern and by vue's layout. Indeed everything in the "views" folder is something that is "smart" (i.e. it does API calls) So the word view is banned from components names.

* I was wondering if `TreeAccordionNode` is aware of the convention of using `/` character as path separator. Also, it seems the example skipping from `nested` to `nested/fraud2/accuracy`, suggests the names have rightfully no role in the structure of the tree. Can you explain how the node display name is computed in this PRs example (e.g. `nested/fraud2/accuracy`)?

No Accordions and there node have no clues of the underlining data. The tree is parsed in the report store.
See the keysAsTree function of the store.

Edit: describe keysAsTree function.

@augustebaum augustebaum self-requested a review September 30, 2024 08:23
@augustebaum augustebaum changed the title UI: Present items as a hierarchical list feat(ui): Present items as a hierarchical list Sep 30, 2024
Copy link
Contributor

@augustebaum augustebaum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like it to be possible to add items by clicking rather than dragging. Can you add this back?

@rouk1
Copy link
Contributor Author

rouk1 commented Sep 30, 2024

I'd like it to be possible to add items by clicking rather than dragging. Can you add this back?

This should be discussed with @anasstarfaoui this leads to question in the future. Where does a clicked item goes in the list ? Do we need to trigger a scroll to the added item ? Which cursor type should be use ? (For now on mouse press you get the drag cursor).

@tuscland
Copy link
Member

@anasstarfaoui @rouk1 could we use double-click to add an item to the end of the view?

thomass-dev
thomass-dev previously approved these changes Sep 30, 2024
@rouk1
Copy link
Contributor Author

rouk1 commented Sep 30, 2024

@anasstarfaoui @rouk1 could we use double-click to add an item to the end of the view?

It's done : )

@rouk1 rouk1 requested a review from augustebaum September 30, 2024 14:35
thomass-dev
thomass-dev previously approved these changes Oct 1, 2024
Copy link
Collaborator

@thomass-dev thomass-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice improvement with LUT, thanks!

@rouk1 rouk1 force-pushed the 335-ui-present-items-as-a-hierarchical-list branch from 4639815 to 3bdf179 Compare October 1, 2024 10:17
Copy link
Contributor

@augustebaum augustebaum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the rewrite of the double-click mechanic!

@augustebaum augustebaum merged commit 5eade98 into main Oct 1, 2024
4 checks passed
@augustebaum augustebaum deleted the 335-ui-present-items-as-a-hierarchical-list branch October 1, 2024 10:20
thomass-dev pushed a commit that referenced this pull request Dec 2, 2024
A new UI component is introduced: a tree accordion 🪗 

It can have as many nested level as needed and is collapsible.

Transforming a list of keys to tree structure is now done in the report
store. It's implemented in the `keysAsTree` function.

1. The function starts by initializing an empty array tree to hold the
root nodes of the tree structure.
2. It gets all the keys from the items object (or an empty object if
items is null).
3. The function then iterates over each key:
  a. It splits the key into segments, filtering out any empty segments.
  b. It identifies the root segment (first part of the path).
c. It checks if a node for this root segment already exists in the tree.
If not, it creates a new node and adds it to the tree.
  d. It then iterates through the remaining segments of the key:
     - For each segment, it builds the full path up to that point.
     - It checks if a child node with this path already exists.
- If not, it creates a new child node and adds it to the current node's
children.
     - It then moves to this child node for the next iteration.
4. After building the basic structure, it defines an addSelf function:
  - This function recursively goes through the tree.
- If a node's name matches a key in the original list and it has
children, it adds a "(self)" node as the first child.
- This handles cases where a path is both a key itself and has child
keys.
5. Finally, it applies the addSelf function to each root node in the
tree.
6. The function returns the completed tree structure.


Usage:

```vue
<script setup lang="ts">
import TreeAccordion, { type TreeAccordionNode } from "@/components/TreeAccordion.vue";

const fileTreeNodes: TreeAccordionNode[] = [
  {
    name: "fraud",
    children: [{ name: "fraud/accuracy" }, { name: "fraud/accuracy3" }],
  },
  {
    name: "fraud2",
    children: [{ name: "fraud2/accuracy" }, { name: "fraud2/accuracy3" }],
  },
  {
    name: "nested",
    children: [
      {
        name: "nested/fraud2/accuracy",
        children: [
          { name: "nested/fraud2/accuracy/self" },
          { name: "nested/fraud2/accuracy/self2" },
          { name: "nested/fraud2/accuracy/self3" },
        ],
      },
      { name: "nested/fraud2/accuracy3", children: [] },
    ],
  },
];
</script>

<template>
  <TreeAccordion :nodes="fileTreeNodes" />
</template
```


https://github.com/user-attachments/assets/b5d83778-1c40-429d-beec-1f20d6814dd9

Fixes #335
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[UI] Present items as a hierarchical list
4 participants