#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