MERGE: Excel extraction / vuejs-setup

This commit is contained in:
xdrm-brackets 2018-02-20 13:10:50 +01:00
commit c1196d92b2
18 changed files with 474 additions and 14 deletions

7
.gitignore vendored
View File

@ -1,2 +1,7 @@
vendor
.idea
.vscode
/vendor
/public_html/css
/public_html/js
/node_modules
/package-lock.json

View File

@ -0,0 +1,78 @@
<?php
namespace router\controller;
class js{
private $page;
/* PRE-CALL
*
* @url<String> Calling URI
*
*/
public function __construct($url){
$this->page = isset($url['page']) ? $url['page'] : '';
$this->page = preg_match('/^@[a-z]+$/', $this->page) ? substr($this->page, 1) : null;
}
/* Generate _SERVER.js
*
*/
public function server(){
header('Content-Type: text/javascript; charset=utf-8');
echo "window._SERVER = ".json_encode([
'session' => [
'name' => $_SESSION['NAME'],
'connected' => isset($_SESSION['USER']) ? count($_SESSION['USER']) > 0 : false
]
])."\n";
}
/* Manage bundle hash
*
*/
public function bundle(){
if( is_null($this->page) ){
http_response_code(404);
die();
}
/* (1) Extract /public_html/js/ all .js files */
$js_scripts = glob(__PUBLIC__.'/js/bundle/'.$this->page.'@*.js');
/* (2) If match pattern 'bundle@home@*.js' */
foreach($js_scripts as $fname){
$bname = basename($fname);
// if match -> load it and exit
header("Location: /js/bundle/$bname");
die();
}
/* (3) If nothing found */
http_response_code(404);
die();
}
/* POST-CALL
*
*/
public function __destruct(){
}
}

View File

@ -15,7 +15,6 @@
*/
public function __construct($url){
$this->pagename = $url['page'];
}
@ -23,8 +22,8 @@
*
*/
public function load(){
if( file_exists(__PUBLIC__."/view/".$this->pagename.".php") )
include __PUBLIC__."/view/".$this->pagename.".php";
if( file_exists(__PUBLIC__."/page/".$this->pagename.".php") )
include __PUBLIC__."/page/".$this->pagename.".php";
else
echo "page not found";
}

View File

@ -18,8 +18,8 @@
/* CALL
*
*/
public function homepage(){
header('Location: /homepage/');
public function home(){
header('Location: /home/');
}
/* POST-CALL

View File

@ -5,6 +5,21 @@
"routes": {
"/js/_SERVER.js": {
"methods": ["GET"],
"controller": "js:server",
"arguments": {}
},
"/js/bundle{page}.js": {
"methods": ["GET"],
"controller": "js:bundle",
"arguments": {
"page":"@[a-z]+"
}
},
"/{page}/": {
"methods": ["GET"],
"controller": "page:load",
@ -23,7 +38,7 @@
"/{any}": {
"methods": ["GET"],
"controller": "redirect:homepage",
"controller": "redirect:home",
"arguments": {
"any": ".*"
}

40
package.json Normal file
View File

@ -0,0 +1,40 @@
{
"name": "ptut-vhost",
"description": "PTUT",
"version": "1.0.0",
"author": "xdrm-brackets <xdrm.brackets.dev@gmail.com> SeekDaSky <mascaro.lucas@yahoo.fr G. Fauvet <gfauvet@gmail.com>",
"license": "MIT",
"private": true,
"scripts": {
"build:clean": "rm ./public_html/js/bundle/*.js*; exit 0",
"build:bundle": "cross-env NODE_ENV=production webpack --progress --hide-modules",
"build:dev": "cross-env NODE_ENV=development webpack --progress --hide-modules",
"build:scss": "node-sass -r --output-style compressed --output ./public_html/css ./webpack/scss",
"dev": "npm run build:clean; npm run build:dev",
"build": "npm run build:clean; npm run build:bundle; npm run build:scss"
},
"dependencies": {
"vue": "^2.5.9"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
],
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.0",
"babel-preset-stage-3": "^6.24.1",
"cross-env": "^5.0.5",
"css-loader": "^0.28.7",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^1.1.4",
"node-sass": "^4.7.2",
"sass-loader": "^6.0.6",
"vue-loader": "^13.0.5",
"vue-template-compiler": "^2.5.9",
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.5"
}
}

35
public_html/page/home.php Normal file
View File

@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=0.4">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>PTUT web title</title>
<!-- Icon -->
<link rel='shortcut icon' href='/favicon.ico'>
<!-- CSS dependencies -->
<link rel='stylesheet' type='text/css' href='/css/font-loader.css'>
<link rel='stylesheet' type='text/css' href='/css/layout.css'>
<link rel='stylesheet' type='text/css' href='/css/menu.css'>
<link rel='stylesheet' type='text/css' href='/css/header.css'>
<link rel='stylesheet' type='text/css' href='/css/container.css'>
<!-- JS dependencies -->
<script type='text/javascript' src='/js/_SERVER.js'></script>
</head>
<body>
<div id='main-vue'></div>
<!-- Main loop -->
<script type='text/javascript' src='/js/bundle@home.js'></script>
</body>
</html>

View File

@ -1,7 +0,0 @@
<?php use \database\core\DatabaseDriver;
echo "<pre>";
echo "home page\n";
print_r( DatabaseDriver::getPDO()->query("show databases;")->fetchAll() );
echo "</pre>";

86
webpack.config.js Normal file
View File

@ -0,0 +1,86 @@
var path = require('path')
var webpack = require('webpack')
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const extractSass = new ExtractTextPlugin({
filename: "[name].css",
disable: process.env.NODE_ENV === "development"
});
var mod_common = {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
}, {
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {} // other vue-loader options go here
}
}, {
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}, {
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: { name: '[name].[ext]?[hash]' }
}
]
};
module.exports = [ {
name: "home",
entry: './webpack/page/home.js',
output: {
path: path.resolve(__dirname, './public_html/js/bundle'),
publicPath: '/js/bundle/',
filename: 'home@[hash].js'
},
module: mod_common,
devtool: '#eval-source-map'
}, {
name: "login",
entry: './webpack/page/login.js',
output: {
path: path.resolve(__dirname, './public_html/js/bundle'),
publicPath: '/js/bundle/',
filename: 'login@[hash].js'
},
module: mod_common,
devtool: '#eval-source-map'
} ]
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
])
}

161
webpack/lib/api-client.js Normal file
View File

@ -0,0 +1,161 @@
/* classe API */
export class APIClient{
constructor(target){
this.target = target;
this.xhr = []; // tableau d'objets pour les requêtes ajax
this.buffer = null; // Contiendra le buffer pour debugger si erreur de parsage
this.error = { // error constants
'-1': 'Invalid target format: "METHOD module/method"',
'-2': 'XHR error',
'-3': 'Invalid JSON response',
};
}
/* transaction avec le serveur (http://{host}/api/)
*
* @param pTarget<String> URI cible, format "HTTP_METHOD uri/uri/uri"
* @param pArgs<Object> Le tableu d'arguments passé en POST (attribut<->postfield) à http://{host}/api/
* @param pHandler<Function> Fonction qui s'éxécutera lors de la réponse (1 argument -> réponse<Object>)
* @param pToken<String> Optionnel, token d'auth pour l'api
*
***************************************************************************************************
*
* @usecase
* 1. api.call(
* 2. "PUT newspaper/article/4"
* 2. { content: "New article content" },
* 3. function(resp){
* 4. alert(resp.error);
* 5. }
* 6. );
*
*/
call(pTarget, pArgs, pHandler, pToken=null){
/* (1) Check @pHandler (for dispatching errors)
---------------------------------------------------------*/
/* (1) Check if is a Function */
if( !(pHandler instanceof Function) )
throw new Error("3rd argument must be a function, but is of type '"+typeof(pHandler)+"' !");
/* (2) Check @pTarget
---------------------------------------------------------*/
/* (1) Check format */
if( !/^([A-Z]+) (.+)/i.test(pTarget) ){
pHandler({ error: -1, ErrorDescription: this.error['-1'] });
return false;
}
/* (2) Store locally data */
var lHttpMethod = RegExp.$1;
var lUri = RegExp.$2;
/* (3) Create form data
---------------------------------------------------------*/
/* (1) Create virtual form */
var lForm = new FormData();
/* (2) Add attributes */
for( var key in pArgs ){
// {2.1} If a file -> send as it //
if( pArgs[key] instanceof File )
lForm.append(key, pArgs[key]);
// {2.2} Else -> JSON stringify //
else
lForm.append(key, JSON.stringify(pArgs[key]));
}
/* (4) Create XHR request
---------------------------------------------------------*/
/* (1) Clean ended requests */
for( var i = this.xhr.length-1 ; i >= 0 ; i-- ){
if( this.xhr[i] != null )
break;
this.xhr.pop();
}
/* (2) Push a new entry -> fetch its index */
i = this.xhr.push(null) - 1;
/* (3) Create XHR object */
this.xhr[i] = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHttpRequest');
/* (5) Bind response event
---------------------------------------------------------*/
var self = this; // to access the buffer
this.xhr[i].onreadystatechange = function(i){
/* (1) If request over */
if( this.xhr[i].readyState == 4 ){
/* (2) Update buffer (for debug) */
self.buffer = this.xhr[i].responseText;
/* (3) If request success */
if( [0, 200, 417].indexOf(this.xhr[i].status) > -1 ){
/* (3.1) Create default response (if JSON error) */
var response = {error:-3, ErrorDescription: self.error['-3']};
/* (3.2) Try to parse JSON */
try{ response = JSON.parse(this.xhr[i].responseText); }catch(e){}
/* (3.3) Launch @pHandler with response */
pHandler(response);
/* (4) If request error */
}else
pHandler({ error:-2, ErrorDescription: self.error['-2'] });
/* (5) Notify current xhr instance is done */
this.xhr[i] = null;
}
}.bind(this, i);
/* (6) Finish & send request
---------------------------------------------------------*/
/* (1) Open the XHR */
this.xhr[i].open(lHttpMethod, this.target+lUri, true);
/* (2) Manage optional token */
if( pToken != null )
this.xhr[i].setRequestHeader('Authorization', 'Digest '+pToken);
/* (3) Custom header to notify we're using Ajax */
this.xhr[i].setRequestHeader('X-Requested-With', 'XMLHttpRequest');
/* (4) Make the call */
this.xhr[i].send( lForm );
return true;
}
}

24
webpack/page/home.js Normal file
View File

@ -0,0 +1,24 @@
/* (1) Imports
---------------------------------------------------------*/
/* (1) NPM libs */
import Vue from 'vue'
/* (2) Internal libs */
import {APIClient} from '../lib/api-client'
/* (3) Vues */
import wrapper_vue from '../vue/wrapper.vue'
/* (2) Initialisation
---------------------------------------------------------*/
/* (1) API */
window.api = new APIClient(gstore.data.is_local ? 'http://ptut.com:8080/api/v/1.0/' : 'https://ptut.xdrm.io/api/v/1.0/');
/* (2) Render view */
new Vue({
el: '#main-vue',
render: h => h(wrapper_vue)
});

24
webpack/page/login.js Normal file
View File

@ -0,0 +1,24 @@
/* (1) Imports
---------------------------------------------------------*/
/* (1) NPM libs */
import Vue from 'vue'
/* (2) Internal libs */
import {APIClient} from '../lib/api-client'
/* (3) Vues */
import wrapper_vue from '../vue/wrapper.vue'
/* (2) Initialisation
---------------------------------------------------------*/
/* (1) API */
window.api = new APIClient(gstore.data.is_local ? 'http://ptut.com:8080/api/v/1.0/' : 'https://ptut.xdrm.io/api/v/1.0/');
/* (2) Render view */
new Vue({
el: '#main-vue',
render: h => h(wrapper_vue)
});

View File

View File

0
webpack/scss/header.scss Normal file
View File

0
webpack/scss/layout.scss Normal file
View File

0
webpack/scss/menu.scss Normal file
View File

0
webpack/vue/wrapper.vue Normal file
View File