Rift.IO OSM R1 Initial Submission
[osm/UI.git] / skyquake / framework / widgets / listy / listy.js
1 /*
2 *
3 * Copyright 2016 RIFT.IO Inc
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18 import React from 'react';
19 import _ from 'lodash';
20
21 /**
22 *
23 *
24 */
25 export default class Listy extends React.Component {
26 constructor(props) {
27 super(props);
28 }
29
30 /**
31
32 */
33 createList(data, iter=0) {
34 var groupTag = this.props.groupTag.tag;
35 var groupClass = this.props.groupTag.className;
36 var itemTag = this.props.itemTag.tag;
37 var itemClass = this.props.itemTag.className;
38 var listHeaderTag = this.props.listHeaderTag.tag;
39 var listHeaderClass = this.props.listHeaderTag.className;
40
41 var listNode = null;
42 var self = this;
43 if (_.isArrayLike(data) && _.isObjectLike(data)) {
44 var children = [];
45 data.forEach(function(element, index, array) {
46 if ( _.isArrayLike(element) || _.isObjectLike(element)) {
47 children.push(self.createList(element, iter+1));
48 } else {
49 children.push(React.createElement(itemTag, {
50 key: index,
51 className: itemClass
52 }, element));
53 }
54 });
55
56 listNode = React.createElement(groupTag, {
57 key: iter,
58 className: groupClass }, children);
59 }
60 else if (_.isObjectLike(data)) {
61 var children = [];
62 for (var key in data) {
63 if ( _.isArrayLike(data[key]) || _.isObjectLike(data[key])) {
64 children.push(
65 React.createElement(listHeaderTag, {
66 key: key + '_header',
67 className: listHeaderClass }, key + ":")
68 );
69 children.push(
70 React.createElement(groupTag, {
71 key: key + '_list',
72 className: groupClass },
73 [this.createList(data[key], iter + 1)])
74 );
75
76 } else {
77 // TODO: Add span to line-wrap the data part (hanging)
78 children.push(React.createElement(itemTag, {
79 key: key,
80 className: itemClass},
81 key + ": " + data[key]));
82 }
83 }
84 listNode = React.createElement(groupTag, {
85 key: iter,
86 className: groupClass }, children);
87 } else {
88 listNode = React.createElement(itemTag, {
89 className: itemClass}, data);
90 }
91
92 return listNode;
93 }
94
95 noDataMessage() {
96 return React.createElement("div", {
97 className: this.props.noDataMessageClass},
98 this.props.noDataMessage);
99 }
100
101 render () {
102 var data = this.props.data;
103
104 return React.createElement("div", {
105 className: "listy" },
106 _.isEmpty(data) ?
107 this.noDataMessage() :
108 this.createList(data)
109 )
110 }
111 }
112
113 Listy.validateTagDefinition = function(props, propName, componentName) {
114 let obj = props[propName];
115 let fullAttr = componentName + "." + propName;
116
117 if (!obj)
118 return new Error('Validation failed. "%" is undefined', fullAttr);
119 if (!obj.hasOwnProperty("tag") || _.isEmpty(obj.tag))
120 return new Error('Validation failed. "%s" missing attribute "tag"', fullAttr);
121 if (!obj.hasOwnProperty("className") || obj.className == undefined)
122 return new Error('Validation failed. "%s" missing attribute "className"', fullAttr);
123 }
124
125 Listy.propTypes = {
126 data: React.PropTypes.object,
127 groupTag: Listy.validateTagDefinition,
128 itemTag: Listy.validateTagDefinition,
129 listHeaderTag: Listy.validateTagDefinition,
130 debugMode: React.PropTypes.bool
131 }
132
133 Listy.defaultProps = {
134 data: {},
135
136 // Visual Rules
137 groupTag: {
138 tag: "ul",
139 className: "listyGroup"
140 },
141 itemTag: {
142 tag: "li",
143 className: "listyItem"
144 },
145 listHeaderTag: {
146 tag: "h2",
147 className: "listyGroupHeader"
148 },
149 noDataMessage: "No data",
150 noDataMessageClass: "listyNoDataMessage",
151 debugMode: false
152 }