Rework web frontend

This removes foundation, introduces vuejs and adds Material Design
This commit is contained in:
Marvin Scholz 2017-01-20 01:21:44 +01:00
parent 0dacd3645e
commit 45e1d55e8a
16 changed files with 230 additions and 24571 deletions

View file

@ -0,0 +1,77 @@
.sd-res-media {
max-width: 100%;
}
.sd-res-media-both {
max-width: 100%;
max-height: 70vh;
}
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
display: table;
transition: opacity .2s ease;
}
.modal-wrapper {
display: table-cell;
vertical-align: middle;
}
.modal-container {
z-index: 9999;
width: -moz-fit-content;
width: -webkit-fit-content;
width: fit-content;
max-height: 100vh;
overflow: hidden;
max-width: 100%;
margin: 3.5em auto 0 auto;
padding: 20px 30px;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
transition: all .3s ease;
}
.modal-header h3 {
margin-top: 0;
color: #42b983;
}
.modal-body {
margin: 20px 0;
}
.modal-default-button {
float: right;
}
/*
* The following styles are auto-applied to elements with
* transition="modal" when their visibility is toggled
* by Vue.js.
*
* You can easily play with the modal transition by editing
* these styles.
*/
.modal-enter {
opacity: 0;
}
.modal-leave-active {
opacity: 0;
}
.modal-enter .modal-container,
.modal-leave-active .modal-container {
-webkit-transform: scale(1.1);
transform: scale(1.1);
}

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +1,22 @@
$(document).foundation()
//$(document).foundation()
Vue.component('modal', {
template: '#modal-template'
})
var app = new Vue({
delimiters: ['[[', ']]'],
el: '#app, #image-modal',
data: {
items: data,
currentItem: false,
showModal: false
},
methods: {
detailPopup: function (itm, event) {
// `this` inside methods points to the Vue instance
this.currentItem = itm;
this.showModal = true;
}
}
})

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,335 +0,0 @@
/**
* what-input - A global utility for tracking the current input method (mouse, keyboard or touch).
* @version v4.0.4
* @link https://github.com/ten1seven/what-input
* @license MIT
*/
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define("whatInput", [], factory);
else if(typeof exports === 'object')
exports["whatInput"] = factory();
else
root["whatInput"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports) {
module.exports = (function() {
/*
---------------
Variables
---------------
*/
// cache document.documentElement
var docElem = document.documentElement;
// last used input type
var currentInput = 'initial';
// last used input intent
var currentIntent = null;
// form input types
var formInputs = [
'input',
'select',
'textarea'
];
// list of modifier keys commonly used with the mouse and
// can be safely ignored to prevent false keyboard detection
var ignoreMap = [
16, // shift
17, // control
18, // alt
91, // Windows key / left Apple cmd
93 // Windows menu / right Apple cmd
];
// mapping of events to input types
var inputMap = {
'keyup': 'keyboard',
'mousedown': 'mouse',
'mousemove': 'mouse',
'MSPointerDown': 'pointer',
'MSPointerMove': 'pointer',
'pointerdown': 'pointer',
'pointermove': 'pointer',
'touchstart': 'touch'
};
// array of all used input types
var inputTypes = [];
// boolean: true if touch buffer timer is running
var isBuffering = false;
// map of IE 10 pointer events
var pointerMap = {
2: 'touch',
3: 'touch', // treat pen like touch
4: 'mouse'
};
// touch buffer timer
var touchTimer = null;
/*
---------------
Set up
---------------
*/
var setUp = function() {
// add correct mouse wheel event mapping to `inputMap`
inputMap[detectWheel()] = 'mouse';
addListeners();
setInput();
};
/*
---------------
Events
---------------
*/
var addListeners = function() {
// `pointermove`, `MSPointerMove`, `mousemove` and mouse wheel event binding
// can only demonstrate potential, but not actual, interaction
// and are treated separately
// pointer events (mouse, pen, touch)
if (window.PointerEvent) {
docElem.addEventListener('pointerdown', updateInput);
docElem.addEventListener('pointermove', setIntent);
} else if (window.MSPointerEvent) {
docElem.addEventListener('MSPointerDown', updateInput);
docElem.addEventListener('MSPointerMove', setIntent);
} else {
// mouse events
docElem.addEventListener('mousedown', updateInput);
docElem.addEventListener('mousemove', setIntent);
// touch events
if ('ontouchstart' in window) {
docElem.addEventListener('touchstart', touchBuffer);
}
}
// mouse wheel
docElem.addEventListener(detectWheel(), setIntent);
// keyboard events
docElem.addEventListener('keydown', updateInput);
docElem.addEventListener('keyup', updateInput);
};
// checks conditions before updating new input
var updateInput = function(event) {
// only execute if the touch buffer timer isn't running
if (!isBuffering) {
var eventKey = event.which;
var value = inputMap[event.type];
if (value === 'pointer') value = pointerType(event);
if (
currentInput !== value ||
currentIntent !== value
) {
var activeInput = (
document.activeElement &&
formInputs.indexOf(document.activeElement.nodeName.toLowerCase()) === -1
) ? true : false;
if (
value === 'touch' ||
// ignore mouse modifier keys
(value === 'mouse' && ignoreMap.indexOf(eventKey) === -1) ||
// don't switch if the current element is a form input
(value === 'keyboard' && activeInput)
) {
// set the current and catch-all variable
currentInput = currentIntent = value;
setInput();
}
}
}
};
// updates the doc and `inputTypes` array with new input
var setInput = function() {
docElem.setAttribute('data-whatinput', currentInput);
docElem.setAttribute('data-whatintent', currentInput);
if (inputTypes.indexOf(currentInput) === -1) {
inputTypes.push(currentInput);
docElem.className += ' whatinput-types-' + currentInput;
}
};
// updates input intent for `mousemove` and `pointermove`
var setIntent = function(event) {
// only execute if the touch buffer timer isn't running
if (!isBuffering) {
var value = inputMap[event.type];
if (value === 'pointer') value = pointerType(event);
if (currentIntent !== value) {
currentIntent = value;
docElem.setAttribute('data-whatintent', currentIntent);
}
}
};
// buffers touch events because they frequently also fire mouse events
var touchBuffer = function(event) {
// clear the timer if it happens to be running
window.clearTimeout(touchTimer);
// set the current input
updateInput(event);
// set the isBuffering to `true`
isBuffering = true;
// run the timer
touchTimer = window.setTimeout(function() {
// if the timer runs out, set isBuffering back to `false`
isBuffering = false;
}, 200);
};
/*
---------------
Utilities
---------------
*/
var pointerType = function(event) {
if (typeof event.pointerType === 'number') {
return pointerMap[event.pointerType];
} else {
return (event.pointerType === 'pen') ? 'touch' : event.pointerType; // treat pen like touch
}
};
// detect version of mouse wheel event to use
// via https://developer.mozilla.org/en-US/docs/Web/Events/wheel
var detectWheel = function() {
return 'onwheel' in document.createElement('div') ?
'wheel' : // Modern browsers support "wheel"
document.onmousewheel !== undefined ?
'mousewheel' : // Webkit and IE support at least "mousewheel"
'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
};
/*
---------------
Init
don't start script unless browser cuts the mustard
(also passes if polyfills are used)
---------------
*/
if (
'addEventListener' in window &&
Array.prototype.indexOf
) {
setUp();
}
/*
---------------
API
---------------
*/
return {
// returns string: the current input type
// opt: 'loose'|'strict'
// 'strict' (default): returns the same value as the `data-whatinput` attribute
// 'loose': includes `data-whatintent` value if it's more current than `data-whatinput`
ask: function(opt) { return (opt === 'loose') ? currentIntent : currentInput; },
// returns array: all the detected input types
types: function() { return inputTypes; }
};
}());
/***/ }
/******/ ])
});
;

View file

@ -46,7 +46,7 @@ func setupGin() {
router.GET("/ws", func(c *gin.Context) { wsHandler(c.Writer, c.Request) })
router.LoadHTMLGlob(config.C.TemplatesDirectory + "/*")
router.LoadHTMLGlob(config.C.TemplatesDirectory + "/*.html")
router.Static("/static", config.C.AssetsDirectory)
router.Static(config.C.ContentWebDirectory, config.C.ContentDirectory)
router.Run(config.C.BindAddress)

View file

@ -1,46 +1,76 @@
{{ template "header.html" . }}
<div class="row">
<div class="large-12 columns">
<h1>{{ .title }}</h1>
<div id="images" class="row small-up-2 medium-up-3 large-up-4">
{{ range .its }}
<div class="column column-block">
{{ if .IsVideo }}
<a class="thumbnail" data-toggle="{{ .ID }}-modal">
<strong>Video</strong>
</a>
{{ else }}
<a class="thumbnail" data-toggle="{{ .ID }}-modal">
<img alt="" src="{{ .Path }}" />
</a>
{{ end }}
</div>
<div id="{{ .ID }}-modal" class="full reveal" data-reveal>
<div class="row align-top">
<div class="small-10 columns">
{{ if .IsVideo }}
<video controls>
<source src="{{ .Path }}" />
</video>
{{ else }}
<img alt="" src="{{ .Path }}" />
{{ end }}
</div>
<div class="small-2 columns">
<a class="button success" href="javascript:approveMedia({{ .ID }})">Approve</a><br />
<a class="button alert" href="javascript:rejectMedia({{ .ID }})">Reject</a>
</div>
</div>
<button class="close-button" data-close aria-label="Close reveal" type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
{{ end }}
<!-- template for the modal component -->
<script type="text/x-template" id="modal-template">
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
</slot>
</div>
<div class="modal-body">
<slot name="body">
default body
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
<slot name="actions">
<button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored modal-default-button">
<i class="material-icons">check</i> Approve
</button>
<button class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">
<i class="material-icons">cancel</i> Reject
</button>
<button class="mdl-button mdl-js-button mdl-button--icon close" @click="$emit('close')">
<i class="material-icons">close</i>
</button>
</slot>
</slot>
</div>
</div>
</div>
</div>
</div>
</transition>
</script>
<body>
<div class="mdl-layout mdl-js-layout mdl-layout--no-desktop-drawer-button mdl-layout--fixed-header">
{{ template "menu.html" . }}
<main class="mdl-layout__content" id="app">
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--3-col" v-for="item in items">
<a v-on:click="detailPopup(item)">
<!-- Image -->
<img class="mdl-shadow--4dp sd-res-media" v-if="!item.IsVideo" v-bind:src="item.Path" alt="" />
<!-- Video -->
<video class="mdl-shadow--4dp sd-res-media" v-if="item.IsVideo">
<source v-bind:src="item.Path" />
</video>
</a>
</div>
<modal v-if="showModal" @close="showModal = false">
<div slot="body">
<video class="sd-res-media-both" controls v-if="currentItem.IsVideo">
<source v-bind:src="currentItem.Path" />
</video>
<img class="sd-res-media-both" alt="" v-bind:src="currentItem.Path" v-if="!currentItem.IsVideo" />
</div>
</modal>
</div>
</main>
</div>
<script type="text/javascript">
var site = "{{ .site }}";
var obj = document.getElementById("images");
var data = {{ .its }};
</script>
{{ template "footer.html" . }}

View file

@ -1,6 +1,6 @@
<script src="/static/js/vendor/jquery.js"></script>
<script src="/static/js/vendor/what-input.js"></script>
<script src="/static/js/vendor/foundation.js"></script>
<script src="/static/js/app.js"></script>
</body>
</main>
</div>
<script src="/static/js/vendor/vue.min.js"></script>
<script src="/static/js/app.js"></script>
</body>
</html>

View file

@ -1,21 +1,16 @@
<!doctype html>
<!DOCTYPE html>
<html class="no-js" lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ .title }}</title>
<link rel="stylesheet" href="/static/css/foundation.css">
<!-- Styles -->
<link rel="stylesheet" href="/static/css/vendor/material.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="/static/css/app.css">
<!-- Scripts -->
<script src="/static/js/vendor/material.min.js"></script>
</head>
<body>
<div class="top-bar">
<div class="top-bar-left">
<ul class="dropdown menu" data-dropdown-menu>
<li class="menu-text">SocialDragon Admin</li>
<li><a href="/admin/inbox">Inbox</a></li>
<li><a href="/admin/approved">Approved</a></li>
<li><a href="/admin/rejected">Rejected</a></li>
</ul>
</div>
</div>

View file

@ -0,0 +1,23 @@
<header class="mdl-layout__header mdl-layout__header--scroll">
<div class="mdl-layout__header-row">
<!-- Title -->
<span class="mdl-layout-title">SocialDragon</span>
<!-- Add spacer, to align navigation to the right -->
<div class="mdl-layout-spacer"></div>
<!-- Navigation -->
<nav class="mdl-navigation mdl-layout--large-screen-only">
<a class="mdl-navigation__link is-active" href="/admin/inbox">Inbox</a>
<a class="mdl-navigation__link" href="/admin/approved">Approved</a>
<a class="mdl-navigation__link" href="/admin/rejected">Rejected</a>
</nav>
</div>
</header>
<div class="mdl-layout__drawer">
<span class="mdl-layout-title">SocialDragon</span>
<nav class="mdl-navigation">
<a class="mdl-navigation__link" href="/admin/inbox">Inbox</a>
<a class="mdl-navigation__link" href="/admin/approved">Approved</a>
<a class="mdl-navigation__link" href="/admin/rejected">Rejected</a>
</nav>
</div>