Vue Attract: Sort/filterable table based on Vue

Initial commit implementing sortable and filterable tables for attract
using Vue.
This commit is contained in:
2019-02-12 09:08:37 +01:00
parent 66212ec5fa
commit 5e73720d91
51 changed files with 1375 additions and 485 deletions

View File

@@ -0,0 +1,40 @@
let PillarTable = pillar.vuecomponents.table.PillarTable;
import {TasksColumnFactory} from './columns/TasksColumnFactory'
import {TaskRowsSource} from './rows/TaskRowsSource'
import {RowFilter} from '../attracttable/filter/RowFilter'
const TEMPLATE =`
<div class="pillar-table-actions">
<button class="action"
v-if="canAddTask"
@click="createNewTask"
>
<i class="pi-plus">New Task</i>
</button>
</div>
`;
let TableActions = {
template: TEMPLATE,
computed: {
canAddTask() {
let projectId = ProjectUtils.projectId();
return attract.auth.AttractAuth.canUserCreateTask(projectId);
}
},
methods: {
createNewTask() {
task_create(undefined, 'generic');
}
},
}
Vue.component('attract-tasks-table', {
extends: PillarTable,
columnFactory: TasksColumnFactory,
rowsSource: TaskRowsSource,
components: {
'pillar-table-actions': TableActions,
'pillar-table-row-filter': RowFilter,
}
});

View File

@@ -0,0 +1,42 @@
let CellDefault = pillar.vuecomponents.table.cells.renderer.CellDefault;
const TEMPLATE =`
<div>
<a
v-if="rawCellValue"
@click.prevent="onClick()"
:href="cellLink"
>
{{ cellValue }}
</a>
</div>
`;
let ParentNameCell = Vue.component('pillar-cell-parent-name', {
extends: CellDefault,
template: TEMPLATE,
computed: {
cellTitle() {
return this.rawCellValue;
},
cellLink() {
let project_url = ProjectUtils.projectUrl();
let item_type = this.itemType();
return `/attract/${project_url}/${item_type}s/${this.rowObject.getParent()._id}`;
},
embededLink() {
return this.cellLink;
}
},
methods: {
onClick() {
item_open(this.rowObject.getParent()._id, this.itemType(), false, ProjectUtils.projectUrl());
},
itemType() {
let node_type = this.rowObject.getParent().node_type;
return node_type.replace('attract_', ''); // eg. attract_task to tasks
}
},
});
export { ParentNameCell }

View File

@@ -0,0 +1,30 @@
let ColumnBase = pillar.vuecomponents.table.columns.ColumnBase;
import {ParentNameCell} from '../cells/ParentName'
class ParentName extends ColumnBase {
constructor() {
super('Parent', 'parent-name');
}
getCellRenderer(rowObject) {
return ParentNameCell.options.name;
}
getRawCellValue(rowObject) {
if(!rowObject.getParent()) return '';
return rowObject.getParent().name || '<No Name>';
}
compareRows(rowObject1, rowObject2) {
let parent1 = rowObject1.getParent();
let parent2 = rowObject2.getParent();
if (parent1 && parent2) {
if (parent1.name === parent2.name) {
return parent1._id < parent2._id ? -1 : 1;
}
}
return super.compareRows(rowObject1, rowObject2);
}
}
export { ParentName }

View File

@@ -0,0 +1,13 @@
let ColumnBase = pillar.vuecomponents.table.columns.ColumnBase;
class ShortCode extends ColumnBase {
constructor() {
super('Short Code', 'short-code');
}
getRawCellValue(rowObject) {
return rowObject.getTask().properties.shortcode || '';
}
}
export { ShortCode }

View File

@@ -0,0 +1,13 @@
let ColumnBase = pillar.vuecomponents.table.columns.ColumnBase;
class TaskType extends ColumnBase {
constructor() {
super('Type', 'task-type');
}
getRawCellValue(rowObject) {
return rowObject.getTask().properties.task_type || '';
}
}
export { TaskType }

View File

@@ -0,0 +1,27 @@
import { Status } from '../../attracttable/columns/Status'
import { RowObject } from '../../attracttable/columns/RowObject'
import { TaskDueDate } from '../../attracttable/columns/TaskDueDate'
import { TaskType } from './TaskType'
import { ShortCode } from './ShortCode'
import { ParentName } from './ParentName'
let ColumnFactoryBase = pillar.vuecomponents.table.columns.ColumnFactoryBase;
class TasksColumnFactory extends ColumnFactoryBase{
thenGetColumns() {
return this.thenGetProject()
.then((project) => {
return [
new Status(),
new ParentName(),
new RowObject(),
new ShortCode(),
new TaskType(),
new TaskDueDate(),
];
})
}
}
export { TasksColumnFactory }

View File

@@ -0,0 +1,29 @@
import {AttractRowBase} from '../../attracttable/rows/AttractRowBase'
class TaskRow extends AttractRowBase {
constructor(task) {
super(task);
this.parent = undefined;
if (task.parent) {
// Deattach parent from task to avoid parent to be overwritten when task is updated
let parentId = task.parent._id;
this.parent = task.parent;
task.parent = parentId;
pillar.events.Nodes.onUpdated(parentId, this.onParentUpdated.bind(this));
}
}
getTask() {
return this.underlyingObject;
}
getParent() {
return this.parent;
}
onParentUpdated(event, updatedObj) {
this.parent = updatedObj;
}
}
export { TaskRow }

View File

@@ -0,0 +1,18 @@
import { AttractRowsSourceBase } from '../../attracttable/rows/AttractRowsSourceBase'
import { TaskRow } from './TaskRow'
class TaskRowsSource extends AttractRowsSourceBase {
constructor(projectId) {
super(projectId, 'attract_task', TaskRow);
}
thenInit() {
return attract.api.thenGetProjectTasks(this.projectId)
.then((result) => {
let tasks = result._items;
this.initRowObjects(tasks);
});
}
}
export { TaskRowsSource }