mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-11-08 20:21:57 +01:00
ONOS-3780: Table model now handles two column sorts.
Change-Id: I8899d56fdca2084e4a7ca0392c21d14f1bc6ea62
This commit is contained in:
parent
ed627a58ed
commit
051e9faa1b
@ -52,6 +52,7 @@ public class TableModel {
|
|||||||
|
|
||||||
private static final CellComparator DEF_CMP = DefaultCellComparator.INSTANCE;
|
private static final CellComparator DEF_CMP = DefaultCellComparator.INSTANCE;
|
||||||
private static final CellFormatter DEF_FMT = DefaultCellFormatter.INSTANCE;
|
private static final CellFormatter DEF_FMT = DefaultCellFormatter.INSTANCE;
|
||||||
|
private static final String EMPTY = "";
|
||||||
|
|
||||||
private final String[] columnIds;
|
private final String[] columnIds;
|
||||||
private final Set<String> idSet;
|
private final Set<String> idSet;
|
||||||
@ -206,14 +207,17 @@ public class TableModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts the table rows based on the specified column, in the
|
* Sorts the table rows based on the specified columns, in the
|
||||||
* specified direction.
|
* specified directions. The second column is optional, and can be
|
||||||
|
* disregarded by passing null into id2 and dir2.
|
||||||
*
|
*
|
||||||
* @param columnId column identifier
|
* @param id1 first column identifier
|
||||||
* @param dir sort direction
|
* @param dir1 first column sort direction
|
||||||
|
* @param id2 second column identifier (may be null)
|
||||||
|
* @param dir2 second column sort direction (may be null)
|
||||||
*/
|
*/
|
||||||
public void sort(String columnId, SortDir dir) {
|
public void sort(String id1, SortDir dir1, String id2, SortDir dir2) {
|
||||||
Collections.sort(rows, new RowComparator(columnId, dir));
|
Collections.sort(rows, new RowComparator(id1, dir1, id2, dir2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -225,33 +229,54 @@ public class TableModel {
|
|||||||
DESC
|
DESC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean nullOrEmpty(String s) {
|
||||||
|
return s == null || EMPTY.equals(s.trim());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Row comparator.
|
* Row comparator.
|
||||||
*/
|
*/
|
||||||
private class RowComparator implements Comparator<Row> {
|
private class RowComparator implements Comparator<Row> {
|
||||||
private final String columnId;
|
private final String id1;
|
||||||
private final SortDir dir;
|
private final SortDir dir1;
|
||||||
private final CellComparator cellComparator;
|
private final String id2;
|
||||||
|
private final SortDir dir2;
|
||||||
|
private final CellComparator cc1;
|
||||||
|
private final CellComparator cc2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a row comparator based on the specified
|
* Constructs a row comparator based on the specified
|
||||||
* column identifier and sort direction.
|
* column identifiers and sort directions. Note that id2 and dir2 may
|
||||||
|
* be null.
|
||||||
*
|
*
|
||||||
* @param columnId column identifier
|
* @param id1 first column identifier
|
||||||
* @param dir sort direction
|
* @param dir1 first column sort direction
|
||||||
|
* @param id2 second column identifier
|
||||||
|
* @param dir2 second column sort direction
|
||||||
*/
|
*/
|
||||||
public RowComparator(String columnId, SortDir dir) {
|
public RowComparator(String id1, SortDir dir1, String id2, SortDir dir2) {
|
||||||
this.columnId = columnId;
|
this.id1 = id1;
|
||||||
this.dir = dir;
|
this.dir1 = dir1;
|
||||||
cellComparator = getComparator(columnId);
|
this.id2 = id2;
|
||||||
|
this.dir2 = dir2;
|
||||||
|
cc1 = getComparator(id1);
|
||||||
|
cc2 = nullOrEmpty(id2) ? null : getComparator(id2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(Row a, Row b) {
|
public int compare(Row a, Row b) {
|
||||||
Object cellA = a.get(columnId);
|
Object cellA = a.get(id1);
|
||||||
Object cellB = b.get(columnId);
|
Object cellB = b.get(id1);
|
||||||
int result = cellComparator.compare(cellA, cellB);
|
int result = cc1.compare(cellA, cellB);
|
||||||
return dir == SortDir.ASC ? result : -result;
|
result = dir1 == SortDir.ASC ? result : -result;
|
||||||
|
|
||||||
|
if (result == 0 && cc2 != null) {
|
||||||
|
cellA = a.get(id2);
|
||||||
|
cellB = b.get(id2);
|
||||||
|
result = cc2.compare(cellA, cellB);
|
||||||
|
result = dir2 == SortDir.ASC ? result : -result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,13 +20,23 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
|
|||||||
import org.onosproject.ui.JsonUtils;
|
import org.onosproject.ui.JsonUtils;
|
||||||
import org.onosproject.ui.RequestHandler;
|
import org.onosproject.ui.RequestHandler;
|
||||||
|
|
||||||
|
import static org.onosproject.ui.table.TableModel.sortDir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message handler specifically for table views.
|
* Message handler specifically for table views.
|
||||||
*/
|
*/
|
||||||
public abstract class TableRequestHandler extends RequestHandler {
|
public abstract class TableRequestHandler extends RequestHandler {
|
||||||
|
|
||||||
|
private static final String FIRST_COL = "firstCol";
|
||||||
|
private static final String FIRST_DIR = "firstDir";
|
||||||
|
private static final String SECOND_COL = "secondCol";
|
||||||
|
private static final String SECOND_DIR = "secondDir";
|
||||||
|
|
||||||
|
private static final String ASC = "asc";
|
||||||
|
|
||||||
private static final String ANNOTS = "annots";
|
private static final String ANNOTS = "annots";
|
||||||
private static final String NO_ROWS_MSG_KEY = "no_rows_msg";
|
private static final String NO_ROWS_MSG_KEY = "no_rows_msg";
|
||||||
|
|
||||||
private final String respType;
|
private final String respType;
|
||||||
private final String nodeName;
|
private final String nodeName;
|
||||||
|
|
||||||
@ -51,9 +61,11 @@ public abstract class TableRequestHandler extends RequestHandler {
|
|||||||
TableModel tm = createTableModel();
|
TableModel tm = createTableModel();
|
||||||
populateTable(tm, payload);
|
populateTable(tm, payload);
|
||||||
|
|
||||||
String sortCol = JsonUtils.string(payload, "sortCol", defaultColumnId());
|
String firstCol = JsonUtils.string(payload, FIRST_COL, defaultColumnId());
|
||||||
String sortDir = JsonUtils.string(payload, "sortDir", "asc");
|
String firstDir = JsonUtils.string(payload, FIRST_DIR, ASC);
|
||||||
tm.sort(sortCol, TableModel.sortDir(sortDir));
|
String secondCol = JsonUtils.string(payload, SECOND_COL, null);
|
||||||
|
String secondDir = JsonUtils.string(payload, SECOND_DIR, null);
|
||||||
|
tm.sort(firstCol, sortDir(firstDir), secondCol, sortDir(secondDir));
|
||||||
|
|
||||||
addTableConfigAnnotations(tm, payload);
|
addTableConfigAnnotations(tm, payload);
|
||||||
|
|
||||||
|
|||||||
@ -35,6 +35,9 @@ public class TableModelTest {
|
|||||||
private static final String FOO = "foo";
|
private static final String FOO = "foo";
|
||||||
private static final String BAR = "bar";
|
private static final String BAR = "bar";
|
||||||
private static final String ZOO = "zoo";
|
private static final String ZOO = "zoo";
|
||||||
|
private static final String ID = "id";
|
||||||
|
private static final String ALPHA = "alpha";
|
||||||
|
private static final String NUMBER = "number";
|
||||||
|
|
||||||
private enum StarWars {
|
private enum StarWars {
|
||||||
LUKE_SKYWALKER, LEIA_ORGANA, HAN_SOLO, C3PO, R2D2, JABBA_THE_HUTT
|
LUKE_SKYWALKER, LEIA_ORGANA, HAN_SOLO, C3PO, R2D2, JABBA_THE_HUTT
|
||||||
@ -191,7 +194,7 @@ public class TableModelTest {
|
|||||||
initUnsortedTable();
|
initUnsortedTable();
|
||||||
|
|
||||||
// sort by name
|
// sort by name
|
||||||
tm.sort(FOO, SortDir.ASC);
|
tm.sort(FOO, SortDir.ASC, null, null);
|
||||||
|
|
||||||
// verify results
|
// verify results
|
||||||
rows = tm.getRows();
|
rows = tm.getRows();
|
||||||
@ -202,7 +205,7 @@ public class TableModelTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// now the other way
|
// now the other way
|
||||||
tm.sort(FOO, SortDir.DESC);
|
tm.sort(FOO, SortDir.DESC, null, null);
|
||||||
|
|
||||||
// verify results
|
// verify results
|
||||||
rows = tm.getRows();
|
rows = tm.getRows();
|
||||||
@ -219,7 +222,7 @@ public class TableModelTest {
|
|||||||
initUnsortedTable();
|
initUnsortedTable();
|
||||||
|
|
||||||
// sort by number
|
// sort by number
|
||||||
tm.sort(BAR, SortDir.ASC);
|
tm.sort(BAR, SortDir.ASC, null, null);
|
||||||
|
|
||||||
// verify results
|
// verify results
|
||||||
rows = tm.getRows();
|
rows = tm.getRows();
|
||||||
@ -230,7 +233,7 @@ public class TableModelTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// now the other way
|
// now the other way
|
||||||
tm.sort(BAR, SortDir.DESC);
|
tm.sort(BAR, SortDir.DESC, null, null);
|
||||||
|
|
||||||
// verify results
|
// verify results
|
||||||
rows = tm.getRows();
|
rows = tm.getRows();
|
||||||
@ -250,7 +253,7 @@ public class TableModelTest {
|
|||||||
tm.setFormatter(BAR, HexFormatter.INSTANCE);
|
tm.setFormatter(BAR, HexFormatter.INSTANCE);
|
||||||
|
|
||||||
// sort by number
|
// sort by number
|
||||||
tm.sort(BAR, SortDir.ASC);
|
tm.sort(BAR, SortDir.ASC, null, null);
|
||||||
|
|
||||||
// verify results
|
// verify results
|
||||||
rows = tm.getRows();
|
rows = tm.getRows();
|
||||||
@ -276,7 +279,7 @@ public class TableModelTest {
|
|||||||
public void sortAndFormatTwo() {
|
public void sortAndFormatTwo() {
|
||||||
initUnsortedTable();
|
initUnsortedTable();
|
||||||
tm.setFormatter(BAR, HexFormatter.INSTANCE);
|
tm.setFormatter(BAR, HexFormatter.INSTANCE);
|
||||||
tm.sort(FOO, SortDir.ASC);
|
tm.sort(FOO, SortDir.ASC, null, null);
|
||||||
rows = tm.getRows();
|
rows = tm.getRows();
|
||||||
int nr = rows.length;
|
int nr = rows.length;
|
||||||
for (int i = 0; i < nr; i++) {
|
for (int i = 0; i < nr; i++) {
|
||||||
@ -324,7 +327,7 @@ public class TableModelTest {
|
|||||||
tm.addRow().cell(FOO, StarWars.R2D2);
|
tm.addRow().cell(FOO, StarWars.R2D2);
|
||||||
tm.addRow().cell(FOO, StarWars.LUKE_SKYWALKER);
|
tm.addRow().cell(FOO, StarWars.LUKE_SKYWALKER);
|
||||||
|
|
||||||
tm.sort(FOO, SortDir.ASC);
|
tm.sort(FOO, SortDir.ASC, null, null);
|
||||||
|
|
||||||
// verify expected results
|
// verify expected results
|
||||||
StarWars[] ordered = StarWars.values();
|
StarWars[] ordered = StarWars.values();
|
||||||
@ -336,6 +339,102 @@ public class TableModelTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------
|
||||||
|
// Second sort column tests
|
||||||
|
|
||||||
|
private static final String A1 = "a1";
|
||||||
|
private static final String A2 = "a2";
|
||||||
|
private static final String A3 = "a3";
|
||||||
|
private static final String B1 = "b1";
|
||||||
|
private static final String B2 = "b2";
|
||||||
|
private static final String B3 = "b3";
|
||||||
|
private static final String C1 = "c1";
|
||||||
|
private static final String C2 = "c2";
|
||||||
|
private static final String C3 = "c3";
|
||||||
|
private static final String A = "A";
|
||||||
|
private static final String B = "B";
|
||||||
|
private static final String C = "C";
|
||||||
|
|
||||||
|
private static final String[] UNSORTED_IDS = {
|
||||||
|
A3, B2, A1, C2, A2, C3, B1, C1, B3
|
||||||
|
};
|
||||||
|
private static final String[] UNSORTED_ALPHAS = {
|
||||||
|
A, B, A, C, A, C, B, C, B
|
||||||
|
};
|
||||||
|
private static final int[] UNSORTED_NUMBERS = {
|
||||||
|
3, 2, 1, 2, 2, 3, 1, 1, 3
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final String[] ROW_ORDER_AA_NA = {
|
||||||
|
A1, A2, A3, B1, B2, B3, C1, C2, C3
|
||||||
|
};
|
||||||
|
private static final String[] ROW_ORDER_AD_NA = {
|
||||||
|
C1, C2, C3, B1, B2, B3, A1, A2, A3
|
||||||
|
};
|
||||||
|
private static final String[] ROW_ORDER_AA_ND = {
|
||||||
|
A3, A2, A1, B3, B2, B1, C3, C2, C1
|
||||||
|
};
|
||||||
|
private static final String[] ROW_ORDER_AD_ND = {
|
||||||
|
C3, C2, C1, B3, B2, B1, A3, A2, A1
|
||||||
|
};
|
||||||
|
|
||||||
|
private void testAddRow(TableModel tm, int index) {
|
||||||
|
tm.addRow().cell(ID, UNSORTED_IDS[index])
|
||||||
|
.cell(ALPHA, UNSORTED_ALPHAS[index])
|
||||||
|
.cell(NUMBER, UNSORTED_NUMBERS[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TableModel unsortedDoubleTableModel() {
|
||||||
|
tm = new TableModel(ID, ALPHA, NUMBER);
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
testAddRow(tm, i);
|
||||||
|
}
|
||||||
|
return tm;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyRowOrder(String tag, TableModel tm, String[] rowOrder) {
|
||||||
|
int i = 0;
|
||||||
|
for (TableModel.Row row : tm.getRows()) {
|
||||||
|
assertEquals(tag + ": unexpected row id", rowOrder[i++], row.get(ID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sortAlphaAscNumberAsc() {
|
||||||
|
tm = unsortedDoubleTableModel();
|
||||||
|
verifyRowOrder("unsorted", tm, UNSORTED_IDS);
|
||||||
|
tm.sort(ALPHA, SortDir.ASC, NUMBER, SortDir.ASC);
|
||||||
|
verifyRowOrder("aana", tm, ROW_ORDER_AA_NA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sortAlphaDescNumberAsc() {
|
||||||
|
tm = unsortedDoubleTableModel();
|
||||||
|
verifyRowOrder("unsorted", tm, UNSORTED_IDS);
|
||||||
|
tm.sort(ALPHA, SortDir.DESC, NUMBER, SortDir.ASC);
|
||||||
|
verifyRowOrder("adna", tm, ROW_ORDER_AD_NA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sortAlphaAscNumberDesc() {
|
||||||
|
tm = unsortedDoubleTableModel();
|
||||||
|
verifyRowOrder("unsorted", tm, UNSORTED_IDS);
|
||||||
|
tm.sort(ALPHA, SortDir.ASC, NUMBER, SortDir.DESC);
|
||||||
|
verifyRowOrder("aand", tm, ROW_ORDER_AA_ND);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sortAlphaDescNumberDesc() {
|
||||||
|
tm = unsortedDoubleTableModel();
|
||||||
|
verifyRowOrder("unsorted", tm, UNSORTED_IDS);
|
||||||
|
tm.sort(ALPHA, SortDir.DESC, NUMBER, SortDir.DESC);
|
||||||
|
verifyRowOrder("adnd", tm, ROW_ORDER_AD_ND);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------
|
||||||
|
// Annotation tests
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void stringAnnotation() {
|
public void stringAnnotation() {
|
||||||
tm = new TableModel(FOO);
|
tm = new TableModel(FOO);
|
||||||
|
|||||||
@ -209,26 +209,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function sortIcons() {
|
function sortIcons() {
|
||||||
function sortAsc(div) {
|
function _s(div, gid) {
|
||||||
div.style('display', 'inline-block');
|
div.style('display', 'inline-block');
|
||||||
loadEmbeddedIcon(div, 'upArrow', 10);
|
loadEmbeddedIcon(div, gid, 10);
|
||||||
div.classed('tableColSort', true);
|
div.classed('tableColSort', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sortDesc(div) {
|
|
||||||
div.style('display', 'inline-block');
|
|
||||||
loadEmbeddedIcon(div, 'downArrow', 10);
|
|
||||||
div.classed('tableColSort', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sortNone(div) {
|
|
||||||
div.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sortAsc: sortAsc,
|
asc: function (div) { _s(div, 'upArrow'); },
|
||||||
sortDesc: sortDesc,
|
desc: function (div) { _s(div, 'downArrow'); },
|
||||||
sortNone: sortNone
|
none: function (div) { div.remove(); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,16 +28,11 @@
|
|||||||
pdg = 22,
|
pdg = 22,
|
||||||
flashTime = 1500,
|
flashTime = 1500,
|
||||||
colWidth = 'col-width',
|
colWidth = 'col-width',
|
||||||
tableIcon = 'table-icon',
|
tableIcon = 'table-icon';
|
||||||
asc = 'asc',
|
|
||||||
desc = 'desc',
|
|
||||||
none = 'none';
|
|
||||||
|
|
||||||
// internal state
|
// internal state
|
||||||
var currCol = {},
|
var cstmWidths = {},
|
||||||
prevCol = {},
|
api;
|
||||||
cstmWidths = {},
|
|
||||||
sortIconAPI;
|
|
||||||
|
|
||||||
// Functions for resizing a tabular view to the window
|
// Functions for resizing a tabular view to the window
|
||||||
|
|
||||||
@ -94,179 +89,208 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sort columns state model and functions
|
||||||
|
var sortState = {
|
||||||
|
s: {
|
||||||
|
first: null,
|
||||||
|
second: null,
|
||||||
|
touched: null
|
||||||
|
},
|
||||||
|
|
||||||
|
reset: function () {
|
||||||
|
var s = sortState.s;
|
||||||
|
s.first && api.none(s.first.adiv);
|
||||||
|
s.second && api.none(s.second.adiv);
|
||||||
|
sortState.s = { first: null, second: null, touched: null };
|
||||||
|
},
|
||||||
|
|
||||||
|
touch: function (id, adiv) {
|
||||||
|
var s = sortState.s,
|
||||||
|
s1 = s.first,
|
||||||
|
d;
|
||||||
|
|
||||||
|
if (!s.touched) {
|
||||||
|
s.first = { id: id, dir: 'asc', adiv: adiv };
|
||||||
|
s.touched = id;
|
||||||
|
} else {
|
||||||
|
if (id === s.touched) {
|
||||||
|
d = s1.dir === 'asc' ? 'desc' : 'asc';
|
||||||
|
s1.dir = d;
|
||||||
|
s1.adiv = adiv;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
s.second = s.first;
|
||||||
|
s.first = { id: id, dir: 'asc', adiv: adiv };
|
||||||
|
s.touched = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
update: function () {
|
||||||
|
var s = sortState.s,
|
||||||
|
s1 = s.first,
|
||||||
|
s2 = s.second;
|
||||||
|
api[s1.dir](s1.adiv);
|
||||||
|
s2 && api.none(s2.adiv);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Functions for sorting table rows by header
|
// Functions for sorting table rows by header
|
||||||
|
|
||||||
function updateSortDirection(thElem) {
|
function updateSortDirection(thElem) {
|
||||||
sortIconAPI.sortNone(thElem.select('div'));
|
var adiv = thElem.select('div'),
|
||||||
currCol.div = thElem.append('div');
|
id = thElem.attr('colId');
|
||||||
currCol.colId = thElem.attr('colId');
|
|
||||||
|
|
||||||
if (currCol.colId === prevCol.colId) {
|
api.none(adiv);
|
||||||
(currCol.dir === desc) ? currCol.dir = asc : currCol.dir = desc;
|
adiv = thElem.append('div');
|
||||||
prevCol.dir = currCol.dir;
|
sortState.touch(id, adiv);
|
||||||
} else {
|
sortState.update();
|
||||||
currCol.dir = asc;
|
|
||||||
prevCol.dir = none;
|
|
||||||
}
|
|
||||||
(currCol.dir === asc) ?
|
|
||||||
sortIconAPI.sortAsc(currCol.div) : sortIconAPI.sortDesc(currCol.div);
|
|
||||||
|
|
||||||
if (prevCol.colId && prevCol.dir === none) {
|
|
||||||
sortIconAPI.sortNone(prevCol.div);
|
|
||||||
}
|
|
||||||
|
|
||||||
prevCol.colId = currCol.colId;
|
|
||||||
prevCol.div = currCol.div;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sortRequestParams() {
|
function sortRequestParams() {
|
||||||
|
var s = sortState.s,
|
||||||
|
s1 = s.first,
|
||||||
|
s2 = s.second,
|
||||||
|
id2 = s2 && s2.id,
|
||||||
|
dir2 = s2 && s2.dir;
|
||||||
return {
|
return {
|
||||||
sortCol: currCol.colId,
|
firstCol: s1.id,
|
||||||
sortDir: currCol.dir
|
firstDir: s1.dir,
|
||||||
|
secondCol: id2,
|
||||||
|
secondDir: dir2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetSort() {
|
|
||||||
if (currCol.div) {
|
|
||||||
sortIconAPI.sortNone(currCol.div);
|
|
||||||
}
|
|
||||||
if (prevCol.div) {
|
|
||||||
sortIconAPI.sortNone(prevCol.div);
|
|
||||||
}
|
|
||||||
currCol = {};
|
|
||||||
prevCol = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
angular.module('onosWidget')
|
angular.module('onosWidget')
|
||||||
.directive('onosTableResize', ['$log','$window',
|
.directive('onosTableResize', ['$log','$window', 'FnService', 'MastService',
|
||||||
'FnService', 'MastService',
|
|
||||||
|
|
||||||
function (_$log_, _$window_, _fs_, _mast_) {
|
function (_$log_, _$window_, _fs_, _mast_) {
|
||||||
return function (scope, element) {
|
return function (scope, element) {
|
||||||
$log = _$log_;
|
$log = _$log_;
|
||||||
$window = _$window_;
|
$window = _$window_;
|
||||||
fs = _fs_;
|
fs = _fs_;
|
||||||
mast = _mast_;
|
mast = _mast_;
|
||||||
|
|
||||||
var table = d3.select(element[0]),
|
var table = d3.select(element[0]),
|
||||||
tableElems = {
|
tableElems = {
|
||||||
table: table,
|
table: table,
|
||||||
thead: table.select('.table-header').select('table'),
|
thead: table.select('.table-header').select('table'),
|
||||||
tbody: table.select('.table-body').select('table')
|
tbody: table.select('.table-body').select('table')
|
||||||
},
|
},
|
||||||
wsz;
|
wsz;
|
||||||
|
|
||||||
findCstmWidths(table);
|
findCstmWidths(table);
|
||||||
|
|
||||||
// adjust table on window resize
|
// adjust table on window resize
|
||||||
scope.$watchCollection(function () {
|
scope.$watchCollection(function () {
|
||||||
return {
|
return {
|
||||||
h: $window.innerHeight,
|
h: $window.innerHeight,
|
||||||
w: $window.innerWidth
|
w: $window.innerWidth
|
||||||
};
|
};
|
||||||
}, function () {
|
}, function () {
|
||||||
wsz = fs.windowSize(0, 30);
|
wsz = fs.windowSize(0, 30);
|
||||||
adjustTable(
|
adjustTable(
|
||||||
scope.tableData.length,
|
scope.tableData.length,
|
||||||
tableElems,
|
tableElems,
|
||||||
wsz.width, wsz.height
|
wsz.width, wsz.height
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// adjust table when data changes
|
// adjust table when data changes
|
||||||
scope.$watchCollection('tableData', function () {
|
scope.$watchCollection('tableData', function () {
|
||||||
adjustTable(
|
adjustTable(
|
||||||
scope.tableData.length,
|
scope.tableData.length,
|
||||||
tableElems,
|
tableElems,
|
||||||
wsz.width, wsz.height
|
wsz.width, wsz.height
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
scope.$on('$destroy', function () {
|
scope.$on('$destroy', function () {
|
||||||
cstmWidths = {};
|
cstmWidths = {};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}])
|
}])
|
||||||
|
|
||||||
.directive('onosSortableHeader', ['$log', 'IconService',
|
.directive('onosSortableHeader', ['$log', 'IconService',
|
||||||
function (_$log_, _is_) {
|
function (_$log_, _is_) {
|
||||||
return function (scope, element) {
|
return function (scope, element) {
|
||||||
$log = _$log_;
|
$log = _$log_;
|
||||||
is = _is_;
|
is = _is_;
|
||||||
var header = d3.select(element[0]);
|
var header = d3.select(element[0]);
|
||||||
sortIconAPI = is.sortIcons();
|
|
||||||
|
|
||||||
header.selectAll('td').on('click', function () {
|
api = is.sortIcons();
|
||||||
var col = d3.select(this);
|
|
||||||
|
|
||||||
if (col.attr('sortable') === '') {
|
header.selectAll('td').on('click', function () {
|
||||||
updateSortDirection(col);
|
var col = d3.select(this);
|
||||||
scope.sortParams = sortRequestParams();
|
|
||||||
scope.sortCallback(scope.sortParams);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
scope.$on('$destroy', function () {
|
if (col.attr('sortable') === '') {
|
||||||
resetSort();
|
updateSortDirection(col);
|
||||||
});
|
scope.sortParams = sortRequestParams();
|
||||||
};
|
scope.sortCallback(scope.sortParams);
|
||||||
}])
|
|
||||||
|
|
||||||
.directive('onosFlashChanges',
|
|
||||||
['$log', '$parse', '$timeout', 'FnService',
|
|
||||||
function ($log, $parse, $timeout, fs) {
|
|
||||||
|
|
||||||
return function (scope, element, attrs) {
|
|
||||||
var idProp = attrs.idProp,
|
|
||||||
table = d3.select(element[0]),
|
|
||||||
trs, promise;
|
|
||||||
|
|
||||||
function highlightRows() {
|
|
||||||
var changedRows = [];
|
|
||||||
function classRows(b) {
|
|
||||||
if (changedRows.length) {
|
|
||||||
angular.forEach(changedRows, function (tr) {
|
|
||||||
tr.classed('data-change', b);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// timeout because 'row-id' was the un-interpolated value
|
|
||||||
// "{{link.one}}" for example, instead of link.one evaluated
|
|
||||||
// timeout executes on the next digest -- after evaluation
|
|
||||||
$timeout(function () {
|
|
||||||
if (scope.tableData.length) {
|
|
||||||
trs = table.selectAll('tr');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (trs && !trs.empty()) {
|
|
||||||
trs.each(function () {
|
|
||||||
var tr = d3.select(this);
|
|
||||||
if (fs.find(tr.attr('row-id'),
|
|
||||||
scope.changedData,
|
|
||||||
idProp) > -1) {
|
|
||||||
changedRows.push(tr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
classRows(true);
|
|
||||||
promise = $timeout(function () {
|
|
||||||
classRows(false);
|
|
||||||
}, flashTime);
|
|
||||||
trs = undefined;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// new items added:
|
scope.$on('$destroy', function () {
|
||||||
scope.$on('ngRepeatComplete', highlightRows);
|
sortState.reset();
|
||||||
// items changed in existing set:
|
});
|
||||||
scope.$watchCollection('changedData', highlightRows);
|
};
|
||||||
|
}])
|
||||||
|
|
||||||
scope.$on('$destroy', function () {
|
.directive('onosFlashChanges',
|
||||||
if (promise) {
|
['$log', '$parse', '$timeout', 'FnService',
|
||||||
$timeout.cancel(promise);
|
function ($log, $parse, $timeout, fs) {
|
||||||
|
|
||||||
|
return function (scope, element, attrs) {
|
||||||
|
var idProp = attrs.idProp,
|
||||||
|
table = d3.select(element[0]),
|
||||||
|
trs, promise;
|
||||||
|
|
||||||
|
function highlightRows() {
|
||||||
|
var changedRows = [];
|
||||||
|
function classRows(b) {
|
||||||
|
if (changedRows.length) {
|
||||||
|
angular.forEach(changedRows, function (tr) {
|
||||||
|
tr.classed('data-change', b);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// timeout because 'row-id' was the un-interpolated value
|
||||||
|
// "{{link.one}}" for example, instead of link.one evaluated
|
||||||
|
// timeout executes on the next digest -- after evaluation
|
||||||
|
$timeout(function () {
|
||||||
|
if (scope.tableData.length) {
|
||||||
|
trs = table.selectAll('tr');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trs && !trs.empty()) {
|
||||||
|
trs.each(function () {
|
||||||
|
var tr = d3.select(this);
|
||||||
|
if (fs.find(tr.attr('row-id'),
|
||||||
|
scope.changedData,
|
||||||
|
idProp) > -1) {
|
||||||
|
changedRows.push(tr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
classRows(true);
|
||||||
|
promise = $timeout(function () {
|
||||||
|
classRows(false);
|
||||||
|
}, flashTime);
|
||||||
|
trs = undefined;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
}]);
|
|
||||||
|
// new items added:
|
||||||
|
scope.$on('ngRepeatComplete', highlightRows);
|
||||||
|
// items changed in existing set:
|
||||||
|
scope.$watchCollection('changedData', highlightRows);
|
||||||
|
|
||||||
|
scope.$on('$destroy', function () {
|
||||||
|
if (promise) {
|
||||||
|
$timeout.cancel(promise);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}]);
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
|||||||
@ -77,8 +77,10 @@
|
|||||||
respCb: refreshCtrls,
|
respCb: refreshCtrls,
|
||||||
// pre-populate sort so active apps are at the top of the list
|
// pre-populate sort so active apps are at the top of the list
|
||||||
sortParams: {
|
sortParams: {
|
||||||
sortCol: 'state',
|
firstCol: 'state',
|
||||||
sortDir: 'desc'
|
firstDir: 'desc',
|
||||||
|
secondCol: 'id',
|
||||||
|
secondDir: 'asc'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,7 @@
|
|||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td colId="available" class="table-icon" sortable></td>
|
<td colId="available" class="table-icon" sortable></td>
|
||||||
<td colId="type" class="table-icon" sortable></td>
|
<td colId="type" class="table-icon"></td>
|
||||||
<td colId="name" sortable>Friendly Name </td>
|
<td colId="name" sortable>Friendly Name </td>
|
||||||
<td colId="id" sortable>Device ID </td>
|
<td colId="id" sortable>Device ID </td>
|
||||||
<td colId="masterid" sortable>Master Instance </td>
|
<td colId="masterid" sortable>Master Instance </td>
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
<div class="table-header" onos-sortable-header>
|
<div class="table-header" onos-sortable-header>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td colId="type" class="table-icon" sortable></td>
|
<td colId="type" class="table-icon"></td>
|
||||||
<td colId="id" sortable>Host ID </td>
|
<td colId="id" sortable>Host ID </td>
|
||||||
<td colId="mac" sortable>MAC Address </td>
|
<td colId="mac" sortable>MAC Address </td>
|
||||||
<td colId="vlan" sortable>VLAN ID </td>
|
<td colId="vlan" sortable>VLAN ID </td>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user