@spaceone/design-system
Version:
SpaceONE Design System
293 lines (282 loc) • 10 kB
text/mdx
import { Meta, Canvas, Story, ArgsTable } from '@storybook/addon-docs/blocks';
import PTree from './PTree.vue';
import PI from '@/foundation/icons/PI.vue'
import PIconButton from '@/inputs/buttons/icon-button/PIconButton.vue'
import PButton from '@/inputs/buttons/button/PButton.vue'
import PRadio from '@/inputs/radio/PRadio.vue'
import PTextInput from '@/inputs/input/PTextInput.vue';
import PFieldGroup from '@/inputs/forms/field-group/PFieldGroup.vue';
import faker from 'faker';
import { reactive, toRefs, computed } from '@vue/composition-api';
import {getTreeList, getTreeData, getTreeNode, getRecursiveInfo, getPermissionInfo} from './mock';
import './PTree.stories.pcss'
<Meta title='Data Display/Tree/Deprecated' parameters={{
design: {
type: 'figma',
url: 'https://www.figma.com/file/wq4wSowBcADBuUrMEZLz6i/SpaceONE-Console-Design?node-id=9570%3A199324',
},
}}
component={PTree} argTypes={{
onInit: {
name: 'init',
description: `Event emitted when the root node is ready`,
defaultValue: null,
table: {
type: {
summary: null,
},
defaultValue: {
summary: null,
},
category: 'events'
}
},
onDelete: {
name: 'delete',
description: `Event emitted when the node is deleted`,
defaultValue: null,
table: {
type: {
summary: null,
},
defaultValue: {
summary: null,
},
category: 'events'
}
},
onUpdateDrag: {
name: 'update-drag',
description: `Event emitted when there are changes by drag & drop`,
defaultValue: null,
table: {
type: {
summary: null,
},
defaultValue: {
summary: null,
},
category: 'events'
}
},
onFinishEdit: {
name: 'finish-edit',
description: `Event emitted when finish inline edit`,
defaultValue: null,
table: {
type: {
summary: null,
},
defaultValue: {
summary: null,
},
category: 'events'
}
},
onUpdateData: {
name: 'update-data',
description: `Event emitted when data is changed by \`setData()\``,
defaultValue: null,
table: {
type: {
summary: null,
},
defaultValue: {
summary: null,
},
category: 'events'
}
},
}}/>
export const ExpertTemplate = () => ({
components: { PTree, PI, PIconButton, PButton, PRadio, PTextInput, PFieldGroup },
template: `
<div class="h-full w-full p-4 overflow-auto">
<div class="mb-4">
<p-button style-type="primary1" ="refresh">Refresh</p-button>
<p-button style-type="secondary" ="add">Add node to root</p-button>
<p-button style-type="safe" ="onClickEdit">
{{editMode ? 'Done' : 'Edit' }}
</p-button>
<p-button style-type="primary" ="findNode">Find node</p-button>
{{target}}
</div>
<div class="p-tree-template flex flex-wrap">
<p-tree id-key="id"
children-key="has_child"
:selected-nodes.sync="selectedNodes"
:data-fetcher="dataFetcher"
:select-options="selectOptions"
:edit-options="editOptions"
:drag-options="dragOptions"
:get-class-names="getClassNames"
fetch-on-init
="onTreeInit"
-drag="onUpdateDrag"
class="w-1/2"
>
<template #data="{node}">
{{ node.data.name }} ({{node.data.id}})
</template>
<template #toggle="{node}">
<p-radio v-if="!node.loading && node.data.item_type === 'PROJECT'"
:selected="node.selected" :value="true"
.stop="node.setSelected(true)"
/>
</template>
<template #toggle-right>
<p-i name="ic_bookmark"
width="1rem" height="1rem"
color="inherit"
/>
</template>
<template #icon="{node}">
<template v-if="editMode">
<p-i v-if="node.data.item_type === 'PROJECT_GROUP'"
:name="permissionInfo[node.data.id] ? 'ic_tree_project-group' : 'ic_tree_project-group_locked'"
width="1rem" height="1rem" color="inherit"
/>
</template>
<p-i v-else :name="node.data.item_type === 'PROJECT' ? 'ic_tree_project' : 'ic_tree_project-group'"
width="1rem" height="1rem" color="inherit transparent"
/>
</template>
<template #right-extra="{node}">
<p-icon-button v-if="editMode && permissionInfo[node.data.id]" name="ic_minus"
color="inherit transparent"
size="sm"
.stop="node.deleteNode()"
/>
<p-icon-button v-else name="ic_plus"
class="add-btn"
size="sm"
.stop="node.addChild(getTreeData())"
/>
</template>
</p-tree>
<div class="p-4 w-1/2">
<pre>{{selectedNodes.map(d => d.data)}}</pre>
</div>
</div>
</div>
`,
setup() {
const state = reactive({
root: null,
selectedNodes: [],
firstSelectedNode: computed(() => state.selectedNodes[0] || null),
selectOptions: {
validator({data}) {
return data.item_type === 'PROJECT'
}
},
editOptions: computed(() => ({
disabled: !state.editMode,
editStartValidator: (item) => {
return state.permissionInfo[item.data.id]
},
validator: (text) => (text && text.length > 2 && text.length < 40),
invalidText: 'should NOT be shorter than 2 characters',
dataSetter(text, originData) {
return {
...originData,
name: text
}
},
dataGetter(data) {
return data.name
}
})),
dragOptions: computed(() => ({
disabled: !state.editMode,
dragValidator(node) {
return true //!!state.permissionInfo[node.data.id]
},
dropValidator(node) {
return true //!!state.permissionInfo[node.data.id]
}
})),
editMode: false,
permissionInfo: {},
findMode: false,
lists: [],
target: ''
})
let dataFetcher = (item) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
let res;
if (state.findMode) {
res = state.lists[item ? item.level : 0]
} else {
res = getTreeList()
}
if (state.editMode && Array.isArray(res)) {
res.forEach(d => {state.permissionInfo[d.id] = faker.random.boolean();})
}
resolve(res)
}, 500)
})
}
const getClassNames = (item) => {
if (state.editMode && !state.permissionInfo[item._id]) return 'no-permission'
else return ''
}
const refresh = async () => {
if (state.root) {
state.selectedNodes = []
const res = await dataFetcher()
await state.root.setChildren(res)
}
}
const add = () => {
state.root.addChild(getTreeData())
}
const onClickEdit = () => {
state.editMode = !state.editMode;
if (state.editMode && state.root) {
state.permissionInfo = getPermissionInfo(state.root.getChildrenNodes())
}
}
const findNode = async () => {
const {lists, paths} = getRecursiveInfo()
state.findMode = true;
state.lists = lists;
state.target = paths[paths.length - 1];
if (state.root) {
const res = await state.root.findNode(state.target, paths);
if(res) res.setSelected(true)
}
state.findMode = false;
}
const onTreeInit = async (root) => {
state.root = root;
}
const onUpdateDrag = (item) => {
console.log('Update Drag', item)
}
return {
...toRefs(state),
dataFetcher,
getClassNames,
refresh,
add,
onClickEdit,
onTreeInit,
onUpdateDrag,
getTreeData,
getTreeNode,
findNode,
}
}
});
# Tree
<br/>
<br/>
## Expert Case
<Canvas>
<Story name="Expert Case">
{ExpertTemplate.bind({})}
</Story>
</Canvas>
<ArgsTable story="Expert Case" />