index-app.js 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967
  1. import page from '/lib/page.mjs';
  2. import { Header } from '/web/header.js';
  3. class IndexApp {
  4. constructor() {
  5. console.log("app constructor");
  6. this.worlds = {};
  7. this.language = _LangManager.language;
  8. this.options = {
  9. query: 'pathname=' + window.location.pathname.slice(1,
  10. window.location.pathname.lastIndexOf("/")),
  11. secure: window.location.protocol === "https:",
  12. reconnection: false,
  13. path: '',
  14. transports: ['websocket']
  15. }
  16. //window.location.host
  17. var socket = io.connect(window._app.reflectorHost, this.options);
  18. const parse = (msg) => {
  19. this.parseOnlineData(msg)
  20. }
  21. socket.on('getWebAppUpdate', msg => parse.call(this, msg));
  22. socket.on("connect", function () {
  23. let noty = new Noty({
  24. text: 'Connected to Reflector!',
  25. timeout: 2000,
  26. theme: 'mint',
  27. layout: 'bottomRight',
  28. type: 'success'
  29. });
  30. noty.show();
  31. })
  32. socket.on('connect_error', function (err) {
  33. console.log(err);
  34. var errDiv = document.createElement("div");
  35. errDiv.innerHTML = "<div class='vwf-err' style='z-index: 10; position: absolute; top: 80px; right: 50px'>Connection error to Reflector!" + err + "</div>";
  36. document.querySelector('body').appendChild(errDiv);
  37. let noty = new Noty({
  38. text: 'Connection error to Reflector! ' + err,
  39. theme: 'mint',
  40. layout: 'bottomRight',
  41. type: 'error'
  42. });
  43. noty.show();
  44. });
  45. }
  46. initHTML() {
  47. let self = this;
  48. //first init from _app
  49. document.querySelector('head').innerHTML += '<link rel="stylesheet" href="/web/index-app.css">';
  50. let headerGUI = new Header();
  51. headerGUI.init();
  52. //add HTML
  53. let entry = document.createElement("div");
  54. entry.setAttribute("id", 'app');
  55. document.body.appendChild(entry);
  56. let divs = ['appGUI', 'userLobby', 'main', 'worldsGUI'];
  57. divs.forEach(el=>{
  58. let appEl = document.createElement("div");
  59. appEl.setAttribute("id", el);
  60. entry.appendChild(appEl);
  61. })
  62. //init CELL
  63. document.querySelector("#userLobby").$cell({
  64. id: "userLobby",
  65. $cell: true,
  66. $type: "div",
  67. $components: [],
  68. $update: function(){
  69. this.$components = self.initUserGUI()
  70. }
  71. });
  72. document.querySelector("#worldsGUI").$cell({
  73. id: 'worldsGUI',
  74. $cell: true,
  75. $type: "div",
  76. $components: [],
  77. _comps: [],
  78. _refresh: async function(data, fn){
  79. _app.showProgressBar();
  80. this._comps = await fn.call(self, data);
  81. this.$update();
  82. _app.hideProgressBar();
  83. },
  84. $update: async function(){
  85. this.$components = this._comps
  86. }
  87. });
  88. }
  89. async generateFrontPage() {
  90. let infoEl = document.createElement("div");
  91. infoEl.setAttribute("id", "indexPage");
  92. let lang = _LangManager.locale;
  93. let infoElHTML = await _app.helpers.getHtmlText('/web/locale/' + lang + '/index.html');
  94. infoEl.innerHTML = infoElHTML;
  95. document.body.appendChild(infoEl);
  96. document.querySelector('#ruLang').addEventListener('click', function (e) {
  97. _LangManager.locale = 'ru';
  98. window.location.reload(true);
  99. });
  100. document.querySelector('#enLang').addEventListener('click', function (e) {
  101. _LangManager.locale = 'en';
  102. window.location.reload(true);
  103. });
  104. }
  105. initApp() {
  106. // let appElHTML = await _app.helpers.getHtmlText('/web/app.html');
  107. // appEl.innerHTML = appElHTML;
  108. // document.body.appendChild(appEl);
  109. this.initUser();
  110. document.querySelector("#userLobby").$update();
  111. //this.initWorldsListGUI();
  112. //this.getAppDetailsFromDB();
  113. }
  114. async initWorldsProtosListForUser (userAlias) {
  115. document.querySelector("#worldsGUI").$components = [];
  116. await document.querySelector("#worldsGUI")._refresh(userAlias, this.getWorldsProtosListForUser);
  117. }
  118. async initWorldsStatesListForUser (userAlias) {
  119. document.querySelector("#worldsGUI").$components = [];
  120. await document.querySelector("#worldsGUI")._refresh(userAlias, this.getWorldsStatesListForUser);
  121. }
  122. async getWorldsStatesListForUser (userAlias) {
  123. let worldsGUI = [];
  124. let data = await _app.getAllStateWorldsInfoForUser(userAlias);
  125. Object.entries(data).forEach(el=>{
  126. let worlds = this.createWorldsGUI(userAlias, el[0]);
  127. worlds._states = el[1];
  128. worlds.$update();
  129. worldsGUI.push(worlds);
  130. })
  131. return [
  132. {
  133. $type: "div",
  134. class: "mdc-layout-grid",
  135. $components: [
  136. {
  137. $type: "div",
  138. class: "mdc-layout-grid__inner",
  139. $components: [
  140. {
  141. $type: "div",
  142. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  143. $components: [
  144. {
  145. $type: "h1",
  146. class: "mdc-typography--headline4",
  147. $text: 'States for ' + userAlias
  148. }
  149. ]
  150. },
  151. {
  152. $type: "div",
  153. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  154. $components: [].concat(worldsGUI)
  155. }
  156. ]
  157. }
  158. ]
  159. }
  160. ]
  161. }
  162. async getWorldsProtosListForUser (userAlias) {
  163. let worldsGUI = [];
  164. let data = await _app.getAllProtoWorldsInfoForUser(userAlias);
  165. let worlds = this.createWorldsGUI(userAlias);
  166. worlds._states = data;
  167. worlds.$update();
  168. worldsGUI.push(worlds);
  169. return [
  170. {
  171. $type: "div",
  172. class: "mdc-layout-grid",
  173. $components: [
  174. {
  175. $type: "div",
  176. class: "mdc-layout-grid__inner",
  177. $components: [
  178. {
  179. $type: "div",
  180. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  181. $components: [
  182. {
  183. $type: "h1",
  184. class: "mdc-typography--headline4",
  185. $text: 'Worlds for ' + userAlias
  186. }
  187. ]
  188. },
  189. {
  190. $type: "div",
  191. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  192. $components: [].concat(worldsGUI)
  193. },
  194. ]
  195. }
  196. ]
  197. }
  198. ]
  199. }
  200. initUser() {
  201. _LCSDB.on('auth', (ack) => {
  202. if (ack.pub) {
  203. let alias = _LCSUSER.is.alias;
  204. let userEl = document.querySelector('#userGUI');
  205. userEl._status = 'Welcome ' + alias + '!';
  206. //userEl.style.backgroundColor = '#e6e6e6';
  207. userEl.$update();
  208. // document.querySelector('#worldGUI').$update();
  209. // document.querySelector('#main').$update();
  210. _LCSUSER.get('profile').once(function (data) { console.log(data) })
  211. var el = document.getElementById("loginGUI");
  212. if (el) {
  213. el.remove();
  214. }
  215. _LCSUSER.get('profile').not(function (key) {
  216. let profile = { 'alias': alias };
  217. _LCSUSER.get('profile').put(profile);
  218. })
  219. let actionsGUI = document.querySelector('#worldActionsGUI');
  220. if (actionsGUI)
  221. actionsGUI._refresh();
  222. new Noty({
  223. text: alias + ' is succesfully authenticated!',
  224. timeout: 2000,
  225. theme: 'mint',
  226. layout: 'bottomRight',
  227. type: 'success'
  228. }).show();
  229. //this.getAppDetailsFromUserDB();
  230. }
  231. console.log(_LCSUSER.is);
  232. });
  233. }
  234. initUserGUI() {
  235. let worldGUI =
  236. {
  237. $type: "div",
  238. id: "worldGUI",
  239. class: "mdc-layout-grid mdc-layout-grid--align-left",
  240. _status: '',
  241. $init: function () {
  242. this._status = "init";
  243. },
  244. $update: function () {
  245. let guiForAll = [
  246. window._app.widgets.buttonStroked(
  247. {
  248. "label": 'Default World Protos',
  249. "onclick": function (e) {
  250. e.preventDefault();
  251. page("/app/worlds/protos")
  252. //window.location.pathname = "/app/worlds/protos"
  253. //_app.indexApp.getAppDetailsFromDefaultDB('protos');
  254. }
  255. }),
  256. window._app.widgets.buttonStroked(
  257. {
  258. "label": 'Default World States',
  259. "onclick": function (e) {
  260. e.preventDefault();
  261. page("/app/worlds/states")
  262. // window.location.pathname = "/app/worlds/states"
  263. //_app.indexApp.getAppDetailsFromDefaultDB('states');
  264. }
  265. })
  266. ];
  267. var guiUser = [];
  268. if (_LCSUSER.is) {
  269. guiUser = []
  270. }
  271. this.$components = [
  272. {
  273. $type: "h1",
  274. class: "mdc-typography--headline4",
  275. $text: "Worlds list"
  276. }
  277. ].concat(guiForAll).concat(guiUser)
  278. }
  279. }
  280. let userGUI =
  281. {
  282. $type: "div",
  283. id: "userGUI",
  284. // style:"background-color: #ffeb3b",
  285. class: "mdc-layout-grid mdc-layout-grid--align-left",
  286. _status: "",
  287. $init: function () {
  288. this._status = "Welcome!"
  289. },
  290. $update: function () {
  291. var gui = {};
  292. if (_LCSUSER.is) {
  293. gui = [
  294. window._app.widgets.buttonRaised(
  295. {
  296. "label": 'Sign OUT',
  297. "onclick": function (e) {
  298. _LCSUSER.leave().then(ack => {
  299. if (ack.ok == 0) {
  300. window.sessionStorage.removeItem('alias');
  301. window.sessionStorage.removeItem('tmp');
  302. window.location.reload(true);
  303. }
  304. });
  305. }
  306. }),
  307. {
  308. $type: "p"
  309. },
  310. window._app.widgets.buttonStroked(
  311. {
  312. "label": 'PROFILE',
  313. "onclick": function (e) {
  314. e.preventDefault();
  315. //page("/profile")
  316. window.location.pathname = "/profile"
  317. }
  318. }),
  319. {
  320. $type: "p"
  321. },
  322. window._app.widgets.buttonStroked(
  323. {
  324. "label": 'My World protos',
  325. "onclick": function (e) {
  326. e.preventDefault();
  327. let alias = _LCSUSER.is.alias;
  328. //window.location.pathname = '/' + alias + '/worlds/protos'
  329. page('/' + alias + '/worlds/protos');
  330. //_app.indexApp.getWorldsProtosFromUserDB(alias);
  331. }
  332. }),
  333. window._app.widgets.buttonStroked(
  334. {
  335. "label": 'My World states',
  336. "onclick": function (e) {
  337. e.preventDefault();
  338. let alias = _LCSUSER.is.alias;
  339. // window.location.pathname = '/' + alias + '/worlds/states'
  340. page('/' + alias + '/worlds/states');
  341. // page.redirect('/' + alias + '/worlds/states');
  342. //_app.indexApp.getWorldsFromUserDB(alias);
  343. }
  344. })
  345. ]
  346. }
  347. this.$components = [
  348. window._app.widgets.buttonRaised(
  349. {
  350. "label": 'Connection settings',
  351. "onclick": function (e) {
  352. e.preventDefault();
  353. window.location.pathname = '/settings';
  354. }
  355. }),
  356. {
  357. $type: "h1",
  358. class: "mdc-typography--headline3",
  359. $text: this._status
  360. }
  361. ].concat(gui)
  362. }
  363. }
  364. let loginGUI =
  365. {
  366. $type: "div",
  367. id: "loginGUI",
  368. //style:"background-color: #efefef",
  369. class: "mdc-layout-grid mdc-layout-grid--align-left",
  370. _alias: null,
  371. _pass: null,
  372. _passField: null,
  373. _aliasField: null,
  374. _initData: function () {
  375. this._alias = '';
  376. this._pass = '';
  377. // if (window.sessionStorage.getItem('alias')) {
  378. // this._alias = window.sessionStorage.getItem('alias')
  379. // }
  380. // if (window.sessionStorage.getItem('tmp')) {
  381. // this._pass = window.sessionStorage.getItem('tmp')
  382. // }
  383. },
  384. $init: function () {
  385. this._initData();
  386. },
  387. $update: function () {
  388. this.$components = [
  389. {
  390. $type: "div",
  391. class: "mdc-layout-grid__inner",
  392. $components: [
  393. {
  394. $type: "div",
  395. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  396. $components: [
  397. {
  398. $type: "span",
  399. class: "mdc-typography--headline5",
  400. $text: "Login: "
  401. },
  402. window._app.widgets.inputTextFieldOutlined({
  403. "id": 'aliasInput',
  404. "label": "Login",
  405. "value": this._alias,
  406. "type": "text",
  407. "init": function() {
  408. this._aliasField = new mdc.textField.MDCTextField(this);
  409. }
  410. }),
  411. ]
  412. },
  413. {
  414. $type: "div",
  415. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  416. $components: [
  417. {
  418. $type: "span",
  419. class: "mdc-typography--headline5",
  420. $text: "Password: "
  421. },
  422. window._app.widgets.inputTextFieldOutlined({
  423. "id": 'passwordInput',
  424. "label": "Password",
  425. "value": this._pass,
  426. "type": "password",
  427. "init": function() {
  428. this._passField = new mdc.textField.MDCTextField(this);
  429. }
  430. }),
  431. ]
  432. },
  433. {
  434. $type: "div",
  435. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  436. $components: [
  437. window._app.widgets.buttonRaised(
  438. {
  439. "label": 'Sign UP',
  440. "onclick": function (e) {
  441. e.preventDefault();
  442. let alias = this._aliasField.value;
  443. let pass = this._passField.value
  444. if (pass.length < 7) {
  445. new Noty({
  446. text: "Your passphrase needs to be longer than 7 letters",
  447. timeout: 2000,
  448. theme: 'mint',
  449. layout: 'bottomRight',
  450. type: 'error'
  451. }).show();
  452. } else {
  453. //
  454. _LCSUSER.create(alias, pass,
  455. (ack) => {
  456. if (!ack.wait) { }
  457. if (ack.err) {
  458. console.log(ack.err)
  459. return ack.err
  460. };
  461. if (ack.pub) {
  462. _LCSUSER.auth(alias, pass);
  463. _LCSDB.get('users').get(alias).put({
  464. 'alias': alias,
  465. 'pub': ack.pub
  466. });
  467. }
  468. });
  469. }
  470. }
  471. }),
  472. {
  473. $type: "span",
  474. $text: " "
  475. },
  476. window._app.widgets.buttonRaised(
  477. {
  478. "label": 'Sign IN',
  479. "onclick": function (e) {
  480. e.preventDefault();
  481. _LCSUSER.auth(this._aliasField.value, this._passField.value, ack => {
  482. if (ack.err) {
  483. new Noty({
  484. text: ack.err,
  485. timeout: 2000,
  486. theme: 'mint',
  487. layout: 'bottomRight',
  488. type: 'error'
  489. }).show();
  490. }
  491. });
  492. }
  493. })
  494. ]
  495. }
  496. ]
  497. }
  498. ]
  499. }
  500. }
  501. // document.querySelector("#userLobby").$cell({
  502. // id: "userLobby",
  503. // $cell: true,
  504. // $type: "div",
  505. // $components: [
  506. // userGUI, loginGUI, _app.widgets.divider, worldGUI]
  507. // }
  508. // );
  509. return [userGUI, loginGUI, _app.widgets.divider, worldGUI]
  510. }
  511. refresh() {
  512. // socket.emit('getWebAppUpdate', "");
  513. }
  514. parseOnlineData(data) {
  515. let parcedData = _app.parseAppInstancesData(data);
  516. //if (Object.entries(parcedData).length !== 0)
  517. let onlineGUIs = document.querySelectorAll('.online');
  518. onlineGUIs.forEach(function (item) {
  519. item._refresh(parcedData)
  520. });
  521. }
  522. createWorldCard(id, type) {
  523. let self = this;
  524. let onlineGUI = {
  525. $cell: true,
  526. id: "onlineGUI_" + id,
  527. class: "online",
  528. $type: "div",
  529. _instances: {},
  530. _worldListItem: function (m) {
  531. return {
  532. $type: "li",
  533. class: "mdc-list-item",
  534. $components: [
  535. {
  536. $type: "span",
  537. class: "world-link mdc-list-item__text",
  538. $components: [
  539. {
  540. $type: "span",
  541. class: "mdc-list-item__primary-text",
  542. $components: [
  543. {
  544. $type: "a",
  545. $text: m[0],
  546. target: "_blank",
  547. href: window.location.protocol + "//" + window.location.host + "/" + m[1].user + m[0],
  548. onclick: function (e) {
  549. //self.refresh();
  550. }
  551. },
  552. ]
  553. },
  554. {
  555. $type: "span",
  556. class: "mdc-list-item__secondary-text",
  557. $text: self.language.t('users') + m[1].clients
  558. }
  559. ]
  560. }
  561. ]
  562. }
  563. },
  564. $components: [],
  565. _refresh: function (data) {
  566. if (data) {
  567. if (Object.entries(data).length !== 0) {
  568. if (this._worldInfo) {
  569. let insts = Object.entries(data).filter(el => el[0] == this._worldInfo.worldName);
  570. if (insts.length !== 0)
  571. this._instances = insts[0][1];
  572. }
  573. } else {
  574. this._instances = {}
  575. }
  576. }
  577. },
  578. $init: function () {
  579. this._refresh();
  580. },
  581. $update: function () {
  582. if (this._instances) {
  583. let cardListData = Object.entries(this._instances).filter(el => el[1].user == this._worldInfo.userAlias);
  584. this.$components = [
  585. {
  586. $type: "hr",
  587. class: "mdc-list-divider"
  588. }
  589. ].concat(cardListData.map(this._worldListItem))
  590. }
  591. }
  592. }
  593. return {
  594. $cell: true,
  595. id: 'worldCard_' + id,
  596. $type: "div",
  597. _worldInfo: {},
  598. _refresh: function (data) {
  599. this._worldInfo = data
  600. },
  601. // _getWorldInfo: async function () {
  602. // //get space for user
  603. // let info = await _app.getWorldInfo(user, space);
  604. // this._refresh(info);
  605. // },
  606. // _getStateInfo: async function () {
  607. // //get space for user
  608. // let info = await _app.getStateInfo(user, space, saveName);
  609. // this._refresh(info);
  610. // },
  611. $init: function () {
  612. //get space for user
  613. // if (!saveName) {
  614. // this._getWorldInfo();
  615. // } else {
  616. // this._getStateInfo();
  617. // }
  618. },
  619. $update: function () {
  620. //console.log(this._worldInfo);
  621. this.$components = [this._updateCard()]
  622. },
  623. $components: [],
  624. _updateCard: function () {
  625. let desc = this._worldInfo;
  626. if (!desc || Object.keys(desc).length == 0) {
  627. return {
  628. $type: "h1",
  629. class: "mdc-typography--headline4",
  630. $text: "ERROR: NO WORLD!"
  631. }
  632. }
  633. let userGUI = [];
  634. let online = [];
  635. let cardInfo = {
  636. "title": ""
  637. };
  638. if (type == "full") {
  639. } else {
  640. userGUI.push({
  641. $type: "a",
  642. class: "mdc-button mdc-button--compact mdc-card__action mdc-button--outlined",
  643. $text: "Details",
  644. onclick: function (e) {
  645. e.preventDefault();
  646. window.location.pathname = "/" + desc.userAlias + '/' + desc.worldName + '/about'
  647. }
  648. });
  649. }
  650. userGUI.push({
  651. $type: "a",
  652. class: "mdc-button mdc-button--raised mdc-card__action ",
  653. $text: self.language.t('start'),//"Start new",
  654. target: "_blank",
  655. href: "/" + desc.userAlias + '/' + desc.worldName,
  656. onclick: function (e) {
  657. //self.refresh();
  658. }
  659. });
  660. if (desc.type == 'saveState') {
  661. cardInfo.title = desc.worldName.split('/')[2];
  662. }
  663. if (desc.type == 'proto') {
  664. cardInfo.title = desc.worldName;
  665. // userGUI.push(
  666. // {
  667. // $type: "a",
  668. // class: "mdc-button mdc-button--compact mdc-card__action",
  669. // $text: "States",
  670. // onclick: async function (e) {
  671. // e.preventDefault();
  672. // window.location.pathname = "/" + desc.userAlias + '/' + desc.worldName +'/about'
  673. // //console.log('clone');
  674. // // document.querySelector('#worldStatesGUI')._refresh({});
  675. // // let data = await _app.getSaveStates(desc.userAlias, desc.worldName);
  676. // // document.querySelector('#worldStatesGUI')._refresh(data);
  677. // }
  678. // }
  679. // )
  680. }
  681. online.push(onlineGUI);
  682. return {
  683. $cell: true,
  684. $type: "div",
  685. class: "mdc-card world-card",
  686. $components: [
  687. {
  688. $type: "section",
  689. class: "mdc-card__media world-card__16-9-media",
  690. $init: function () {
  691. if (desc.info.imgUrl !== "") {
  692. this.style.backgroundImage = 'linear-gradient(0deg, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3) ), url(' + desc.info.imgUrl + ')';
  693. }
  694. }
  695. },
  696. {
  697. $type: "section",
  698. class: "mdc-card__primary",
  699. $components: [
  700. {
  701. $type: "h1",
  702. class: "mdc-card__title mdc-card__title--large",
  703. $text: desc.info.title
  704. },
  705. {
  706. $type: "h2",
  707. class: "mdc-card__subtitle mdc-theme--text-secondary-on-background",
  708. $text: desc.info.text
  709. },
  710. {
  711. $type: "span",
  712. class: "mdc-card__subtitle mdc-theme--text-secondary-on-background",
  713. $text: 'id: '
  714. },
  715. {
  716. $type: "input",
  717. type: "text",
  718. disabled: "",
  719. style: "font-size:18px",
  720. value: cardInfo.title
  721. },
  722. {
  723. $type: "p",
  724. },
  725. {
  726. $type: "span",
  727. class: "mdc-card__subtitle mdc-theme--text-secondary-on-background",
  728. $text: 'created: ' + (new Date(desc.created)).toUTCString()
  729. },
  730. {
  731. $type: "p",
  732. }
  733. // ,{
  734. // $type: "span",
  735. // class: "mdc-card__subtitle mdc-theme--text-secondary-on-background",
  736. // $text: 'modified: ' + (new Date(desc[5])).toUTCString()
  737. // }
  738. ]
  739. },
  740. {
  741. $type: "section",
  742. class: "mdc-card__actions",
  743. $components: [
  744. ].concat(userGUI)
  745. },
  746. {
  747. $type: "section",
  748. class: "mdc-card__actions",
  749. $components: [
  750. {
  751. $type: 'div',
  752. $text: 'online now: '
  753. }
  754. ].concat(online)
  755. }
  756. ]
  757. }
  758. }
  759. }
  760. }
  761. createWorldsGUI(userAlias, worldName) {
  762. let self = this;
  763. let id = worldName?worldName + '_' + userAlias: "allWorlds_" + userAlias
  764. let headerText = worldName?'States for ' + worldName: 'All Worlds Protos'
  765. let worldCards = {
  766. $cell: true,
  767. id: id,
  768. $type: "div",
  769. $components: [],
  770. _states: {},
  771. _refresh: function (data) {
  772. this._states = data
  773. },
  774. $init: async function () {
  775. //this._refresh();
  776. },
  777. _makeWorldCard: function (data) {
  778. let cardID = data[1].userAlias + '_' + data[1].worldName + '_' + data[0];
  779. let card = self.createWorldCard(cardID, 'min');
  780. card._worldInfo = data[1];
  781. card.$update();
  782. return {
  783. $cell: true,
  784. $type: "div",
  785. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-4",
  786. $components: [
  787. card
  788. //self.createWorldCard(data[1].userAlias, data[1].worldName, data[0])
  789. //this._worldCardDef(appInfo)
  790. ]
  791. }
  792. //console.log(data);
  793. },
  794. $update: function () {
  795. this.$components = [
  796. {
  797. $type: "div",
  798. class: "mdc-layout-grid",
  799. $components: [
  800. {
  801. $type: "div",
  802. class: "mdc-layout-grid__inner",
  803. $components: [
  804. {
  805. $type: "div",
  806. class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
  807. $components: [
  808. {
  809. $type: "H3",
  810. $text: headerText
  811. }
  812. ]
  813. }
  814. ]
  815. },
  816. {
  817. $type: "div",
  818. class: "mdc-layout-grid__inner",
  819. $components: Object.entries(this._states)
  820. .filter(el =>Object.keys(el[1]).length !== 0)
  821. .sort(function (el1, el2) {
  822. return parseInt(el2[1].created) - parseInt(el1[1].created)
  823. })
  824. .map(this._makeWorldCard)
  825. }
  826. ]
  827. }
  828. ]
  829. }
  830. }
  831. return worldCards
  832. }
  833. }
  834. export { IndexApp }
  835. //export {getAppDetails, generateFrontPage, setLanguage, initLocale};