#wip: 1 hora de Jam. Misión no finalizada. Terminado controlador servidor, gestión de un JSON como DB y estructura del GUI. Falta el ViewController.
This commit is contained in:
parent
6035470997
commit
f8eeb437a3
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/Data
|
||||||
|
/Public/data
|
||||||
|
*[Ss]ecrets*
|
14
GamUsino.apache2.conf
Executable file
14
GamUsino.apache2.conf
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
<VirtualHost *:80>
|
||||||
|
ServerName gamusino.local
|
||||||
|
DocumentRoot /Projects/GamUsino/Public
|
||||||
|
<Directory /Projects/GamUsino>
|
||||||
|
Options +Indexes +FollowSymLinks +MultiViews
|
||||||
|
DirectoryIndex index.html index.php
|
||||||
|
AllowOverride all
|
||||||
|
Order Allow,Deny
|
||||||
|
Allow from all
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
ErrorLog ${APACHE_LOG_DIR}/error_gamusino_80.log
|
||||||
|
CustomLog ${APACHE_LOG_DIR}/access_gamusino_80.log combined
|
||||||
|
</VirtualHost>
|
86
PHP/GamUsino.php
Normal file
86
PHP/GamUsino.php
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class GamUsino{
|
||||||
|
|
||||||
|
public function __construct($inputs = null){
|
||||||
|
|
||||||
|
$data = json_decode(base64_decode($_POST["GamUsino"]), true);
|
||||||
|
|
||||||
|
if($data){
|
||||||
|
if(isset($data["action"])){
|
||||||
|
switch($data["action"]){
|
||||||
|
case "add_poll":
|
||||||
|
$database = $this->load_database();
|
||||||
|
isset($database["polls"]) || ($database["polls"] = []);
|
||||||
|
$database["polls"][] = [
|
||||||
|
"name" => $data["name"],
|
||||||
|
"options" => []
|
||||||
|
];
|
||||||
|
$this->save_database($database);
|
||||||
|
$this->response(200, $database["polls"]);
|
||||||
|
break;
|
||||||
|
case "get_poll":
|
||||||
|
$database = $this->load_database();
|
||||||
|
$poll = isset($database["polls"]) && isset($database["polls"][$data["name"]]) ? $database["polls"][$data["name"]] : null;
|
||||||
|
$this->response($poll ? 200 : 404, $poll ?? [
|
||||||
|
"message" => "poll_not_exists",
|
||||||
|
"name" => $data["name"]
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case "add_option":
|
||||||
|
$database = $this->load_database();
|
||||||
|
if(isset($database["polls"]) && isset($database["polls"][$data["name"]])){
|
||||||
|
$database["polls"][$data["name"]][] = [
|
||||||
|
"text" => $data["text"],
|
||||||
|
"points" => 0
|
||||||
|
];
|
||||||
|
$this->save_database($database);
|
||||||
|
$this->response(200, $database["polls"][$data["name"]]);
|
||||||
|
}else
|
||||||
|
$this->response(404, [
|
||||||
|
"message" => "poll_not_exists",
|
||||||
|
"name" => $data["name"]
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case "set_option":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$database = $this->load_database();
|
||||||
|
if(isset($database["polls"]) && isset($database["polls"][$data["name"]])){
|
||||||
|
$database["polls"][$data["name"]][$data["i"]]["points"] ++;
|
||||||
|
$this->save_database($database);
|
||||||
|
$this->response(200, null);
|
||||||
|
}else
|
||||||
|
$this->response(404, [
|
||||||
|
"message" => "poll_not_exists",
|
||||||
|
"name" => $data["name"]
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}else
|
||||||
|
$this->response(405, ["message" => "no_action"]);
|
||||||
|
}else
|
||||||
|
$this->response(405, ["message" => "no_data"]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function response($code, $data){
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
"ok" => $code == 200,
|
||||||
|
"code" => $code,
|
||||||
|
"content" => $data
|
||||||
|
]);
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function load_database(){
|
||||||
|
return file_exists(\GamUsino\Secrets::settings["database_path"]) ? json_decode(file_get_contents(\GamUsino\Secrets::settings["database_path"]), true) : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function save_database($database){
|
||||||
|
file_put_contents(\GamUsino\Secrets::settings["database_path"], json_encode($database));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
8
PHP/includes.php
Normal file
8
PHP/includes.php
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
foreach([
|
||||||
|
__DIR__ . "/GamUsino.php",
|
||||||
|
__DIR__ . "/GamUsino.Secrets.php"
|
||||||
|
] as $file)
|
||||||
|
if(file_exists($file))
|
||||||
|
include $file;
|
5
Public/api.php
Normal file
5
Public/api.php
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
include __DIR__ . "/../PHP/includes.php";
|
||||||
|
|
||||||
|
$gamusino = new GamUsino();
|
109
Public/ecma/GamUsino.ecma.js
Normal file
109
Public/ecma/GamUsino.ecma.js
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
GamUsino = function(custom){
|
||||||
|
|
||||||
|
const self = this,
|
||||||
|
default_settings = {
|
||||||
|
nulls : false,
|
||||||
|
default_value : null,
|
||||||
|
autostart : true,
|
||||||
|
timeout : 2000
|
||||||
|
},
|
||||||
|
settings = {};
|
||||||
|
let started = false,
|
||||||
|
ajax_timeout = 2000;
|
||||||
|
|
||||||
|
const constructor = () => {};
|
||||||
|
|
||||||
|
this.start = callback => {
|
||||||
|
|
||||||
|
const end = status => typeof callback == "function" && callback(status);
|
||||||
|
|
||||||
|
if(started){
|
||||||
|
end(false);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
started = true;
|
||||||
|
|
||||||
|
ajax_timeout = self.settings(["ajax_timeout", "timeout"]);
|
||||||
|
|
||||||
|
end(true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.nulls = nulls => typeof nulls == "boolean" ? nulls : self.settings("nulls", null, false, false);
|
||||||
|
|
||||||
|
this.default_value = (_default, nulls) => _default !== undefined && (self.nulls(nulls) || _default !== null) ? _default : self.settings("default_value", null, null, true);
|
||||||
|
|
||||||
|
this.settings = (keys, inputs, _default, nulls) => {
|
||||||
|
|
||||||
|
const m = (keys = (typeof keys == "object" && keys instanceof Array ? keys : keys).filter(key => key && typeof key == "string")).length;
|
||||||
|
|
||||||
|
if(m){
|
||||||
|
|
||||||
|
const l = (inputs = (typeof inputs == "object" ? inputs instanceof Array ? inputs : [inputs] : []).concat(custom, settings, default_settings)).length;
|
||||||
|
|
||||||
|
nulls = self.nulls(nulls);
|
||||||
|
|
||||||
|
for(let i = 0; i < l; i ++)
|
||||||
|
if(inputs[i] && typeof inputs[i] == "object")
|
||||||
|
for(let j = 0; j < m; j ++)
|
||||||
|
if(inputs[i][keys[j]] !== undefined && (nulls || inputs[i][keys[j]] !== null))
|
||||||
|
return inputs[i][keys[j]];
|
||||||
|
};
|
||||||
|
return self.default_value(_default, nulls);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.send = (data, callback) => {
|
||||||
|
|
||||||
|
let ended = false;
|
||||||
|
const ajax = new XMLHttpRequest(),
|
||||||
|
date = Date.now(),
|
||||||
|
end = error => !ended && (ended = true) && typeof callback == "function" && callback(ajax.responseText && JSON.parse(ajax.responseText) || ajax.responseText, ajax.status, ajax.readyState, error == "OK", error);
|
||||||
|
|
||||||
|
ajax.open("post", "/api.php", true);
|
||||||
|
ajax.timeout = ajax_timeout;
|
||||||
|
ajax.setRequestHeader("content-type", "application/x-www-form-urlencoded,charset=utf-8");
|
||||||
|
ajax.onreadystatechange = () => {
|
||||||
|
if(ended)
|
||||||
|
return;
|
||||||
|
if(ajax.readyState == 4)
|
||||||
|
end([301, 302, 304].includes(ajax.stauts) || (ajax.status >= 200 && ajax.status < 300) ? "OK" : "HTTP_ERROR");
|
||||||
|
else if(Date.now() - date > ajax_timeout)
|
||||||
|
end("FORCED_TIMEOUT");
|
||||||
|
};
|
||||||
|
ajax.send("GamUsino=" + btoa(JSON.stringify(data)));
|
||||||
|
|
||||||
|
ajax.onabort = () => end("ABORTED");
|
||||||
|
ajax.ontimeout = () => end("TIMEOUT");
|
||||||
|
ajax.onerror = () => end("ERROR");
|
||||||
|
|
||||||
|
return ajax;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.confirm = (message, ok_action, no_action) => {
|
||||||
|
|
||||||
|
const action = confirm(message) ? ok_action : no_action;
|
||||||
|
|
||||||
|
typeof action == "function" && action();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
this.add_poll = (item, event) => {
|
||||||
|
|
||||||
|
const poll_name = item.parentNode.parentNode.querySelector("input").value;
|
||||||
|
|
||||||
|
if(poll_name)
|
||||||
|
self.confirm("add_poll_sure", () => {
|
||||||
|
self.send({
|
||||||
|
action : "add_poll",
|
||||||
|
name : poll_name
|
||||||
|
}, response => {
|
||||||
|
console.log(response);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor();
|
||||||
|
|
||||||
|
};
|
68
Public/index.html
Normal file
68
Public/index.html
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="es">
|
||||||
|
<head>
|
||||||
|
<title data-i18n="gamusino">GAM-USINO</title>
|
||||||
|
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
|
||||||
|
<script data-type="text/javascript" data-lang="ECMAScript 2015" src="ecma/GamUsino.ecma.js" data-crossorigin="anonymous" charset="utf-8"></script>
|
||||||
|
|
||||||
|
<script data-type="text/javascript" data-lang="ECMAScript 2015" charset="utf-8">
|
||||||
|
|
||||||
|
gamusino = new GamUsino();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1 data-i18n="gamusino" title="GAM-USINO" data-i18n-without="true">
|
||||||
|
<a href="#" target="_self">
|
||||||
|
<span class="logo">
|
||||||
|
<img src="" data-i18n="gamusino" alt="GAM-USINO" data-i18n-without="true" />
|
||||||
|
<span style="background-image:url('');"></span>
|
||||||
|
</span>
|
||||||
|
<span data-i18n="gamusino">GAM-USINO</span>
|
||||||
|
</a>
|
||||||
|
</h1>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<section class="polls">
|
||||||
|
<div class="group">
|
||||||
|
<span class="input"><input type="text" name="poll" data-i18n="poll" data-i18n-without="true" placeholder="Encuesta..." /></span>
|
||||||
|
<span class="input"><button data-i18n="add" data-i18n-without="true" title="Añadir" onclick="gamusino.add_poll(this, event);">
|
||||||
|
<span data-icon="add"></span>
|
||||||
|
<span data-i18n="add">Añadir</span>
|
||||||
|
</button></span>
|
||||||
|
</div>
|
||||||
|
<nav class="polls">
|
||||||
|
<ul></ul>
|
||||||
|
</nav>
|
||||||
|
</section>
|
||||||
|
<section class="poll">
|
||||||
|
<h2 data-i18n="poll">Encuesta</h2>
|
||||||
|
<div class="group">
|
||||||
|
<span class="input"><input type="text" name="option" data-i18n="option" data-i18n-without="true" placeholder="Opción..." /></span>
|
||||||
|
<span class="input"><button data-i18n="add" data-i18n-without="true" title="Añadir" onclick="gamusino.add_option(this, event);">
|
||||||
|
<span data-icon="add"></span>
|
||||||
|
<span data-i18n="add">Añadir</span>
|
||||||
|
</button></span>
|
||||||
|
</div>
|
||||||
|
<nav>
|
||||||
|
<ul></ul>
|
||||||
|
</nav>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
<footer>
|
||||||
|
<span class="licences">
|
||||||
|
<a href="https://www.gnu.org/licenses/gpl-3.0.txt" target="_blank" title="GPLv3">
|
||||||
|
<span data-i18n="license_text">© 2024-2025 CopyLeft.</span>
|
||||||
|
<img src="https://www.gnu.org/graphics/gplv3-127x51.png" alt="GPLv3" />
|
||||||
|
</a>
|
||||||
|
<a class="license-image" href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" data-i18n="license_creative_commons" data-i18n-without="true" title="Creative Commons">
|
||||||
|
<img src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" alt="cc-sa" />
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user