diff --git a/src/scripts/js/es6/common/vuecomponents/init.js b/src/scripts/js/es6/common/vuecomponents/init.js
index 5f42b6b3..6cd6b180 100644
--- a/src/scripts/js/es6/common/vuecomponents/init.js
+++ b/src/scripts/js/es6/common/vuecomponents/init.js
@@ -2,13 +2,13 @@ import './comments/CommentTree'
import './customdirectives/click-outside'
import { UnitOfWorkTracker } from './mixins/UnitOfWorkTracker'
import { BrowserHistoryState, StateSaveMode } from './mixins/BrowserHistoryState'
-import { PillarTable } from './table/Table'
+import { PillarTable, TableState } from './table/Table'
import { CellPrettyDate } from './table/cells/renderer/CellPrettyDate'
import { CellDefault } from './table/cells/renderer/CellDefault'
import { ColumnBase } from './table/columns/ColumnBase'
import { ColumnFactoryBase } from './table/columns/ColumnFactoryBase'
import { RowObjectsSourceBase } from './table/rows/RowObjectsSourceBase'
-import { RowBase, RowState } from './table/rows/RowObjectBase'
+import { RowBase } from './table/rows/RowObjectBase'
import { RowFilter } from './table/filter/RowFilter'
let mixins = {
@@ -19,6 +19,7 @@ let mixins = {
let table = {
PillarTable,
+ TableState,
columns: {
ColumnBase,
ColumnFactoryBase,
@@ -32,7 +33,6 @@ let table = {
rows: {
RowObjectsSourceBase,
RowBase,
- RowState,
},
filter: {
RowFilter
diff --git a/src/scripts/js/es6/common/vuecomponents/table/Table.js b/src/scripts/js/es6/common/vuecomponents/table/Table.js
index 810b6fd0..bc9149b2 100644
--- a/src/scripts/js/es6/common/vuecomponents/table/Table.js
+++ b/src/scripts/js/es6/common/vuecomponents/table/Table.js
@@ -3,7 +3,25 @@ import './rows/renderer/Row'
import './filter/ColumnFilter'
import './filter/RowFilter'
import {UnitOfWorkTracker} from '../mixins/UnitOfWorkTracker'
-import {RowState} from './rows/RowObjectBase'
+
+/**
+ * Table State
+ *
+ * Used to restore a table to a given state.
+ */
+class TableState {
+ constructor(selectedIds) {
+ this.selectedIds = selectedIds || [];
+ }
+
+ /**
+ * Apply state to row
+ * @param {RowBase} rowObject
+ */
+ applyRowState(rowObject) {
+ rowObject.isSelected = this.selectedIds.includes(rowObject.getId());
+ }
+}
const TEMPLATE =`
`;
+/**
+ * The table renders RowObject instances for the rows, and ColumnBase instances for the Columns.
+ * Extend the table to fit your needs.
+ *
+ * Usage:
+ * Extend RowBase to wrap the data you want in your row
+ * Extend ColumnBase once per column type you need
+ * Extend RowObjectsSourceBase to fetch and initialize your rows
+ * Extend ColumnFactoryBase to create the rows for your table
+ * Extend This Table with your ColumnFactory and RowSource
+ *
+ * @emits isInitialized When all rows has been fetched, and are initialized.
+ * @emits selectItemsChanged(selectedItems) When selected rows has changed.
+ */
let PillarTable = Vue.component('pillar-table-base', {
template: TEMPLATE,
mixins: [UnitOfWorkTracker],
@@ -64,15 +96,18 @@ let PillarTable = Vue.component('pillar-table-base', {
visibleRowObjects: [],
rowsSource: {},
isInitialized: false,
- compareRows: (row1, row2) => 0
+ compareRowsCB: (row1, row2) => 0
}
},
computed: {
rowObjects() {
return this.rowsSource.rowObjects || [];
},
+ /**
+ * Rows sorted with a column sorter
+ */
sortedRowObjects() {
- return this.rowObjects.concat().sort(this.compareRows);
+ return this.rowObjects.concat().sort(this.compareRowsCB);
},
rowAndChildObjects() {
let all = [];
@@ -105,19 +140,19 @@ let PillarTable = Vue.component('pillar-table-base', {
let columnFactory = new this.$options.columnFactory(this.projectId);
this.rowsSource = new this.$options.rowsSource(this.projectId);
- let rowState = new RowState(this.selectedIds);
+ let tableState = new TableState(this.selectedIds);
this.unitOfWork(
Promise.all([
columnFactory.thenGetColumns(),
- this.rowsSource.thenFetchObjects()
+ this.rowsSource.thenGetRowObjects()
])
.then((resp) => {
this.columns = resp[0];
return this.rowsSource.thenInit();
})
.then(() => {
- this.rowAndChildObjects.forEach(rowState.applyState.bind(rowState));
+ this.rowAndChildObjects.forEach(tableState.applyRowState.bind(tableState));
this.isInitialized = true;
})
);
@@ -133,10 +168,11 @@ let PillarTable = Vue.component('pillar-table-base', {
function compareRows(r1, r2) {
return column.compareRows(r1, r2) * direction;
}
- this.compareRows = compareRows;
+ this.compareRowsCB = compareRows;
},
onItemClicked(clickEvent, itemId) {
if(!this.canChangeSelectionCB()) return;
+
if(this.isMultiToggleClick(clickEvent) && this.canMultiSelect) {
let slectedIdsWithoutClicked = this.selectedIds.filter(id => id !== itemId);
if (slectedIdsWithoutClicked.length < this.selectedIds.length) {
@@ -144,7 +180,7 @@ let PillarTable = Vue.component('pillar-table-base', {
} else {
this.selectedIds = [itemId, ...this.selectedIds];
}
- } else if(this.isSelectBetween(clickEvent) && this.canMultiSelect) {
+ } else if(this.isSelectBetweenClick(clickEvent) && this.canMultiSelect) {
if (this.selectedIds.length > 0) {
let betweenA = this.selectedIds[this.selectedIds.length -1];
let betweenB = itemId;
@@ -162,13 +198,19 @@ let PillarTable = Vue.component('pillar-table-base', {
}
}
},
- isSelectBetween(clickEvent) {
+ isSelectBetweenClick(clickEvent) {
return clickEvent.shiftKey;
},
isMultiToggleClick(clickEvent) {
return clickEvent.ctrlKey ||
clickEvent.metaKey; // Mac command key
},
+ /**
+ * Get visible rows between id1 and id2
+ * @param {String} id1
+ * @param {String} id2
+ * @returns {Array(RowObjects)}
+ */
rowsBetween(id1, id2) {
let hasFoundFirst = false;
let hasFoundLast = false;
@@ -185,4 +227,4 @@ let PillarTable = Vue.component('pillar-table-base', {
}
});
-export { PillarTable }
+export { PillarTable, TableState }
diff --git a/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/CellDefault.js b/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/CellDefault.js
index e3c433be..8a9a71f1 100644
--- a/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/CellDefault.js
+++ b/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/CellDefault.js
@@ -4,6 +4,10 @@ const TEMPLATE =`
`;
+/**
+ * Default cell renderer. Takes raw cell value and formats it.
+ * Override for custom formatting of value.
+ */
let CellDefault = Vue.component('pillar-cell-default', {
template: TEMPLATE,
props: {
diff --git a/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/CellPrettyDate.js b/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/CellPrettyDate.js
index f158d552..dc884568 100644
--- a/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/CellPrettyDate.js
+++ b/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/CellPrettyDate.js
@@ -1,5 +1,9 @@
import { CellDefault } from './CellDefault'
+/**
+ * Formats raw values as "pretty date".
+ * Expects rawCellValue to be a date.
+ */
let CellPrettyDate = Vue.component('pillar-cell-pretty-date', {
extends: CellDefault,
computed: {
diff --git a/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/CellProxy.js b/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/CellProxy.js
index c5838cdc..ac3322de 100644
--- a/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/CellProxy.js
+++ b/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/CellProxy.js
@@ -10,22 +10,39 @@ const TEMPLATE =`
/>
`;
+/**
+ * Renders the cell that the column requests.
+ *
+ * @emits item-clicked(mouseEvent,itemId) Re-emits if real cell is emitting it
+ */
let CellProxy = Vue.component('pillar-cell-proxy', {
template: TEMPLATE,
props: {
- column: Object,
- rowObject: Object
+ column: Object, // ColumnBase
+ rowObject: Object // RowObject
},
computed: {
+ /**
+ * Raw unformated cell value
+ */
rawCellValue() {
return this.column.getRawCellValue(this.rowObject) || '';
},
+ /**
+ * Name of the cell render component to be rendered
+ */
cellRenderer() {
return this.column.getCellRenderer(this.rowObject);
},
+ /**
+ * Css classes to apply to the cell
+ */
cellClasses() {
return this.column.getCellClasses(this.rawCellValue, this.rowObject);
},
+ /**
+ * Cell tooltip
+ */
cellTitle() {
return this.column.getCellTitle(this.rawCellValue, this.rowObject);
}
diff --git a/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/HeadCell.js b/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/HeadCell.js
index 97facd37..3416b20c 100644
--- a/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/HeadCell.js
+++ b/src/scripts/js/es6/common/vuecomponents/table/cells/renderer/HeadCell.js
@@ -22,6 +22,11 @@ const TEMPLATE =`
`;
+/**
+ * A cell in the Header of the table
+ *
+ * @emits sort(column,direction) When user clicks column sort arrows.
+ */
Vue.component('pillar-head-cell', {
template: TEMPLATE,
props: {
diff --git a/src/scripts/js/es6/common/vuecomponents/table/columns/ColumnBase.js b/src/scripts/js/es6/common/vuecomponents/table/columns/ColumnBase.js
index 29cfa8f9..a3532e96 100644
--- a/src/scripts/js/es6/common/vuecomponents/table/columns/ColumnBase.js
+++ b/src/scripts/js/es6/common/vuecomponents/table/columns/ColumnBase.js
@@ -1,5 +1,9 @@
import { CellDefault } from '../cells/renderer/CellDefault'
+/**
+ * Column logic
+ */
+
let nextColumnId = 0;
export class ColumnBase {
constructor(displayName, columnType) {
@@ -13,13 +17,18 @@ export class ColumnBase {
/**
*
- * @param {*} rowObject
+ * @param {RowObject} rowObject
* @returns {String} Name of the Cell renderer component
*/
getCellRenderer(rowObject) {
return CellDefault.options.name;
}
+ /**
+ *
+ * @param {RowObject} rowObject
+ * @returns {*} Raw unformated value
+ */
getRawCellValue(rowObject) {
// Should be overridden
throw Error('Not implemented');
@@ -38,7 +47,7 @@ export class ColumnBase {
/**
* Object with css classes to use on the header cell
- * @returns {Any} Object with css classes
+ * @returns {Object} Object with css classes
*/
getHeaderCellClasses() {
// Should be overridden
diff --git a/src/scripts/js/es6/common/vuecomponents/table/columns/ColumnFactoryBase.js b/src/scripts/js/es6/common/vuecomponents/table/columns/ColumnFactoryBase.js
index 18c1fa6a..878782e9 100644
--- a/src/scripts/js/es6/common/vuecomponents/table/columns/ColumnFactoryBase.js
+++ b/src/scripts/js/es6/common/vuecomponents/table/columns/ColumnFactoryBase.js
@@ -1,10 +1,16 @@
+/**
+ * Provides the columns that are available in a table.
+ */
class ColumnFactoryBase{
constructor(projectId) {
this.projectId = projectId;
this.projectPromise;
}
- // Override this
+ /**
+ * To be overridden for your purposes
+ * @returns {Promise(ColumnBase)} The columns that are available in the table.
+ */
thenGetColumns() {
throw Error('Not implemented')
}
@@ -19,3 +25,4 @@ class ColumnFactoryBase{
}
export { ColumnFactoryBase }
+
diff --git a/src/scripts/js/es6/common/vuecomponents/table/columns/renderer/Column.js b/src/scripts/js/es6/common/vuecomponents/table/columns/renderer/Column.js
deleted file mode 100644
index d22392bc..00000000
--- a/src/scripts/js/es6/common/vuecomponents/table/columns/renderer/Column.js
+++ /dev/null
@@ -1,10 +0,0 @@
-const TEMPLATE =`
-
-`;
-
-Vue.component('pillar-table-column', {
- template: TEMPLATE,
- props: {
- column: Object
- },
-});
diff --git a/src/scripts/js/es6/common/vuecomponents/table/filter/ColumnFilter.js b/src/scripts/js/es6/common/vuecomponents/table/filter/ColumnFilter.js
index 222e9532..0ca380a4 100644
--- a/src/scripts/js/es6/common/vuecomponents/table/filter/ColumnFilter.js
+++ b/src/scripts/js/es6/common/vuecomponents/table/filter/ColumnFilter.js
@@ -25,14 +25,27 @@ const TEMPLATE =`
`;
+class ColumnState{
+ constructor(id, displayName, isVisible) {
+ this.id = id;
+ this.displayName = displayName;
+ this.isVisible = isVisible;
+ }
+}
+
+/**
+ * Component to select what columns to render in the table.
+ *
+ * @emits visibleColumnsChanged(columns) When visible columns has changed
+ */
let Filter = Vue.component('pillar-table-column-filter', {
template: TEMPLATE,
props: {
- columns: Array,
+ columns: Array, // Instances of ColumnBase
},
data() {
return {
- columnStates: [],
+ columnStates: [], // Instances of ColumnState
}
},
computed: {
@@ -57,18 +70,16 @@ let Filter = Vue.component('pillar-table-column-filter', {
setColumnStates() {
return this.columns.reduce((states, c) => {
if (!c.isMandatory) {
- states.push({
- _id: c._id,
- displayName: c.displayName,
- isVisible: true,
- });
+ states.push(
+ new ColumnState(c._id, c.displayName, true)
+ );
}
return states;
}, [])
},
isColumnStateVisible(column) {
for (let state of this.columnStates) {
- if (state._id === column._id) {
+ if (state.id === column._id) {
return state.isVisible;
}
}
diff --git a/src/scripts/js/es6/common/vuecomponents/table/filter/RowFilter.js b/src/scripts/js/es6/common/vuecomponents/table/filter/RowFilter.js
index 098627a2..6282c200 100644
--- a/src/scripts/js/es6/common/vuecomponents/table/filter/RowFilter.js
+++ b/src/scripts/js/es6/common/vuecomponents/table/filter/RowFilter.js
@@ -7,6 +7,9 @@ const TEMPLATE =`
`;
+/**
+ * @emits visibleRowObjectsChanged(rowObjects) When the what objects to be visible has changed.
+ */
let RowFilter = Vue.component('pillar-table-row-filter', {
template: TEMPLATE,
props: {
diff --git a/src/scripts/js/es6/common/vuecomponents/table/rows/RowObjectBase.js b/src/scripts/js/es6/common/vuecomponents/table/rows/RowObjectBase.js
index a24c99b6..02394e43 100644
--- a/src/scripts/js/es6/common/vuecomponents/table/rows/RowObjectBase.js
+++ b/src/scripts/js/es6/common/vuecomponents/table/rows/RowObjectBase.js
@@ -1,26 +1,16 @@
-class RowState {
- constructor(selectedIds) {
- this.selectedIds = selectedIds || [];
- }
-
- /**
- *
- * @param {RowBase} rowObject
- */
- applyState(rowObject) {
- rowObject.isSelected = this.selectedIds.includes(rowObject.getId());
- }
-}
-
+/**
+ * Each object to be visualized in the table is wrapped in a RowBase object. Column cells interact with it,
+ */
class RowBase {
constructor(underlyingObject) {
this.underlyingObject = underlyingObject;
this.isInitialized = false;
- this.isVisible = true;
this.isSelected = false;
}
-
+ /**
+ * Called after the row has been created to initalize async properties. Fetching child objects for instance
+ */
thenInit() {
return this._thenInitImpl()
.then(() => {
@@ -28,6 +18,9 @@ class RowBase {
})
}
+ /**
+ * Override to initialize async properties such as fetching child objects.
+ */
_thenInitImpl() {
return Promise.resolve();
}
@@ -44,15 +37,21 @@ class RowBase {
return this.underlyingObject.properties;
}
+ /**
+ * The css classes that should be applied to the row in the table
+ */
getRowClasses() {
return {
"is-busy": !this.isInitialized
}
}
+ /**
+ * A row could have children (shots has tasks for example). Children should also be instances of RowObject
+ */
getChildObjects() {
return [];
}
}
-export { RowBase, RowState }
+export { RowBase }
diff --git a/src/scripts/js/es6/common/vuecomponents/table/rows/RowObjectsSourceBase.js b/src/scripts/js/es6/common/vuecomponents/table/rows/RowObjectsSourceBase.js
index cb3d4139..429b733a 100644
--- a/src/scripts/js/es6/common/vuecomponents/table/rows/RowObjectsSourceBase.js
+++ b/src/scripts/js/es6/common/vuecomponents/table/rows/RowObjectsSourceBase.js
@@ -1,14 +1,24 @@
+/**
+ * The provider of RowObjects to a table.
+ * Extend to fit your purpose.
+ */
class RowObjectsSourceBase {
constructor(projectId) {
this.projectId = projectId;
this.rowObjects = [];
}
- // Override this
- thenFetchObjects() {
+ /**
+ * Should be overriden to fetch and create the row objects to we rendered in the table. The Row objects should be stored in
+ * this.rowObjects
+ */
+ thenGetRowObjects() {
throw Error('Not implemented');
}
+ /**
+ * Inits all its row objects.
+ */
thenInit() {
return Promise.all(
this.rowObjects.map(it => it.thenInit())
diff --git a/src/scripts/js/es6/common/vuecomponents/table/rows/renderer/Head.js b/src/scripts/js/es6/common/vuecomponents/table/rows/renderer/Head.js
index d71a88b2..d614f8e1 100644
--- a/src/scripts/js/es6/common/vuecomponents/table/rows/renderer/Head.js
+++ b/src/scripts/js/es6/common/vuecomponents/table/rows/renderer/Head.js
@@ -9,7 +9,9 @@ const TEMPLATE =`
/>
`;
-
+/**
+ * @emits sort(column,direction) When a column head has been clicked
+ */
Vue.component('pillar-table-head', {
template: TEMPLATE,
props: {
diff --git a/src/scripts/js/es6/common/vuecomponents/table/rows/renderer/Row.js b/src/scripts/js/es6/common/vuecomponents/table/rows/renderer/Row.js
index a74758a9..7f2e0e31 100644
--- a/src/scripts/js/es6/common/vuecomponents/table/rows/renderer/Row.js
+++ b/src/scripts/js/es6/common/vuecomponents/table/rows/renderer/Row.js
@@ -15,7 +15,9 @@ const TEMPLATE =`
/>
`;
-
+/**
+ * @emits item-clicked(mouseEvent,itemId) When a RowObject has been clicked
+ */
Vue.component('pillar-table-row', {
template: TEMPLATE,
props: {