RIFT-15726 - optimize download size -> lodash usage in UI
[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 _isArrayLike from 'lodash/isArrayLike';
20 import _isObjectLike from 'lodash/isObjectLike';
21 import _isEmpty from 'lodash/isEmpty';
22
23 /**
24 *
25 *
26 */
27 export default class Listy extends React.Component {
28 constructor(props) {
29 super(props);
30 }
31
32 /**
33
34 */
35 createList(data, iter=0) {
36 var groupTag = this.props.groupTag.tag;
37 var groupClass = this.props.groupTag.className;
38 var itemTag = this.props.itemTag.tag;
39 var itemClass = this.props.itemTag.className;
40 var listHeaderTag = this.props.listHeaderTag.tag;
41 var listHeaderClass = this.props.listHeaderTag.className;
42
43 var listNode = null;
44 var self = this;
45 if (_isArrayLike(data) && _isObjectLike(data)) {
46 var children = [];
47 data.forEach(function(element, index, array) {
48 if ( _isArrayLike(element) || _isObjectLike(element)) {
49 children.push(self.createList(element, iter+1));
50 } else {
51 children.push(React.createElement(itemTag, {
52 key: index,
53 className: itemClass
54 }, element));
55 }
56 });
57
58 listNode = React.createElement(groupTag, {
59 key: iter,
60 className: groupClass }, children);
61 }
62 else if (_isObjectLike(data)) {
63 var children = [];
64 for (var key in data) {
65 if ( _isArrayLike(data[key]) || _isObjectLike(data[key])) {
66 children.push(
67 React.createElement(listHeaderTag, {
68 key: key + '_header',
69 className: listHeaderClass }, key + ":")
70 );
71 children.push(
72 React.createElement(groupTag, {
73 key: key + '_list',
74 className: groupClass },
75 [this.createList(data[key], iter + 1)])
76 );
77
78 } else {
79 // TODO: Add span to line-wrap the data part (hanging)
80 children.push(React.createElement(itemTag, {
81 key: key,
82 className: itemClass},
83 key + ": " + data[key]));
84 }
85 }
86 listNode = React.createElement(groupTag, {
87 key: iter,
88 className: groupClass }, children);
89 } else {
90 listNode = React.createElement(itemTag, {
91 className: itemClass}, data);
92 }
93
94 return listNode;
95 }
96
97 noDataMessage() {
98 return React.createElement("div", {
99 className: this.props.noDataMessageClass},
100 this.props.noDataMessage);
101 }
102
103 render () {
104 var data = this.props.data;
105
106 return React.createElement("div", {
107 className: "listy" },
108 _isEmpty(data) ?
109 this.noDataMessage() :
110 this.createList(data)
111 )
112 }
113 }
114
115 Listy.validateTagDefinition = function(props, propName, componentName) {
116 let obj = props[propName];
117 let fullAttr = componentName + "." + propName;
118
119 if (!obj)
120 return new Error('Validation failed. "%" is undefined', fullAttr);
121 if (!obj.hasOwnProperty("tag") || _isEmpty(obj.tag))
122 return new Error('Validation failed. "%s" missing attribute "tag"', fullAttr);
123 if (!obj.hasOwnProperty("className") || obj.className == undefined)
124 return new Error('Validation failed. "%s" missing attribute "className"', fullAttr);
125 }
126
127 Listy.propTypes = {
128 data: React.PropTypes.object,
129 groupTag: Listy.validateTagDefinition,
130 itemTag: Listy.validateTagDefinition,
131 listHeaderTag: Listy.validateTagDefinition,
132 debugMode: React.PropTypes.bool
133 }
134
135 Listy.defaultProps = {
136 data: {},
137
138 // Visual Rules
139 groupTag: {
140 tag: "ul",
141 className: "listyGroup"
142 },
143 itemTag: {
144 tag: "li",
145 className: "listyItem"
146 },
147 listHeaderTag: {
148 tag: "h2",
149 className: "listyGroupHeader"
150 },
151 noDataMessage: "No data",
152 noDataMessageClass: "listyNoDataMessage",
153 debugMode: false
154 }