Vue Shared - New component `nested_groups_projects_list.vue`
What / Why
- Part of &13791
We are aiming to create a more consistent experience across all Group Lists in GitLab. We have created a shared groups_list.vue
that is intended to be the SSoT for all singular group lists in GitLab.
Additionally, we would like to add a similar SSoT component for tree like lists that utilize a tree like structure. This component could be called nested_groups_projects_list.vue
. There is an existing Vue component that does tree few on Groups/Subgroups found in group_folder.vue
This is a good starting point, but ideally we could create a new, more flexible, component that could support a tree of Groups and Projects to meet the upcoming requirements of &13790 (closed).
Implementation Plan
Pulled from @peterhegman comments below
Directory
.
├── groups_list/
│ ├── groups_list_item.vue
│ └── groups_list.vue
├── projects_list/
│ ├── projects_list_item.vue
│ └── projects_list.vue
└── nested_groups_projects_list/
├── list_item.vue
└── nested_groups_projects_list.vue
Nested data structure
This is the simplified structure the API returns. I removed everything that wasn't relevant to this example. As the user dives into each subgroup items are added to the children
array
[
{
"id": 205,
"type": "group",
"parent_id": 31,
"subgroup_count": 1,
"project_count": 1,
"children": [
{
"id": 224,
"type": "group",
"parent_id": 205,
"subgroup_count": 0,
"project_count": 0,
"children": []
},
{
"id": 45,
"type": "project",
}
]
},
{
"id": 6,
"type": "project",
}
]
nested_groups_projects_list/list_item.vue
logic
Docs:
- https://v2.vuejs.org/v2/guide/components-edge-cases.html?redirect=true#Circular-References-Between-Components
- https://v2.vuejs.org/v2/examples/tree-view
<script>
export default {
props: {
item: {
type: Object,
required: true
}
},
beforeCreate: function () {
this.$options.components.ListItem = require('./list_item.vue').default
},
computed: {
itemComponent() {
return this.item.type === 'project' ? ProjectsListItem : GroupsListItem;
}
}
}
<script>
<template>
<component :is="itemComponent">
<ul v-if="item.children.length">
<list-item v-for="childItem in item.children" :item="childItem" />
</ul>
</component>
<template>
nested_groups_projects_list/nested_groups_projects_list.vue
logic
<script>
export default {
props: {
items: {
type: Array,
required: true
}
},
}
<script>
<template>
<ul>
<list-item v-for="item in items" :item="item" />
</ul>
<template>
The above code is untested but I think it should at least be close to working.