index.html 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. <html>
  2. <head>
  3. <title></title>
  4. <meta content="">
  5. <style>
  6. .green { color: green; }
  7. .red { color: red; }
  8. .yellow { color: dark-yellow; }
  9. .entity_types {
  10. border: 2px solid olive;
  11. margin-bottom: 20px;
  12. max-width: 690px;
  13. }
  14. .entity_types .header {
  15. background-color: olive;
  16. padding: 5px;
  17. }
  18. .entity_types .type {
  19. padding: 2px 5px;
  20. }
  21. .entity_types {
  22. border: 2px solid olive;
  23. margin-bottom: 20px;
  24. max-width: 690px;
  25. }
  26. .entity-table {
  27. border-collapse: collapse;
  28. }
  29. .entity-header {
  30. background-color: pink;
  31. padding: 5px;
  32. }
  33. .entity-details {
  34. border: 2px solid pink;
  35. }
  36. .entity-details .components {
  37. padding: 5px;
  38. }
  39. .newEntity.header {
  40. background-color: #aaaaff;
  41. margin-bottom: 0px;
  42. }
  43. .newEntity {
  44. border: 2px solid #aaaaff;
  45. padding: 5px;
  46. max-width: 690px;
  47. margin-bottom: 20px;
  48. }
  49. .search-tabs {
  50. margin-bottom: 5px;
  51. cursor: pointer;
  52. }
  53. .search-tabs [tab="filter"] {
  54. background-color: purple;
  55. color: silver;
  56. padding: 5px;
  57. }
  58. .search-tabs [tab="search"] {
  59. background-color: #115511;
  60. color: silver;
  61. padding: 5px;
  62. }
  63. .search-values {
  64. border: 2px solid #115511;
  65. max-width: 700px;
  66. margin-bottom: 20px;
  67. }
  68. .search-entities {
  69. border: 2px solid purple;
  70. max-width: 700px;
  71. margin-bottom: 20px;
  72. }
  73. .search-entities .component-filter {
  74. padding: 5px;
  75. float: left;
  76. clear: both;
  77. }
  78. .search-entities .component-filter .component-checkbox {
  79. float: left;
  80. display: inline-block;
  81. min-width: 180px;
  82. }
  83. </style>
  84. <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  85. <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.10/handlebars.min.js"></script>
  86. <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
  87. <script type="text/javascript" src="./templates.js"></script>
  88. <script type="text/javascript" src="./ces.js"></script>
  89. <script type="text/javascript">
  90. var compData;
  91. $(function() {
  92. function refreshEntities() {
  93. $.getJSON('/entities', function(data, status) {
  94. $('.entity_list').html(JSON.stringify(data));
  95. })
  96. }
  97. CES.listTypes(function(err, data) {
  98. $('.entity_types').html(HB['types'](data));
  99. compData = {componentTypes: data};
  100. });
  101. CES.allEntities(function(err, data) {
  102. $('.entity_list').html(HB['entity'](data)).data('entities', data);
  103. });
  104. $(document).on('click', '.newType [action="create"]', function(e) {
  105. var en = $(e.target);
  106. var parent = en.closest('.newType');
  107. var name = parent.find('[name="name"]').val();
  108. var dataType = parent.find('[name="dataType"]').val();
  109. if(name == '<name>') return;
  110. CES.addType(name, dataType, function(err, data) {
  111. $('.entity_types').html(HB['types'](data));
  112. })
  113. });
  114. $(document).on('click', '.entity-header [action="delete"]', function(e) {
  115. var en = $(e.target);
  116. var entity = en.closest('.entity-header')
  117. var eid = entity.attr('eid')|0;
  118. CES.deleteEntity(eid, function(err, data) {
  119. console.log('entity deleted ' + eid);
  120. $('.entity-header[eid="'+eid+'"]').remove();
  121. $('.entity-details[eid="'+eid+'"]').remove();
  122. });
  123. });
  124. $(document).on('click', '.entity-header [action="fetch-components"]', function(e) {
  125. var en = $(e.target);
  126. var entity = en.closest('.entity-header')
  127. var eid = entity.attr('eid')|0;
  128. console.log('eid: ', eid)
  129. var compdata;
  130. CES.fetchEntity(eid, function(err, comps) {
  131. console.log('comps: ', comps);
  132. var ed = $('.entity-details[eid="'+eid+'"]');
  133. ed.show();
  134. ed.find('.components').html(HB['components'](comps));
  135. ed.find('button[action="save"]').show();
  136. CES.listTypes(function(err, data) {
  137. compdata = {componentTypes: data};
  138. });
  139. function addComponent() {
  140. ed.find('.components').append(HB['new_component'](compdata))
  141. }
  142. ed.find('[action="add-component"]').click(function(e) {
  143. e.preventDefault();
  144. addComponent();
  145. });
  146. });
  147. });
  148. $(document).on('click', '.entity-details [action="save"]', function(e) {
  149. console.log('save clicked', e);
  150. var en = $(e.target);
  151. var entity_details = en.closest('.entity-details');
  152. var eid = entity_details.attr('eid')|0;
  153. var new_entity = {eid: eid};
  154. // existing components
  155. entity_details.find('input.valedit').each(function() {
  156. var name = $(this).attr('name');
  157. var val = $(this).val();
  158. new_entity[name] = val;
  159. });
  160. // new components. hacky but meh
  161. entity_details.find('.newcomp').each(function() {
  162. var name = $(this).find('select[name="type"]').val();
  163. var val = $(this).find('input[name="value"]').val();
  164. new_entity[name] = val;
  165. });
  166. console.log(new_entity)
  167. var status_node = entity_details.find('.save_status');
  168. status_node.html('saving...').removeClass('red green').addClass('yellow');
  169. CES.upsertEntity(new_entity, function(err, data) {
  170. console.log('upsert Entity callback');
  171. if(!err) {
  172. status_node.html('saved!').removeClass('red yellow').addClass('green');
  173. setTimeout(function() { status_node.html('').removeClass('green'); }, 10000);
  174. }
  175. else {
  176. status_node.html('save failed').removeClass('green yellow').addClass('red');
  177. }
  178. });
  179. });
  180. function initNewEntity(editor) {
  181. var ed = $(editor);
  182. var compdata;
  183. function addComponent() {
  184. ed.find('.components').append(HB['new_component'](compdata))
  185. }
  186. CES.listTypes(function(err, data) {
  187. compdata = {componentTypes: data};
  188. ed.find('.components').html('');
  189. addComponent();
  190. });
  191. ed.find('[action="add-component"]').click(function(e) {
  192. e.preventDefault();
  193. addComponent();
  194. });
  195. ed.find('[action="create-entity"]').click(function(e) {
  196. var components = {};
  197. ed.find('.components .newcomp').each(function() {
  198. var compName = $(this).find('[name="type"]').val();
  199. var value = $(this).find('[name="value"]').val();
  200. components[compName] = value;
  201. });
  202. console.log('new entity', components)
  203. CES.createEntity(components, function(err, data) {
  204. console.log('created entity', data);
  205. });
  206. });
  207. }
  208. initNewEntity('.newEntity');
  209. CES.listTypes(function(err, data) {
  210. $('.search-entities .component-filter').html(HB['search_comp_filter'](data));
  211. });
  212. $(document).on('click', '.search-entities [action="filter-by-components"]', function(e) {
  213. var en = $(e.target);
  214. var se = en.closest('.search-entities');
  215. var cl = se.find('.component-filter');
  216. var list = [];
  217. cl.find('.component-checkbox input[type="checkbox"]').each(function() {
  218. if($(this).is(':checked')) {
  219. list.push($(this).attr('name'));
  220. }
  221. });
  222. CES.findEntitiesWithComps(list, function(err, data) {
  223. $('.entity_list').html(HB['entity'](data)).data('entities', data);
  224. });
  225. });
  226. $(document).on('click', '[action="search-values"]', function(e) {
  227. var t = $(this);
  228. var sv = t.closest('.search-values');
  229. var components = {};
  230. sv.find('.components .newcomp').each(function() {
  231. var compName = $(this).find('[name="type"]').val();
  232. var value = $(this).find('[name="value"]').val();
  233. components[compName] = value;
  234. });
  235. CES.findEntity(components, function(err, data) {
  236. $('.entity_list').html(HB['entity'](data)).data('entities', data);
  237. });
  238. });
  239. $(document).on('click', '[action="Add-component"]', function(e) {
  240. e.preventDefault();
  241. var t = $(this);
  242. $(HB['new_component'](compData)).insertBefore(t);
  243. });
  244. $('.search-tabs > span[tab]').click(function(e) {
  245. e.preventDefault();
  246. var t = $(this).attr('tab');
  247. $('.tab').hide();
  248. $('.tab[tab="'+t+'"]').show();
  249. });
  250. });
  251. </script>
  252. </head>
  253. <body>
  254. <div class="entity_types"></div>
  255. <div class="newEntity header">Create Entity</div>
  256. <div class="newEntity">
  257. <div class="components"></div>
  258. <button action="add-component">+</button>
  259. <br>
  260. <button action="create-entity">Create Entity</button>
  261. </div>
  262. <div class="search-tabs">
  263. <span tab="filter">Component Filter</span>
  264. <span tab="search">Value Search</span>
  265. </div>
  266. <div class="tab-container">
  267. <div class="search-entities tab" tab="filter">
  268. <div class="component-filter">
  269. </div>
  270. <br>
  271. <button action="filter-by-components" >Apply Filter</button>
  272. </div>
  273. <div class="search-values tab" tab="search" style="display:none;">
  274. <div class="components">
  275. <button action="Add-component">+</button>
  276. </div>
  277. <br>
  278. <button action="search-values">Search</button>
  279. </div>
  280. </div>
  281. <div class="entity_list"></div>
  282. </body>
  283. </html>