Compare commits

...

7 Commits

19 changed files with 408 additions and 57 deletions

View File

@ -32,6 +32,7 @@ my $build = Module::Build->new(
'UUID::URandom' => 0,
'Crypt::Bcrypt' => 0,
'DBIx::Class::TimeStamp' => 0,
'DateTime::Format::HTTP' => 0,
},
);
$build->create_build_script;

View File

@ -9,6 +9,7 @@
<attributes>
<attribute>hamburguesas</attribute>
<attribute>pizzerias</attribute>
<attribute>reparto-a-domicilio-comida</attribute>
</attributes>
<slug>hamburgueseria-la-ermita</slug>
<content>

View File

@ -1,6 +1,6 @@
<post>
<author>Burguillos.info</author>
<date>2023-09-21T05:00+00:00</date>
<date>2023-09-21T09:11+00:00</date>
<title>Carta y menú de Bar el Polígono.</title>
<ogdesc>Carta y menú de Bar el Polígono.</ogdesc>
<img src="/img/bar-poligono.webp" bottom-preview="600"/>
@ -11,6 +11,7 @@
</attributes>
<slug>bar-poligono</slug>
<content>
<h2 style="background: black; color: red;">Cerrado permanentemente.</h2>
<img witdh="50%" alt="Puerta de la Bar el Poligono" style="border: solid 1px black" src="/img/bar-poligono.webp"/>
<p>El bar el polígono es un negocio de nueva apertura localizado en Calle Tomás Alba Edison número 8 donde antes se encontraba el Bar el Chori II.</p>

11
generate_proto.sh Normal file
View File

@ -0,0 +1,11 @@
#!/bin/bash
rm -rf ./js-src/generated/
mkdir ./js-src/generated/
protoc --plugin="protoc-gen-ts=./node_modules/.bin/protoc-gen-ts" \
--plugin="protoc-gen-js=./node_modules/.bin/protoc-gen-js" \
--ts_opt=esModuleInterop=true \
--js_out="import_style=commonjs,binary:./js-src/generated" \
--ts_out="./js-src/generated" \
--proto_path="proto" \
$(find proto/ -name '*.proto')

View File

@ -20,6 +20,7 @@ import SelfPlayerUI from '@burguillosinfo/conquer/interface/self-player'
import CreateNode from '@burguillosinfo/conquer/create-node'
import MapState from '@burguillosinfo/conquer/map-state'
import MapNode from '@burguillosinfo/conquer/map-node'
import NewNodeUI from '@burguillosinfo/conquer/interface/new-node'
type StylesInterface = Record<string, Style>

View File

@ -0,0 +1,29 @@
import Conquer from '@burguillosinfo/conquer'
import ConquerInterface from '@burguillosinfo/conquer/interface'
export default abstract class AbstractTopBarInterface extends ConquerInterface {
constructor() {
super()
const exitButton = this.getExitButton()
exitButton.addEventListener('click', () => {
this.runCallbacks('close')
})
}
protected generateNodes(): HTMLElement[] {
const newNode = this.getNodeFromTemplateId('conquer-interface-with-top-bar-template')
return [newNode]
}
protected getMainNode(): HTMLElement {
return this.getNodes()[0]
}
protected getExitButton(): HTMLElement {
const maybeExitButton = this.getMainNode().querySelector('.conquer-exit-button')
if (maybeExitButton === null || !(maybeExitButton instanceof HTMLElement)) {
Conquer.fail('No exit button.')
}
return maybeExitButton
}
public generateInterfaceElementCentered(): HTMLElement {
return this.getNodeFromTemplateId('conquer-interface-element-padded-template')
}
}

View File

@ -0,0 +1,10 @@
import AbstractTopBarInterface from '@burguillosinfo/conquer/interface/abstract-top-bar-interface'
import Conquer from '@burguillosinfo/conquer'
export default class NewNodeUI extends AbstractTopBarInterface {
private coordinates: number[];
constructor(coordinates: number[]) {
super()
this.coordinates = coordinates
}
}

View File

@ -1,35 +1,23 @@
import ConquerInterface from '@burguillosinfo/conquer/interface'
import Conquer from '@burguillosinfo/conquer'
import ConquerUser from '@burguillosinfo/conquer/user'
import AbstractTopBarInterface from '@burguillosinfo/conquer/interface/abstract-top-bar-interface'
export default class SelfPlayerUI extends ConquerInterface {
export default class SelfPlayerUI extends AbstractTopBarInterface {
private selfPlayer: ConquerUser | null = null
private userWelcome: HTMLElement | null = null
protected generateNodes(): HTMLElement[] {
const player = this.getNodeFromTemplateId('conquer-self-player-template')
const player = this.getNodeFromTemplateId('conquer-interface-with-top-bar-template')
return [player]
}
public getSelfPlayerNode(): HTMLElement {
return this.getNodes()[0]
}
public getExitButton(): HTMLElement {
const maybeExitButton = this.getSelfPlayerNode().querySelector('.conquer-exit-button')
if (maybeExitButton === null || !(maybeExitButton instanceof HTMLElement)) {
Conquer.fail('No exit button.')
}
return maybeExitButton
}
public generateInterfaceElementCentered(): HTMLElement {
return this.getNodeFromTemplateId('conquer-interface-element-padded-template')
}
public async run(): Promise<void> {
const selfPlayerNode = this.getSelfPlayerNode()
const selfPlayerNode = this.getMainNode()
selfPlayerNode.classList.remove('conquer-display-none')
const exitButton = this.getExitButton()
exitButton.addEventListener('click', () => {
this.runCallbacks('close')
})
const user = await ConquerUser.getSelfUser()
if (user === null) {
this.runCallbacks('close')
@ -53,14 +41,14 @@ export default class SelfPlayerUI extends ConquerInterface {
})
const createNodeButtonInterface = this.generateInterfaceElementCentered()
createNodeButtonInterface.appendChild(createNodeButton)
this.getSelfPlayerNode().appendChild(createNodeButtonInterface)
this.getMainNode().appendChild(createNodeButtonInterface)
}
private populateWelcome(): void {
const userWelcome = this.getUserWelcome()
const userWelcomeInterface = this.generateInterfaceElementCentered();
userWelcomeInterface.appendChild(userWelcome)
this.getSelfPlayerNode().appendChild(userWelcomeInterface)
this.getMainNode().appendChild(userWelcomeInterface)
}
private getUserWelcome(): HTMLElement {

View File

@ -0,0 +1,30 @@
export default class ConquerWebSocket {
private webSocket: WebSocket | null = null
private socketReady = false
private getWebSocket(): WebSocket {
if (this.webSocket !== null) {
return this.webSocket
}
this.webSocket = new WebSocket(`wss://${window.location.hostname}:${window.location.port}/conquer/websocket`)
this.webSocket.addEventListener('close', (event) => {
this.onSocketClose(event)
})
this.webSocket.addEventListener('error', (event) => {
this.onSocketClose(event)
})
this.webSocket.addEventListener('open', (event) => {
this.onSocketOpen(event)
})
return this.webSocket
}
private onSocketOpen(event: Event) {
this.socketReady = true
}
private onSocketClose(event: Event) {
this.socketReady = false
console.error(event)
}
}

View File

@ -0,0 +1,29 @@
// package: proto.v1.packet
// file: v1/packet/open-new-node.proto
import * as jspb from "google-protobuf";
export class OpenNewNode extends jspb.Message {
getLatitude(): number;
setLatitude(value: number): void;
getLongitude(): number;
setLongitude(value: number): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): OpenNewNode.AsObject;
static toObject(includeInstance: boolean, msg: OpenNewNode): OpenNewNode.AsObject;
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
static serializeBinaryToWriter(message: OpenNewNode, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): OpenNewNode;
static deserializeBinaryFromReader(message: OpenNewNode, reader: jspb.BinaryReader): OpenNewNode;
}
export namespace OpenNewNode {
export type AsObject = {
latitude: number,
longitude: number,
}
}

View File

@ -0,0 +1,206 @@
// source: v1/packet/open-new-node.proto
/**
* @fileoverview
* @enhanceable
* @suppress {missingRequire} reports error on implicit type usages.
* @suppress {messageConventions} JS Compiler reports an error if a variable or
* field starts with 'MSG_' and isn't a translatable message.
* @public
*/
// GENERATED CODE -- DO NOT EDIT!
/* eslint-disable */
// @ts-nocheck
var jspb = require('google-protobuf');
var goog = jspb;
var global =
(typeof globalThis !== 'undefined' && globalThis) ||
(typeof window !== 'undefined' && window) ||
(typeof global !== 'undefined' && global) ||
(typeof self !== 'undefined' && self) ||
(function () { return this; }).call(null) ||
Function('return this')();
goog.exportSymbol('proto.proto.v1.packet.OpenNewNode', null, global);
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.proto.v1.packet.OpenNewNode = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.proto.v1.packet.OpenNewNode, jspb.Message);
if (goog.DEBUG && !COMPILED) {
/**
* @public
* @override
*/
proto.proto.v1.packet.OpenNewNode.displayName = 'proto.proto.v1.packet.OpenNewNode';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* Optional fields that are not set will be set to undefined.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
* @param {boolean=} opt_includeInstance Deprecated. whether to include the
* JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @return {!Object}
*/
proto.proto.v1.packet.OpenNewNode.prototype.toObject = function(opt_includeInstance) {
return proto.proto.v1.packet.OpenNewNode.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Deprecated. Whether to include
* the JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.proto.v1.packet.OpenNewNode} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.proto.v1.packet.OpenNewNode.toObject = function(includeInstance, msg) {
var f, obj = {
latitude: jspb.Message.getFloatingPointFieldWithDefault(msg, 1, 0.0),
longitude: jspb.Message.getFloatingPointFieldWithDefault(msg, 2, 0.0)
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.proto.v1.packet.OpenNewNode}
*/
proto.proto.v1.packet.OpenNewNode.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.proto.v1.packet.OpenNewNode;
return proto.proto.v1.packet.OpenNewNode.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.proto.v1.packet.OpenNewNode} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.proto.v1.packet.OpenNewNode}
*/
proto.proto.v1.packet.OpenNewNode.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {number} */ (reader.readDouble());
msg.setLatitude(value);
break;
case 2:
var value = /** @type {number} */ (reader.readDouble());
msg.setLongitude(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.proto.v1.packet.OpenNewNode.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.proto.v1.packet.OpenNewNode.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.proto.v1.packet.OpenNewNode} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.proto.v1.packet.OpenNewNode.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
f = message.getLatitude();
if (f !== 0.0) {
writer.writeDouble(
1,
f
);
}
f = message.getLongitude();
if (f !== 0.0) {
writer.writeDouble(
2,
f
);
}
};
/**
* optional double latitude = 1;
* @return {number}
*/
proto.proto.v1.packet.OpenNewNode.prototype.getLatitude = function() {
return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 1, 0.0));
};
/**
* @param {number} value
* @return {!proto.proto.v1.packet.OpenNewNode} returns this
*/
proto.proto.v1.packet.OpenNewNode.prototype.setLatitude = function(value) {
return jspb.Message.setProto3FloatField(this, 1, value);
};
/**
* optional double longitude = 2;
* @return {number}
*/
proto.proto.v1.packet.OpenNewNode.prototype.getLongitude = function() {
return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 2, 0.0));
};
/**
* @param {number} value
* @return {!proto.proto.v1.packet.OpenNewNode} returns this
*/
proto.proto.v1.packet.OpenNewNode.prototype.setLongitude = function(value) {
return jspb.Message.setProto3FloatField(this, 2, value);
};
goog.object.extend(exports, proto.proto.v1.packet);

View File

@ -10,43 +10,61 @@ use utf8;
use Mojo::Base 'Mojolicious::Controller', '-signatures';
use Path::Tiny;
use Mojo::UserAgent;
use DateTime::Format::HTTP;
use DateTime;
my $cache_files_dir = path(__FILE__)->parent->parent->parent->parent->child('cache/tiles/');
my $cache_files_dir =
path(__FILE__)->parent->parent->parent->parent->child('cache/tiles/');
sub tile($self) {
my $zoom = $self->stash('zoom');
my $x = $self->stash('x');
my $y = $self->stash('y');
sub _cache_response ($self) {
my $tomorrow_same_hour_datetime = DateTime->now->add( days => 1 );
$self->res->headers->cache_control("max_age=@{[3600*24]}");
$self->res->headers->expires(
DateTime::Format::HTTP->format_datetime($tomorrow_same_hour_datetime) );
}
sub tile ($self) {
my $zoom = $self->stash('zoom');
my $x = $self->stash('x');
my $y = $self->stash('y');
my $candidate_file = $cache_files_dir->child("$zoom-$x-$y.png");
if (-f $candidate_file) {
if ( -f $candidate_file ) {
$self->_cache_response;
return $self->_render_png($candidate_file);
}
if (!defined $self->current_user) {
return $self->render(status => 401, text => '¡¡No estás loggeado, no puedes cargar mapa nuevo.!!');
if ( !defined $self->current_user ) {
return $self->render(
status => 401,
text => '¡¡No estás loggeado, no puedes cargar mapa nuevo.!!'
);
}
$self->_cache_response;
my $file_to_write = $candidate_file;
my $ua = Mojo::UserAgent->new;
my $png_tile = $ua->get("https://tile.openstreetmap.org/$zoom/$x/$y.png")->result->body;
open my $fh, '|-', 'convert', '/dev/stdin', '-channel', 'RGB', '-negate', $file_to_write;
my $ua = Mojo::UserAgent->new;
my $png_tile =
$ua->get("https://tile.openstreetmap.org/$zoom/$x/$y.png")->result->body;
open my $fh, '|-', 'convert', '/dev/stdin', '-channel', 'RGB', '-negate',
$file_to_write;
print $fh $png_tile;
close $fh;
$self->_render_png($file_to_write);
$self->_delete_extra_files();
}
sub _delete_extra_files($self) {
my @files = $cache_files_dir->children;
if (scalar @files < 20001) {
sub _delete_extra_files ($self) {
my @files = $cache_files_dir->children;
if ( scalar @files < 20001 ) {
return;
}
@files = sort { -M $a <=> -M $b } @files;
for (my $i = 0; $i < (scalar @files) - 20000; $i++) {
for ( my $i = 0 ; $i < ( scalar @files ) - 20000 ; $i++ ) {
system 'rm', '-v', $files[$i];
}
}
sub _render_png($self, $file) {
sub _render_png ( $self, $file ) {
system 'touch', $file;
return $self->render(data => $file->slurp_raw, status => 200, format => 'png');
return $self->render( data => $file->slurp_raw, status => 200,
format => 'png' );
}
1;

View File

@ -10,10 +10,12 @@ use Mojo::Base 'Mojolicious::Controller', '-signatures';
sub index($self) {
return $self->render(text => <<"EOF");
Esta aplicación no almacena datos que puedan identificar
de forma única a los usuarios.\r\n
Con fines analíticos y técnicos se almacenan la cantidad
de visitas a cada página.\r\n
La dirección IP, Agente de Usuario y parametros GET con los
que se visita la página es almacenado de forma temporal
(90 días) para detectar posibles ciberataques, tras ese tiempo
es sustituido por un hash.
Esta política puede cambiar en un futuro si se
requieren funcionalidades como registros.\r\n
EOF

View File

@ -25,7 +25,9 @@
"dependencies": {
"babel-loader": "^9.1.3",
"ol": "^8.1.0",
"protoc-gen-js": "^3.21.2",
"tablesort": "^5.3.0",
"ts-loader": "^9.5.0"
"ts-loader": "^9.5.0",
"ts-protoc-gen": "^0.15.0"
}
}

View File

@ -0,0 +1,8 @@
syntax = "proto3";
package proto.v1.packet;
message OpenNewNode {
double latitude = 1;
double longitude = 2;
}

View File

@ -105,6 +105,7 @@ body {
body .conquer-display-none {
display: none; }
body div.conquer-container {
background: black;
height: 100dvh;
width: 100%; }
body div.ol-control {
@ -216,15 +217,15 @@ body {
body div.carousel {
position: fixed;
top: 80%;
height: calc(20% - 6px);
width: calc(100% - 6px); }
height: 20%;
width: 100%; }
body div.carousel a {
position: fixed;
top: 80%;
border: solid 3px black;
width: calc(100%-6px);
width: calc(100% - 6px);
height: calc(20% - 6px);
left: calc(100% + 3px);
left: 100%;
transition: left 1s ease-in;
font-size: 13px;
background: #f2eb8c;
@ -235,9 +236,9 @@ body {
align-items: center;
text-decoration: none; }
body div.carousel a.show {
left: calc(0% + 3px); }
left: 0%; }
body div.carousel a.remove {
left: calc(-100% - 3px); }
left: -100%; }
body div.carousel a:hover, body div.carousel a:focus {
background: blueviolet;
color: #f2eb8c; }

View File

@ -126,6 +126,7 @@ body {
display: none;
}
div.conquer-container {
background: black;
height: 100dvh;
width: 100%;
}
@ -289,22 +290,23 @@ body {
div.carousel {
position: fixed;
top: 80%;
height: calc(20% - 6px);
width: calc(100% - 6px);
height: 20%;
width: 100%;
a {
position: fixed;
top: 80%;
position: fixed;
top: 80%;
border: solid 3px black;
width: calc(100%-6px);
width: calc(100% - 6px);
height: calc(20% - 6px);
left: calc(100% + 3px);
left: 100%;
transition: left 1s ease-in;
&.show {
left: calc(0% + 3px);
left: 0%;
}
&.remove {
left: calc(-100% - 3px);
left: -100%;
}
font-size: 13px;
background: $color_div;

View File

@ -105,6 +105,17 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
/***/ }),
/***/ "./js-src/conquer/interface/abstract-top-bar-interface.ts":
/*!****************************************************************!*\
!*** ./js-src/conquer/interface/abstract-top-bar-interface.ts ***!
\****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ AbstractTopBarInterface)\n/* harmony export */ });\n/* harmony import */ var _burguillosinfo_conquer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @burguillosinfo/conquer */ \"./js-src/conquer/index.ts\");\n/* harmony import */ var _burguillosinfo_conquer_interface__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @burguillosinfo/conquer/interface */ \"./js-src/conquer/interface.ts\");\n\n\nclass AbstractTopBarInterface extends _burguillosinfo_conquer_interface__WEBPACK_IMPORTED_MODULE_1__[\"default\"] {\n constructor() {\n super();\n const exitButton = this.getExitButton();\n exitButton.addEventListener('click', () => {\n this.runCallbacks('close');\n });\n }\n generateNodes() {\n const newNode = this.getNodeFromTemplateId('conquer-interface-with-top-bar-template');\n return [newNode];\n }\n getMainNode() {\n return this.getNodes()[0];\n }\n getExitButton() {\n const maybeExitButton = this.getMainNode().querySelector('.conquer-exit-button');\n if (maybeExitButton === null || !(maybeExitButton instanceof HTMLElement)) {\n _burguillosinfo_conquer__WEBPACK_IMPORTED_MODULE_0__[\"default\"].fail('No exit button.');\n }\n return maybeExitButton;\n }\n generateInterfaceElementCentered() {\n return this.getNodeFromTemplateId('conquer-interface-element-padded-template');\n }\n}\n\n\n//# sourceURL=webpack://BurguillosInfo/./js-src/conquer/interface/abstract-top-bar-interface.ts?");
/***/ }),
/***/ "./js-src/conquer/interface/login.ts":
/*!*******************************************!*\
!*** ./js-src/conquer/interface/login.ts ***!
@ -123,7 +134,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ SelfPlayerUI)\n/* harmony export */ });\n/* harmony import */ var _burguillosinfo_conquer_interface__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @burguillosinfo/conquer/interface */ \"./js-src/conquer/interface.ts\");\n/* harmony import */ var _burguillosinfo_conquer__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @burguillosinfo/conquer */ \"./js-src/conquer/index.ts\");\n/* harmony import */ var _burguillosinfo_conquer_user__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @burguillosinfo/conquer/user */ \"./js-src/conquer/user.ts\");\n\n\n\nclass SelfPlayerUI extends _burguillosinfo_conquer_interface__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n constructor() {\n super(...arguments);\n this.selfPlayer = null;\n this.userWelcome = null;\n }\n generateNodes() {\n const player = this.getNodeFromTemplateId('conquer-self-player-template');\n return [player];\n }\n getSelfPlayerNode() {\n return this.getNodes()[0];\n }\n getExitButton() {\n const maybeExitButton = this.getSelfPlayerNode().querySelector('.conquer-exit-button');\n if (maybeExitButton === null || !(maybeExitButton instanceof HTMLElement)) {\n _burguillosinfo_conquer__WEBPACK_IMPORTED_MODULE_1__[\"default\"].fail('No exit button.');\n }\n return maybeExitButton;\n }\n generateInterfaceElementCentered() {\n return this.getNodeFromTemplateId('conquer-interface-element-padded-template');\n }\n async run() {\n const selfPlayerNode = this.getSelfPlayerNode();\n selfPlayerNode.classList.remove('conquer-display-none');\n const exitButton = this.getExitButton();\n exitButton.addEventListener('click', () => {\n this.runCallbacks('close');\n });\n const user = await _burguillosinfo_conquer_user__WEBPACK_IMPORTED_MODULE_2__[\"default\"].getSelfUser();\n if (user === null) {\n this.runCallbacks('close');\n return;\n }\n this.selfPlayer = user;\n this.populateWelcome();\n this.populateCreateNodeOption();\n }\n populateCreateNodeOption() {\n if (!this.selfPlayer?.isAdmin()) {\n return;\n }\n const createNodeButton = document.createElement('button');\n createNodeButton.innerText = 'Crear Nuevo Nodo';\n createNodeButton.addEventListener('click', () => {\n this.runCallbacks('createNodeStart');\n // We close because it is a sensible thing to do.\n this.runCallbacks('close');\n });\n const createNodeButtonInterface = this.generateInterfaceElementCentered();\n createNodeButtonInterface.appendChild(createNodeButton);\n this.getSelfPlayerNode().appendChild(createNodeButtonInterface);\n }\n populateWelcome() {\n const userWelcome = this.getUserWelcome();\n const userWelcomeInterface = this.generateInterfaceElementCentered();\n userWelcomeInterface.appendChild(userWelcome);\n this.getSelfPlayerNode().appendChild(userWelcomeInterface);\n }\n getUserWelcome() {\n if (this.userWelcome !== null) {\n return this.userWelcome;\n }\n const element = document.createElement('h2');\n if (this.selfPlayer === null) {\n throw new Error('User still not set');\n }\n element.innerText = `¡Hola, ${this.selfPlayer.getUsername()}!`;\n this.userWelcome = element;\n return this.userWelcome;\n }\n}\n\n\n//# sourceURL=webpack://BurguillosInfo/./js-src/conquer/interface/self-player.ts?");
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ SelfPlayerUI)\n/* harmony export */ });\n/* harmony import */ var _burguillosinfo_conquer_user__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @burguillosinfo/conquer/user */ \"./js-src/conquer/user.ts\");\n/* harmony import */ var _burguillosinfo_conquer_interface_abstract_top_bar_interface__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @burguillosinfo/conquer/interface/abstract-top-bar-interface */ \"./js-src/conquer/interface/abstract-top-bar-interface.ts\");\n\n\nclass SelfPlayerUI extends _burguillosinfo_conquer_interface_abstract_top_bar_interface__WEBPACK_IMPORTED_MODULE_1__[\"default\"] {\n constructor() {\n super(...arguments);\n this.selfPlayer = null;\n this.userWelcome = null;\n }\n generateNodes() {\n const player = this.getNodeFromTemplateId('conquer-interface-with-top-bar-template');\n return [player];\n }\n generateInterfaceElementCentered() {\n return this.getNodeFromTemplateId('conquer-interface-element-padded-template');\n }\n async run() {\n const selfPlayerNode = this.getMainNode();\n selfPlayerNode.classList.remove('conquer-display-none');\n const user = await _burguillosinfo_conquer_user__WEBPACK_IMPORTED_MODULE_0__[\"default\"].getSelfUser();\n if (user === null) {\n this.runCallbacks('close');\n return;\n }\n this.selfPlayer = user;\n this.populateWelcome();\n this.populateCreateNodeOption();\n }\n populateCreateNodeOption() {\n if (!this.selfPlayer?.isAdmin()) {\n return;\n }\n const createNodeButton = document.createElement('button');\n createNodeButton.innerText = 'Crear Nuevo Nodo';\n createNodeButton.addEventListener('click', () => {\n this.runCallbacks('createNodeStart');\n // We close because it is a sensible thing to do.\n this.runCallbacks('close');\n });\n const createNodeButtonInterface = this.generateInterfaceElementCentered();\n createNodeButtonInterface.appendChild(createNodeButton);\n this.getMainNode().appendChild(createNodeButtonInterface);\n }\n populateWelcome() {\n const userWelcome = this.getUserWelcome();\n const userWelcomeInterface = this.generateInterfaceElementCentered();\n userWelcomeInterface.appendChild(userWelcome);\n this.getMainNode().appendChild(userWelcomeInterface);\n }\n getUserWelcome() {\n if (this.userWelcome !== null) {\n return this.userWelcome;\n }\n const element = document.createElement('h2');\n if (this.selfPlayer === null) {\n throw new Error('User still not set');\n }\n element.innerText = `¡Hola, ${this.selfPlayer.getUsername()}!`;\n this.userWelcome = element;\n return this.userWelcome;\n }\n}\n\n\n//# sourceURL=webpack://BurguillosInfo/./js-src/conquer/interface/self-player.ts?");
/***/ }),

View File

@ -16,7 +16,7 @@
</div>
<div id="conquer-interface-element-padded-template" class="conquer-interface-element-padded">
</div>
<div id="conquer-self-player-template" class="conquer-self-player conquer-display-none">
<div id="conquer-interface-with-top-bar-template" class="conquer-self-player conquer-display-none">
<div class="conquer-top-bar">
<a href="#" class="conquer-exit-button">X</a>
</div>