index-app.js 37 KB

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