Redo design from scratch with something significantly simpler and lower maintainence.
This commit is contained in:
parent
a84bf8aab3
commit
3d00f28657
31 changed files with 228 additions and 1857 deletions
|
@ -13,8 +13,28 @@
|
|||
}
|
||||
|
||||
<form method="post" action="login">
|
||||
<input type="hidden" name="returnUrl" value="@Model.ReturnUrl"/>
|
||||
<label for="username">Username: </label><input name="username" id="username"/>
|
||||
<label for="password">Password: </label><input name="password" type="password" id="password"/>
|
||||
<input type="hidden" name="returnUrl" value="@Model.ReturnUrl" />
|
||||
<table>
|
||||
<tr class="form-row">
|
||||
<td>
|
||||
<label for="username">Username: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input name="username" id="username" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="form-row">
|
||||
<td>
|
||||
<label for="password">Password: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input name="password" type="password" id="password" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="form-row">
|
||||
<td colspan="2">
|
||||
<button type="submit">Login</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
|
|
|
@ -4,9 +4,12 @@
|
|||
ViewBag.Title = Model != null ? "Edit Post" : "New Post";
|
||||
}
|
||||
|
||||
<form method="post" action="/blog/save">
|
||||
<form method="post" action="/blog/save" class="edit-form">
|
||||
<input type="hidden" name="id" value="@Model?.Id"/>
|
||||
<label for="postTitle">Title: </label><input name="title" id="postTitle" value="@Model?.Title"/>
|
||||
<div class="edit-form__title form-row">
|
||||
<label for="postTitle" class="edit-form__title__label">Title: </label>
|
||||
<input name="title" id="postTitle" value="@Model?.Title" class="edit-form__title__input"/>
|
||||
</div>
|
||||
<textarea id="postContent" name="content">@Model?.Content</textarea>
|
||||
<button type="submit">Save</button>
|
||||
</form>
|
||||
|
|
|
@ -4,21 +4,6 @@
|
|||
ViewData["Title"] = "Blog";
|
||||
}
|
||||
|
||||
@section ButtonsLeft {
|
||||
@if (Model.Page > 1) {
|
||||
<button onclick="window.location.href='/blog/page/@(Model.Page-1)'" title="Previous Page">
|
||||
<img src="/images/previous.svg" alt="Previous" />
|
||||
</button>
|
||||
}
|
||||
}
|
||||
@section ButtonsRight {
|
||||
@if (Model.Page < Model.MaxPages) {
|
||||
<button onclick="window.location.href='/blog/page/@(Model.Page+1)'" title="Next Page">
|
||||
<img src="/images/next.svg" alt="Next" />
|
||||
</button>
|
||||
}
|
||||
}
|
||||
|
||||
@foreach (var post in Model.Posts) {
|
||||
<article>
|
||||
<h2><a href="/blog/view/@post.Url">@post.Title</a></h2>
|
||||
|
@ -27,3 +12,12 @@
|
|||
<p><a href="/blog/view/@post.Url">Read more...</a></p>
|
||||
</article>
|
||||
}
|
||||
|
||||
<div class="blog-navigation">
|
||||
@if (Model.Page > 1) {
|
||||
<a href="/blog/page/@(Model.Page - 1)" class="round-button blog-navigation__previous"><img src="/images/previous.svg" alt="Previous"/></a>
|
||||
}
|
||||
@if (Model.Page < Model.MaxPages) {
|
||||
<a href="/blog/page/@(Model.Page + 1)" class="round-button blog-navigation__next"><img src="/images/next.svg" alt="Next"/></a>
|
||||
}
|
||||
</div>
|
|
@ -1,125 +1,47 @@
|
|||
@{
|
||||
var angularSource = "ajax.googleapis.com/ajax/libs/angularjs";
|
||||
var angularVersion = "1.5.0";
|
||||
|
||||
var jsFiles = new[]{
|
||||
"javascript.js",
|
||||
"controllers/main.js",
|
||||
"directives/equalHeightWidth.js",
|
||||
"directives/scopeInit.js",
|
||||
};
|
||||
}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html ng-app="robware">
|
||||
<head>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>@ViewData["Title"] | Robware</title>
|
||||
|
||||
<link href="/css/style.css" rel="stylesheet" defer />
|
||||
<link href="/css/style-med.css?" media="(max-width:1023px)" rel="stylesheet" defer />
|
||||
<link href="/css/style-small.css" media="(max-width:680px)" rel="stylesheet" defer />
|
||||
<link href="/css/style.css" rel="stylesheet" defer/>
|
||||
<style type="text/css">
|
||||
@RenderSection("CSS", required:false);
|
||||
@RenderSection("CSS", required: false);
|
||||
</style>
|
||||
<style media="(max-width:1023px)">
|
||||
@RenderSection("CSSMed", required:false);
|
||||
</style>
|
||||
<style media="(max-width:680px)">
|
||||
@RenderSection("CSSSmall", required:false);
|
||||
</style>
|
||||
<environment include="Development">
|
||||
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.js" defer></script>
|
||||
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.js" defer></script>
|
||||
<script type="text/javascript" src="//@angularSource/@angularVersion/angular.js" defer></script>
|
||||
<script type="text/javascript" src="//@angularSource/@angularVersion/angular-animate.js" defer></script>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js" defer></script>
|
||||
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js" defer></script>
|
||||
<script type="text/javascript" src="//@angularSource/@angularVersion/angular.min.js" defer></script>
|
||||
<script type="text/javascript" src="//@angularSource/@angularVersion/angular-animate.min.js" defer></script>
|
||||
</environment>
|
||||
@foreach (var file in jsFiles){
|
||||
<script type="text/javascript" src="~/js/@file" defer asp-append-version="true"></script>
|
||||
}
|
||||
<script type="text/javascript">
|
||||
@RenderSection("JavaScript", required: false)
|
||||
</script>
|
||||
</head>
|
||||
<body ng-controller="main" ng-class="{scrollLock: (menuVisible && window.innerWidth < 1024) || spinnerVisible}">
|
||||
<div id="menu" ng-show="shouldShowMenu()">
|
||||
<div class="header">
|
||||
<img src="/images/logo.png" /><h1>Robware</h1>
|
||||
</head>
|
||||
<body>
|
||||
<header class="header">
|
||||
<div class="header__blurb">
|
||||
<a class="header__blurb__title" href="/">Robware</a>
|
||||
<small class="header__blurb__tagline">Software by Rob</small>
|
||||
</div>
|
||||
<div id="nav-container">
|
||||
<nav>
|
||||
<dl>
|
||||
<dt class="active">
|
||||
<a href="/home"><img src="/images/home.svg">Home</a>
|
||||
</dt>
|
||||
<dt>
|
||||
<a href="/blog"><img src="/images/blog.svg">Blog</a><span class="go" style="display: none;">»</span><span class="expand" style="display: block;">+</span>
|
||||
</dt>
|
||||
<div class="sub-pages">
|
||||
<dd>
|
||||
<a href="/blog/view/using-a-json-string-as-a-configuration-source-for-a-.net-core-project">Using a JSON string as a configuration source f...</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/blog/view/the-home-automation-saga">The Home Automation Saga</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/blog/view/a-basic-timer-for-the-arduino">A basic timer for the Arduino</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/blog/view/diy-home-automation-update">DIY Home Automation: Update</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/blog/view/the-start-of-diy-home-automation-replacing-the-thermostat-part-2">The start of DIY home automation: replacing the...</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="/blog/"><i>View all</i></a>
|
||||
</dd>
|
||||
</div>
|
||||
<dt>
|
||||
<a href="//git.robware.uk/rob"><img src="/images/projects.svg">Projects</a>
|
||||
</dt>
|
||||
<dt>
|
||||
<a href="/gallery"><img src="/images/photo.svg">Gallery</a>
|
||||
</dt>
|
||||
</dl>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
<div id="main">
|
||||
<div class="header">
|
||||
<img src="/images/menu.svg" id="menu-button" ng-click="menuVisible=!menuVisible" />@{ // using code blocks to remove HTML space but to keep source tidy
|
||||
}<h2>@{ // Shitty, I know, but eh...
|
||||
}<span>@ViewData["Title"]</span>@{
|
||||
}</h2>
|
||||
</div>
|
||||
<div class="errors" ng-if="errors.length>0">
|
||||
The following errors were encountered:
|
||||
<ul>
|
||||
<li ng-repeat="error in errors">{{error}}</li>
|
||||
</ul>
|
||||
Please rectify them and try again.
|
||||
</div>
|
||||
<div id="content">
|
||||
<div id="body">
|
||||
<div class="header__headshot"></div>
|
||||
</header>
|
||||
<div id="content">
|
||||
<main>
|
||||
<h1>@ViewData["Title"]</h1>
|
||||
@RenderBody()
|
||||
</div>
|
||||
<div id="footer">@RenderSection("Footer", required: false)</div>
|
||||
</div>
|
||||
<div id="buttons-left">@RenderSection("ButtonsLeft", required: false)</div>
|
||||
<div id="buttons-right">@RenderSection("ButtonsRight", required: false)</div>
|
||||
</div>
|
||||
<div class="backdrop" ng-show="shouldShowMenu()" ng-click="menuVisible=false"></div>
|
||||
<div id="spinner" class="backdrop" ng-show="spinnerVisible">
|
||||
<img src="/images/spinner.svg" />
|
||||
</div>
|
||||
|
||||
@RenderSection("Scripts", required: false)
|
||||
</body>
|
||||
</main>
|
||||
<nav>
|
||||
@Re
|
||||
<h5>Projects:</h5>
|
||||
<ul>
|
||||
<li><a href="link 1">Link 1</a></li>
|
||||
<li><a href="link 2">Link 2</a></li>
|
||||
<li><a href="link 3">Link 3</a></li>
|
||||
<li><a href="//git.robware.uk">View All</a></li>
|
||||
</ul>
|
||||
<h5>Blog:</h5>
|
||||
<ul>
|
||||
<li><a href="link 1">Link 1</a></li>
|
||||
<li><a href="link 2">Link 2</a></li>
|
||||
<li><a href="link 3">Link 3</a></li>
|
||||
<li><a href="/blog">View All</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<footer>
|
||||
<div class="logo"></div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
.ng-leave {
|
||||
opacity:1;
|
||||
|
||||
&.ng-leave-active {
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
|
||||
.ng-enter{
|
||||
opacity:0;
|
||||
|
||||
&.ng-enter-active {
|
||||
opacity:1;
|
||||
}
|
||||
}
|
||||
|
||||
.ng-hide-add{
|
||||
opacity:1;
|
||||
|
||||
&.ng-hide-add-active{
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
|
||||
.ng-hide-remove{
|
||||
opacity:0;
|
||||
|
||||
&.ng-hide-remove-active{
|
||||
opacity:1;
|
||||
}
|
||||
}
|
|
@ -30,3 +30,27 @@
|
|||
font-size: 0.8em;
|
||||
}
|
||||
}
|
||||
|
||||
.blog-navigation{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
&__next{
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-form{
|
||||
&__title{
|
||||
display: flex;
|
||||
|
||||
&__label{
|
||||
flex: 0 0 auto;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
&__input{
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
@import "colours.less";
|
||||
|
||||
.contextMenu{
|
||||
position: absolute;
|
||||
float:left;
|
||||
background:@background;
|
||||
border:1px solid @Grey-500;
|
||||
border-radius:3px;
|
||||
padding: 3px 0;
|
||||
box-shadow: 3px 3px 5px 0px rgba(0, 0, 0, 0.5);
|
||||
-webkit-user-select: none; /* Chrome all / Safari all */
|
||||
-moz-user-select: none; /* Firefox all */
|
||||
-ms-user-select: none; /* IE 10+ */
|
||||
user-select: none;
|
||||
cursor:default;
|
||||
z-index:10000;
|
||||
|
||||
.menuItem{
|
||||
padding: 0 5px;
|
||||
position:relative;
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover{
|
||||
background: @accent-200;
|
||||
}
|
||||
|
||||
&:not(:last-child){
|
||||
border-bottom: 1px solid @Grey-200;
|
||||
}
|
||||
|
||||
.arrow{
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,198 +0,0 @@
|
|||
@import "colours.less";
|
||||
|
||||
#tabs{
|
||||
background:@primary;
|
||||
margin:-20px;
|
||||
margin-bottom:10px;
|
||||
position:fixed;
|
||||
width:100%;
|
||||
box-shadow: 0px 0px 5px 0px rgba(50, 50, 50, 0.8);
|
||||
overflow-x:auto;
|
||||
white-space:nowrap;
|
||||
|
||||
a{
|
||||
display:inline-block;
|
||||
color:@primary-100;
|
||||
padding:15px 30px;
|
||||
text-decoration:none;
|
||||
text-transform: uppercase;
|
||||
|
||||
&.active{
|
||||
color:#fff;
|
||||
border-bottom:3px solid #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.album{
|
||||
width:33.33%;
|
||||
/*float:left;*/
|
||||
display:inline-block;
|
||||
vertical-align:top;
|
||||
|
||||
div{
|
||||
margin:5px;
|
||||
padding:5px;
|
||||
background:@control2;
|
||||
}
|
||||
|
||||
span{
|
||||
display:block;
|
||||
text-align:center;
|
||||
color:@Grey-800;
|
||||
overflow:hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.imageSelector{
|
||||
.image{
|
||||
width:25%;
|
||||
display:inline-block;
|
||||
vertical-align:top;
|
||||
text-align:center;
|
||||
|
||||
&.selected {
|
||||
>div{
|
||||
background:@primary-300;
|
||||
|
||||
&:hover{
|
||||
background:@primary-400;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input[type=checkbox]{
|
||||
display:none;
|
||||
}
|
||||
|
||||
>div{
|
||||
margin:5px;
|
||||
padding:5px;
|
||||
background:@control2;
|
||||
|
||||
&:hover{
|
||||
background:@Grey-400;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#album-viewer{
|
||||
height:100%;
|
||||
display:flex;
|
||||
flex-direction: column;
|
||||
|
||||
#album-description{
|
||||
flex: 0 0 auto;
|
||||
|
||||
.expander{
|
||||
padding:5px;
|
||||
background:@control2;
|
||||
|
||||
&:after{
|
||||
float:right;
|
||||
content: "+";
|
||||
}
|
||||
|
||||
&.expanded:after{
|
||||
content: '-';
|
||||
}
|
||||
}
|
||||
|
||||
.text{
|
||||
background:@control;
|
||||
padding:5px;
|
||||
|
||||
&.ng-hide{
|
||||
//opacity: 0;
|
||||
line-height: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#album-thumbnails{
|
||||
flex: 0 0 auto;
|
||||
overflow-x:auto;
|
||||
overflow-y:hidden;
|
||||
white-space:nowrap;
|
||||
text-align:center;
|
||||
|
||||
img{
|
||||
width:100px;
|
||||
border:3px solid transparent;
|
||||
|
||||
&.selected{
|
||||
border:3px solid @primary-300;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#album-images{
|
||||
flex: 1 1 auto;
|
||||
overflow:auto;
|
||||
position:relative;
|
||||
|
||||
.image{
|
||||
position:absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow:hidden;
|
||||
text-align:center;
|
||||
|
||||
img{
|
||||
max-height: 100%;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#galleryUpload{
|
||||
|
||||
.upload{
|
||||
font-size:2em;
|
||||
padding:5px;
|
||||
}
|
||||
|
||||
.dragDrop{
|
||||
min-height:200px;
|
||||
border-color: @background;
|
||||
background-position: center;
|
||||
background-size: 100px;
|
||||
margin-bottom:5px;
|
||||
|
||||
&.dragOver{
|
||||
border: 3px dashed @Grey-700;
|
||||
background-image: url("/images/upload.svg");
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
|
||||
.newImage{
|
||||
display:flex;
|
||||
margin-bottom:5px;
|
||||
|
||||
.information{
|
||||
flex:1;
|
||||
}
|
||||
|
||||
.preview{
|
||||
flex:1;
|
||||
position: relative;
|
||||
|
||||
.imageContainer{
|
||||
position:absolute;
|
||||
top:0;
|
||||
bottom:0;
|
||||
right:0;
|
||||
text-align:right;
|
||||
|
||||
img{
|
||||
height:100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
@import "colours.less";
|
||||
|
||||
body{
|
||||
display:initial;
|
||||
}
|
||||
|
||||
#menu{
|
||||
left:0;
|
||||
position:fixed;
|
||||
height:100%;
|
||||
box-shadow:-10px 0px 5px 10px @Grey-900;
|
||||
transition:all ease-in-out 0.4s;
|
||||
|
||||
&.ng-hide{
|
||||
left:-280px;
|
||||
}
|
||||
}
|
||||
|
||||
#main{
|
||||
.header{
|
||||
#menu-button{
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#buttons-left, #buttons-right{
|
||||
button{
|
||||
width:60px;
|
||||
height:60px;
|
||||
}
|
||||
}
|
||||
|
||||
.backdrop{
|
||||
display: initial;
|
||||
}
|
||||
|
||||
.row{
|
||||
|
||||
>.col {
|
||||
width:100%;
|
||||
float:left;
|
||||
}
|
||||
|
||||
&.col-lg-1>.col, &.col-lg-2>.col, &.col-lg-3>.col, &.col-lg-4>.col{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
dl{
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
#main{
|
||||
.header {
|
||||
span:not(:last-child){
|
||||
display:none;
|
||||
}
|
||||
|
||||
>*{
|
||||
padding-left: 15px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#nav-container{
|
||||
top:48px;
|
||||
}
|
||||
|
||||
.header{
|
||||
height: 48px;
|
||||
|
||||
> *{
|
||||
line-height: 48px;
|
||||
font-size:18px;
|
||||
}
|
||||
span:not(:first-child):before{
|
||||
content:none;
|
||||
}
|
||||
}
|
||||
|
||||
.row{
|
||||
>.col {
|
||||
width:100%;
|
||||
float:left;
|
||||
}
|
||||
|
||||
&.col-md-1>.col, &.col-md-2>.col, &.col-md-3>.col, &.col-md-4>.col{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
table{
|
||||
width:100%;
|
||||
}
|
|
@ -1,455 +1,128 @@
|
|||
@import url('https://fonts.googleapis.com/css?family=Public+Sans&display=swap');
|
||||
@import "colours.less";
|
||||
@import "animations.less";
|
||||
@import "contextMenu.less";
|
||||
|
||||
@import url(//fonts.googleapis.com/css?family=Roboto);
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
html {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: @Grey-900;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
h1,
|
||||
h2,
|
||||
button {
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html,
|
||||
button,
|
||||
input,
|
||||
textarea {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
font-family: 'Public Sans', sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: @background;
|
||||
max-width: 1280px;
|
||||
min-height: 100%;
|
||||
margin: auto;
|
||||
background: @Grey-100;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
a {
|
||||
color: @accent;
|
||||
}
|
||||
|
||||
nav {
|
||||
img {
|
||||
vertical-align: middle;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
dt,
|
||||
dd {
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
background: @control;
|
||||
cursor: pointer;
|
||||
cursor: hand;
|
||||
}
|
||||
}
|
||||
|
||||
dt {
|
||||
padding: 10px 10px;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin: 0;
|
||||
padding: 10px 10px 10px 40px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 10px;
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom: 10px;
|
||||
.header {
|
||||
background: url(/images/header.jpg) no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
padding: 40px 30px;
|
||||
display: flex;
|
||||
align-items: start;
|
||||
justify-content: flex-end;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0px;
|
||||
&__blurb {
|
||||
|
||||
&__title {
|
||||
font-size: 32px;
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
&__headshot {
|
||||
flex: 0 0 auto;
|
||||
background: url(/images/headshot.jpg) center no-repeat;
|
||||
background-size: cover;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border: 5px solid white;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0px 0px 5px 0px rgba(0,0,0,1);
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid @control;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
|
||||
input[type=text],
|
||||
textarea {
|
||||
#content {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
main {
|
||||
flex: 1 1 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
nav {
|
||||
flex: 0 0 200px;
|
||||
border-left: 1px solid @Grey-400;
|
||||
margin: 20px 0;
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
}
|
||||
footer {
|
||||
padding: 20px;
|
||||
margin-top: auto;
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 0 10px 5px 0;
|
||||
vertical-align: top;
|
||||
.logo {
|
||||
background: url(/images/logo.png) no-repeat center;
|
||||
background-size: contain;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
background: @accent;
|
||||
border: none;
|
||||
background: @control;
|
||||
box-shadow: 0px 2px 3px 0px rgba(0, 0, 0, 0.25);
|
||||
padding: 10px 20px;
|
||||
border-radius: 50px;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.round-button {
|
||||
border-radius: 50%;
|
||||
background: @accent;
|
||||
padding: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: none;
|
||||
box-shadow: 0px 2px 3px 0px rgba(0, 0, 0, 0.25);
|
||||
margin: 10px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
form {
|
||||
|
||||
button,
|
||||
input[type=submit] {
|
||||
border: none;
|
||||
background: @control;
|
||||
|
||||
&:hover {
|
||||
background: @control2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button:hover {
|
||||
cursor: pointer;
|
||||
cursor: hand;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
p {
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#menu {
|
||||
background: @background;
|
||||
width: 280px;
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: -2px 0px 0px 0px @control inset;
|
||||
z-index: 400;
|
||||
overflow-x: hidden;
|
||||
|
||||
#nav-container {
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
flex: 1 1 auto;
|
||||
|
||||
dl {
|
||||
margin: 5px 0 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
z-index: 401;
|
||||
flex: 0 0 auto;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
#main {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
|
||||
.header {
|
||||
flex: 0 0 auto;
|
||||
z-index: 1;
|
||||
|
||||
#menu-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
>* {
|
||||
padding-left: 20px !important;
|
||||
}
|
||||
}
|
||||
|
||||
#content {
|
||||
flex: 1 1 auto;
|
||||
overflow: auto;
|
||||
z-index: 0;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
#body {
|
||||
padding: 20px;
|
||||
//height:100%;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#buttons-left,
|
||||
#buttons-right {
|
||||
position: absolute;
|
||||
padding: 10px;
|
||||
bottom: 0px;
|
||||
|
||||
button {
|
||||
margin: 10px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
box-shadow: 0px 2px 3px 0px rgba(0, 0, 0, 0.25);
|
||||
vertical-align: middle;
|
||||
border: none;
|
||||
background: @accent;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
color: white;
|
||||
font-size: 24px;
|
||||
line-height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
#buttons-left {
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
#buttons-right {
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
#cookiePopup {
|
||||
position: absolute;
|
||||
background: black;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
padding: 20px;
|
||||
border-radius: 30px;
|
||||
width: 230px;
|
||||
height: 230px;
|
||||
margin-top: -115px;
|
||||
margin-left: -115px;
|
||||
color: white;
|
||||
|
||||
>div {
|
||||
margin-top: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
#spinner {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
z-index: 1000;
|
||||
transition: all ease-in-out 0.5s;
|
||||
|
||||
&.ng-hide {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
>img {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.scrollLock {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.header {
|
||||
height: 64px;
|
||||
background: @primary;
|
||||
color: white;
|
||||
white-space: nowrap;
|
||||
padding: 0 !important;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 -9px 5px 10px rgba(50, 50, 50, 0.8);
|
||||
|
||||
>* {
|
||||
line-height: 64px;
|
||||
font-size: 24px;
|
||||
font-weight: 400;
|
||||
padding-left: 10px;
|
||||
white-space: nowrap;
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
||||
>h2>span {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
>img {
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
|
||||
&:not(:first-child):before {
|
||||
margin: 2px 10px 0 10px;
|
||||
width: 6px;
|
||||
float: left;
|
||||
height: 62px;
|
||||
background: url("/images/chevron.png") no-repeat scroll right center / contain rgba(0, 0, 0, 0);
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.circle {
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.go,
|
||||
.expand {
|
||||
display: none;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.backdrop {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
display: none;
|
||||
transition: all ease-in-out 0.5s;
|
||||
|
||||
&.ng-hide {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.errors {
|
||||
background: url(/images/error.svg) no-repeat scroll 10px 10px @Grey-800;
|
||||
padding: 10px;
|
||||
padding-left: 40px;
|
||||
color: #fff;
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
list-style: square;
|
||||
}
|
||||
}
|
||||
|
||||
.row {
|
||||
width: 100%;
|
||||
clear: both;
|
||||
|
||||
>.col {
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
&.col-lg-1,
|
||||
&.col-md-1,
|
||||
&.col-sm-1 {
|
||||
>.col {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&.col-lg-2,
|
||||
&.col-md-2,
|
||||
&.col-sm-2 {
|
||||
>.col {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
&.col-lg-3,
|
||||
&.col-md-3,
|
||||
&.col-sm-3 {
|
||||
>.col {
|
||||
width: 33.3333%;
|
||||
}
|
||||
}
|
||||
|
||||
&.col-lg-4,
|
||||
&.col-md-4,
|
||||
&.col-sm-4 {
|
||||
>.col {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table.alternatingRows {
|
||||
tr {
|
||||
&:nth-child(1n) {
|
||||
background: @control;
|
||||
}
|
||||
|
||||
&:nth-child(2n) {
|
||||
background: @control2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 3px;
|
||||
|
||||
&.number {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
div.percentageBar {
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
background: @LightGreen-400;
|
||||
overflow: hidden;
|
||||
|
||||
>div {
|
||||
background: @Red-400;
|
||||
height: 100%;
|
||||
transition: all 500ms ease-in-out;
|
||||
.form-row {
|
||||
margin: 5px 0;
|
||||
}
|
||||
}
|
||||
|
||||
@import "blog.less";
|
||||
@import "gallery.less";
|
BIN
Website/wwwroot/images/header.jpg
Normal file
BIN
Website/wwwroot/images/header.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 272 KiB |
BIN
Website/wwwroot/images/headshot.jpg
Normal file
BIN
Website/wwwroot/images/headshot.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
|
@ -1,12 +0,0 @@
|
|||
angular.module("robware").controller('gallery', ["$scope", function($scope) {
|
||||
$scope.images=[];
|
||||
$scope.imageToShow=0;
|
||||
|
||||
$scope.showNextImage=function(){
|
||||
$scope.imageToShow=Math.min($scope.imageToShow+1, $scope.images.length-1);
|
||||
};
|
||||
|
||||
$scope.showPreviousImage=function(){
|
||||
$scope.imageToShow=Math.max($scope.imageToShow-1, 0);
|
||||
};
|
||||
}]);
|
|
@ -1,77 +0,0 @@
|
|||
angular.module("robware").controller('galleryManage', ["$scope", "$http", function($scope, $http) {
|
||||
$scope.albums=[];
|
||||
var albumActions={};
|
||||
|
||||
var moveIndex="Move selected to album";
|
||||
$scope.contextMenuActions={
|
||||
"Delete selected":deleteSelected
|
||||
};
|
||||
|
||||
function getSelectedImageIds(){
|
||||
var images=[];
|
||||
angular.forEach($scope.selectedAlbum.Images, function(image){
|
||||
if (image.selected)
|
||||
images.push(image.ImageId);
|
||||
});
|
||||
return images;
|
||||
}
|
||||
|
||||
function updateAlbums(data){
|
||||
var selectedId=$scope.selectedAlbum.AlbumId;
|
||||
$scope.albums=data;
|
||||
angular.forEach($scope.albums, function(album){
|
||||
if (album.AlbumId===selectedId)
|
||||
$scope.selectedAlbum=album;
|
||||
});
|
||||
}
|
||||
|
||||
function deleteSelected(){
|
||||
var images=getSelectedImageIds();
|
||||
if (images.length===0 || !confirm("Are you sure you want to delete?"))
|
||||
return;
|
||||
|
||||
var data={
|
||||
selectedImages:images
|
||||
};
|
||||
|
||||
$http.post("/gallery/deleteimages",data).then(function(response){
|
||||
updateAlbums(response.data);
|
||||
});
|
||||
};
|
||||
|
||||
function moveImages(newAlbum){
|
||||
var images=getSelectedImageIds();
|
||||
if (images.length===0)
|
||||
return;
|
||||
|
||||
var data={
|
||||
selectedImages:images,
|
||||
targetAlbumId:newAlbum.AlbumId
|
||||
};
|
||||
$http.post("/gallery/move",data).then(function(response){
|
||||
updateAlbums(response.data);
|
||||
});
|
||||
}
|
||||
|
||||
$scope.$watch("albums", function(){
|
||||
if ($scope.selectedAlbum===undefined)
|
||||
$scope.selectedAlbum=$scope.albums[0];
|
||||
|
||||
albumActions={};
|
||||
angular.forEach($scope.albums, function(album){
|
||||
albumActions[album.AlbumTitle]=function(){
|
||||
moveImages(album);
|
||||
};
|
||||
});
|
||||
$scope.contextMenuActions[moveIndex]=albumActions;
|
||||
});
|
||||
|
||||
$scope.selectImage=function(image){
|
||||
image.selected=!image.selected;
|
||||
};
|
||||
|
||||
$scope.editAlbum=function(album){
|
||||
Navigate("/gallery/editablum/"+album.AlbumId);
|
||||
};
|
||||
}]);
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
angular.module("robware").controller('galleryUpload', ["$scope", "$http", function($scope, $http) {
|
||||
$scope.images = [];
|
||||
$scope.contextMenuActions = {
|
||||
Remove: remove,
|
||||
Clear: clear
|
||||
};
|
||||
|
||||
function remove(containerScope) {
|
||||
if (!containerScope.image)
|
||||
return;
|
||||
|
||||
var index = $scope.images.indexOf(containerScope.image);
|
||||
if (index !== -1)
|
||||
$scope.images.splice(index, 1);
|
||||
}
|
||||
|
||||
function clear() {
|
||||
if (confirm("Are you sure you want to clear the uploads?"))
|
||||
$scope.images = [];
|
||||
}
|
||||
|
||||
function removeImages(toRemove) {
|
||||
// I need this roundabout way to work with Angular's view engine
|
||||
var imageReferences = [];
|
||||
angular.forEach(toRemove, function(index) {
|
||||
imageReferences.push($scope.images[index]);
|
||||
});
|
||||
angular.forEach(imageReferences, function(ref) {
|
||||
$scope.images.splice($scope.images.indexOf(ref), 1);
|
||||
});
|
||||
}
|
||||
|
||||
$scope.getTotalImageSize = function() {
|
||||
var totalSize = 0;
|
||||
angular.forEach($scope.images, function(image) {
|
||||
totalSize += image.file.size;
|
||||
});
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
$scope.safeUploadSize = function() {
|
||||
return $scope.maxUploadSize * 0.95;
|
||||
}
|
||||
|
||||
$scope.fileDrop = function(files) {
|
||||
angular.forEach(files, function(file) {
|
||||
var imageObject = {
|
||||
file: file,
|
||||
title: file.name.replace(/\.[^/.]+$/, ""),
|
||||
description: "",
|
||||
preview: ""
|
||||
};
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
imageObject.preview = e.target.result;
|
||||
$scope.$apply();
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
|
||||
$scope.images.push(imageObject);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.upload = function() {
|
||||
var data = new FormData();
|
||||
var errors = [];
|
||||
angular.forEach($scope.images, function(image) {
|
||||
if (!image.title)
|
||||
errors.push("The image " + image.file.name + " doesn't have a title");
|
||||
data.append("files[]", image.file);
|
||||
data.append("title[]", image.title);
|
||||
data.append("description[]", image.description);
|
||||
});
|
||||
|
||||
var totalSize = 0;
|
||||
data.getAll("files[]").forEach(function(entry){
|
||||
totalSize += entry.size;
|
||||
});
|
||||
if (totalSize>$scope.safeUploadSize())
|
||||
errors.push("Max upload size exceeded");
|
||||
|
||||
if (errors.length>0){
|
||||
$scope.showErrors(errors);
|
||||
return;
|
||||
}
|
||||
|
||||
$http({
|
||||
method: 'POST',
|
||||
url: '/gallery/uploadimages',
|
||||
data: data,
|
||||
showSpinner: true,
|
||||
headers: {'Content-Type': undefined},
|
||||
transformRequest: angular.identity
|
||||
}).then(function(response) {
|
||||
$scope.showErrors(response.data.errors);
|
||||
removeImages(response.data.uploaded);
|
||||
});
|
||||
};
|
||||
}]);
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
/* global app, angular */
|
||||
|
||||
angular.module("robware", ['ngAnimate'], ["$httpProvider", function($httpProvider) {
|
||||
/*
|
||||
* Stolen from: http://stackoverflow.com/questions/19254029/angularjs-http-post-does-not-send-data
|
||||
* Reason: send payload as form data instead of JSON, bind to controller action parameters
|
||||
*/
|
||||
// Use x-www-form-urlencoded Content-Type
|
||||
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
|
||||
/**
|
||||
* The workhorse; converts an object to x-www-form-urlencoded serialization.
|
||||
* @param {Object} obj
|
||||
* @return {String}
|
||||
*/
|
||||
var param = function(obj) {
|
||||
var query = '', name, value, fullSubName, subName, subValue, innerObj, i;
|
||||
for (name in obj) {
|
||||
value = obj[name];
|
||||
if (value instanceof Array) {
|
||||
for (i = 0; i < value.length; ++i) {
|
||||
subValue = value[i];
|
||||
fullSubName = name + '[' + i + ']';
|
||||
innerObj = {};
|
||||
innerObj[fullSubName] = subValue;
|
||||
query += param(innerObj) + '&';
|
||||
}
|
||||
}
|
||||
else if (value instanceof Object) {
|
||||
for (subName in value) {
|
||||
subValue = value[subName];
|
||||
fullSubName = name + '[' + subName + ']';
|
||||
innerObj = {};
|
||||
innerObj[fullSubName] = subValue;
|
||||
query += param(innerObj) + '&';
|
||||
}
|
||||
}
|
||||
else if (value !== undefined && value !== null)
|
||||
query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
|
||||
}
|
||||
|
||||
return query.length ? query.substr(0, query.length - 1) : query;
|
||||
};
|
||||
// Override $http service's default transformRequest
|
||||
$httpProvider.defaults.transformRequest = [
|
||||
function(data) {
|
||||
return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
|
||||
}
|
||||
];
|
||||
|
||||
$httpProvider.interceptors.push([
|
||||
'$rootScope',
|
||||
'$q',
|
||||
function($rootScope, $q) {
|
||||
return {
|
||||
request: function(config) {
|
||||
if (config.showSpinner)
|
||||
$rootScope.showSpinner();
|
||||
return config;
|
||||
},
|
||||
requestError: function(rejection) {
|
||||
$rootScope.hideSpinner();
|
||||
return $q.reject(rejection);
|
||||
},
|
||||
response: function(response) {
|
||||
$rootScope.hideSpinner();
|
||||
return response;
|
||||
},
|
||||
responseError: function(rejection) {
|
||||
$rootScope.hideSpinner();
|
||||
return $q.reject(rejection);
|
||||
}
|
||||
};
|
||||
}
|
||||
]);
|
||||
}]);
|
||||
|
||||
angular.module("robware").controller("main", ['$scope', '$rootScope', function ($scope, $rootScope) {
|
||||
var largeWindowBoundary = 1023;
|
||||
|
||||
$scope.menuVisible = false;//window.innerWidth > largeWindowBoundary;
|
||||
|
||||
$scope.shouldShowMenu = function() {
|
||||
return $scope.menuVisible || window.innerWidth > largeWindowBoundary;
|
||||
};
|
||||
|
||||
$scope.spinnerVisible = false;
|
||||
|
||||
$rootScope.showSpinner = function() {
|
||||
$scope.spinnerVisible = true;
|
||||
};
|
||||
|
||||
$rootScope.hideSpinner = function() {
|
||||
$scope.spinnerVisible = false;
|
||||
};
|
||||
|
||||
$(window).on("resize.doResize", function() {
|
||||
$scope.$apply(function() {
|
||||
//$scope.menuVisible = false;
|
||||
});
|
||||
});
|
||||
|
||||
$scope.errors=[];
|
||||
$scope.showErrors=function(errors){
|
||||
$scope.errors=errors;
|
||||
}
|
||||
}]);
|
|
@ -1,65 +0,0 @@
|
|||
angular.module("robware").controller('status', ["$scope", "statusService", "$interval", function($scope, statusService, $interval) {
|
||||
$scope.chartData=[];
|
||||
var chartDataId=0;
|
||||
|
||||
function reloadUptime() {
|
||||
statusService.getUptime().then(function(data) {
|
||||
$scope.uptime = data;
|
||||
$scope.haveUptime = true;
|
||||
});
|
||||
}
|
||||
$scope.haveUptime = false;
|
||||
$scope.uptime = {};
|
||||
reloadUptime();
|
||||
$interval(reloadUptime, 60000);
|
||||
|
||||
function reloadSystemInfo() {
|
||||
statusService.getSystemInfo().then(function(data) {
|
||||
if ($scope.chartData.length>=50)
|
||||
$scope.chartData.shift();
|
||||
$scope.chartData=$scope.chartData.concat([{id: chartDataId, CPU: data.load[0]*100, Mem: data.memUsage, Temp: data.cpuTemp}]);
|
||||
chartDataId++;
|
||||
$scope.load = data.load;
|
||||
$scope.cpuTemp = data.cpuTemp;
|
||||
$scope.memory = {
|
||||
free: data.memFree,
|
||||
used: data.memUsage,
|
||||
total: data.memTotal
|
||||
};
|
||||
$scope.haveSystemInfo = true;
|
||||
});
|
||||
}
|
||||
$scope.haveSystemInfo = false;
|
||||
$scope.load = {};
|
||||
$scope.loadHistory = [];
|
||||
$scope.cpuTemp = 0;
|
||||
$scope.systemInfoRefreshInterval = 5;
|
||||
var systemRefresh = $interval(reloadSystemInfo, $scope.systemInfoRefreshInterval * 1000);
|
||||
reloadSystemInfo();
|
||||
$scope.changeSystemInfoRefreshInterval = function(amount) {
|
||||
$scope.systemInfoRefreshInterval += amount;
|
||||
if ($scope.systemInfoRefreshInterval < 1)
|
||||
return;
|
||||
$interval.cancel(systemRefresh);
|
||||
systemRefresh = $interval(reloadSystemInfo, $scope.systemInfoRefreshInterval * 1000);
|
||||
};
|
||||
|
||||
function reloadProcesses() {
|
||||
statusService.getProcesses().then(function(data) {
|
||||
$scope.processes = data;
|
||||
$scope.haveProcesses = true;
|
||||
});
|
||||
}
|
||||
$scope.haveProcesses = false;
|
||||
$scope.processses = {};
|
||||
$scope.processRefreshInterval = 10;
|
||||
var processRefesh = $interval(reloadProcesses, $scope.processRefreshInterval * 1000);
|
||||
reloadProcesses();
|
||||
$scope.changeProcesRefreshInterval = function(amount) {
|
||||
$scope.processRefreshInterval += amount;
|
||||
if ($scope.processRefreshInterval < 1)
|
||||
return;
|
||||
$interval.cancel(processRefesh);
|
||||
processRefesh = $interval(reloadProcesses, $scope.processRefreshInterval * 1000);
|
||||
};
|
||||
}]);
|
|
@ -1,56 +0,0 @@
|
|||
angular.module("robware").controller('temperature', ["$scope", "temperatureService", "$interval", function($scope, temperatureService, $interval) {
|
||||
$scope.readings = [];
|
||||
$scope.temperatureData = {};
|
||||
|
||||
$scope.$watch("readings", function() {
|
||||
for (var i = 0; i < $scope.readings.length; i++) {
|
||||
$scope.readings[i].Timestamp = new Date($scope.readings[i].Timestamp * 1000);
|
||||
}
|
||||
});
|
||||
|
||||
function getData() {
|
||||
temperatureService.getReadings().then(function(data) {
|
||||
$scope.readings = data;
|
||||
});
|
||||
}
|
||||
$interval(getData, 60000);
|
||||
|
||||
function updateCurrentTemperature() {
|
||||
temperatureService.getCurrentTemperatureData().then(function(data) {
|
||||
$scope.temperatureData = data;
|
||||
});
|
||||
}
|
||||
$interval(updateCurrentTemperature, 5000);
|
||||
|
||||
var graphAdjustment = 10;
|
||||
|
||||
$scope.getGraphPercentage = function() {
|
||||
var graphTarget = ($scope.temperatureData.target * 1.2) - graphAdjustment;
|
||||
var graphTemperature = $scope.temperatureData.temperature - graphAdjustment;
|
||||
return Math.min((graphTemperature / graphTarget) * 100, 100);
|
||||
};
|
||||
|
||||
function getPercentage() {
|
||||
return (($scope.temperatureData.target - graphAdjustment) / (($scope.temperatureData.temperature * 1.5) - graphAdjustment)) * 100;
|
||||
}
|
||||
|
||||
$scope.getRed = function() {
|
||||
var percentage = getPercentage();
|
||||
return 255 * (1 - (Math.min(50, percentage) / 50));
|
||||
};
|
||||
|
||||
$scope.getBlue = function() {
|
||||
var percentage = Math.max(getPercentage() - 50, 0);
|
||||
return 255 * (Math.min(50, percentage) / 50);
|
||||
};
|
||||
|
||||
$scope.getGreen = function() {
|
||||
var percentage = getPercentage();
|
||||
percentage = Math.min(percentage, 75);
|
||||
percentage = Math.max(percentage, 25);
|
||||
percentage = Math.abs(50 - percentage);
|
||||
percentage /= 25;
|
||||
return 255 * (1 - Math.max(percentage, 0));
|
||||
};
|
||||
}]);
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
angular.module("robware").controller("weight", ["$scope", "weightService", function($scope, weightService) {
|
||||
$scope.submitting = false;
|
||||
$scope.weight = null;
|
||||
$scope.fat = null;
|
||||
|
||||
$scope.readings = [];
|
||||
$scope.headings = {weight: "Weight (KG)", fat: "Fat %", bmi: "BMI"};
|
||||
|
||||
function refreshReadings() {
|
||||
weightService.getReadings().then(function(data) {
|
||||
$scope.readings = data;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.$watch("readings", function() {
|
||||
for (var i = 0; i < $scope.readings.length; i++) {
|
||||
$scope.readings[i].date = new Date($scope.readings[i].date);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.addReading = function() {
|
||||
if (!$scope.weight || !$scope.fat)
|
||||
return;
|
||||
|
||||
$scope.submitting = true;
|
||||
weightService.addWeight($scope.weight, $scope.fat).then(function(data) {
|
||||
refreshReadings();
|
||||
$scope.submitting = false;
|
||||
$scope.weight = null;
|
||||
$scope.fat = null;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteReading = function(id) {
|
||||
weightService.deleteWeight(id).then(function() {
|
||||
refreshReadings();
|
||||
});
|
||||
};
|
||||
|
||||
Object.defineProperty($scope, "tenLatestReadings", {
|
||||
get: function() {
|
||||
var temp = $scope.readings.slice(-10);
|
||||
temp.reverse();
|
||||
return temp;
|
||||
}
|
||||
});
|
||||
}]);
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
angular.module("robware").directive('contextMenu', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
templateUrl: '/scripts/directives/templates/contextMenu.html',
|
||||
scope: {
|
||||
actions: '=',
|
||||
isChild: '=?'
|
||||
},
|
||||
link: function(scope, element) {
|
||||
scope.isFunction = angular.isFunction;
|
||||
scope.show=false;
|
||||
scope.selectedElement=null;
|
||||
scope.subMenuShowKey="";
|
||||
|
||||
scope.changeSubMenuShowKey=function(name){
|
||||
scope.subMenuShowKey=name;
|
||||
};
|
||||
|
||||
function show(x, y, target){
|
||||
scope.changeSubMenuShowKey("");
|
||||
scope.menuX=x+"px";
|
||||
scope.menuY=y+"px";
|
||||
scope.selectedElement=target;
|
||||
scope.show=true;
|
||||
};
|
||||
|
||||
function hide(){
|
||||
scope.show=false;
|
||||
}
|
||||
|
||||
scope.performAction=function(func){
|
||||
if (!angular.isFunction(func))
|
||||
return;
|
||||
func($(scope.selectedElement).scope());
|
||||
hide();
|
||||
};
|
||||
|
||||
$(document).on("click", function(e){
|
||||
hide();
|
||||
scope.$apply();
|
||||
});
|
||||
|
||||
var parent=element.parent()[0];
|
||||
|
||||
if (scope.isChild){
|
||||
show(parent.clientWidth,parent.clientTop);
|
||||
}else
|
||||
$(parent).css("position","relative");
|
||||
element.parent().on("contextmenu", function(e){
|
||||
var offset=$(element).offset();
|
||||
show(e.pageX-offset.left, e.pageY-offset.top, e.target);
|
||||
scope.$apply();
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
angular.module("robware").directive('dragDrop', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
dragDrop:'='
|
||||
},
|
||||
link: function(scope, element) {
|
||||
function handleEvent(e){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
element.on('dragover', function(e) {
|
||||
handleEvent(e);
|
||||
});
|
||||
element.on('dragenter', function(e) {
|
||||
handleEvent(e);
|
||||
$(element).addClass("dragOver");
|
||||
});
|
||||
element.on('dragleave', function(e) {
|
||||
handleEvent(e);
|
||||
$(element).removeClass("dragOver");
|
||||
});
|
||||
element.on('drop', function(e){
|
||||
handleEvent(e);
|
||||
$(element).removeClass("dragOver");
|
||||
|
||||
if (e.originalEvent.dataTransfer){
|
||||
if (e.originalEvent.dataTransfer.files.length > 0) {
|
||||
scope.dragDrop(e.originalEvent.dataTransfer.files);
|
||||
scope.$apply();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
angular.module("robware").directive("equalWidth", function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope, element) {
|
||||
scope.getHeight = function() {
|
||||
return $(element).height();
|
||||
};
|
||||
scope.$watch(scope.getHeight, function(height) {
|
||||
$(element).width(height);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
/* global google, angular */
|
||||
|
||||
angular.module("robware").directive('googleChart', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
templateUrl: '/scripts/directives/templates/googleChart.html',
|
||||
scope: {
|
||||
data: '=',
|
||||
headings: '=?',
|
||||
ignore: '=?',
|
||||
height: '='
|
||||
},
|
||||
link: function(scope, element, attributes) {
|
||||
var chartLoaded = false;
|
||||
|
||||
if (!scope.headings)
|
||||
scope.headings = [];
|
||||
|
||||
if (!scope.ignore)
|
||||
scope.ignore = [];
|
||||
|
||||
var chartData, chart;
|
||||
var chartOptions = {
|
||||
title: attributes.title,
|
||||
height: scope.height || 400,
|
||||
curveType: attributes.curveType,
|
||||
legend: {
|
||||
position: attributes.legendPosition || 'right'
|
||||
},
|
||||
vAxis: {
|
||||
title: attributes.vAxisTitle
|
||||
},
|
||||
backgroundColor: attributes.background || 'transparent'
|
||||
};
|
||||
|
||||
function formatToolTip(input, args) {
|
||||
return input.replace(/{(.+?)(:.*?)?}/g, function(match, index, format) {
|
||||
if (format)
|
||||
format = format.slice(1);
|
||||
if (args[index]===undefined)
|
||||
return match;
|
||||
if (isNumber(args[index]))
|
||||
return args[index].toString(format, true);
|
||||
return args[index].toString(format);
|
||||
});
|
||||
}
|
||||
|
||||
function shouldIgnore(value){
|
||||
return scope.ignore.indexOf(value)>-1;
|
||||
}
|
||||
|
||||
function setupChart() {
|
||||
if (!chartLoaded)
|
||||
return;
|
||||
|
||||
var firstRow = scope.data[0];
|
||||
var fields = {};
|
||||
for (var propertyName in firstRow) {
|
||||
if (shouldIgnore(propertyName))
|
||||
continue;
|
||||
|
||||
var datum = firstRow[propertyName];
|
||||
var type = typeof (datum);
|
||||
if (type === "object")
|
||||
type = datum.constructor.name;
|
||||
fields[propertyName] = {
|
||||
title: scope.headings[propertyName] || propertyName,
|
||||
type: type.toLowerCase()
|
||||
};
|
||||
}
|
||||
|
||||
chartData = new google.visualization.DataTable();
|
||||
angular.forEach(fields, function(value) {
|
||||
chartData.addColumn(value.type, value.title);
|
||||
if (attributes['toolTip' + value.title.upperCaseFirst()])
|
||||
chartData.addColumn({type: 'string', role: 'tooltip'});
|
||||
});
|
||||
|
||||
angular.forEach(scope.data, function(value) {
|
||||
var row = [];
|
||||
angular.forEach(value, function(value2, index) {
|
||||
if (shouldIgnore(index))
|
||||
return;
|
||||
|
||||
row.push(value2);
|
||||
var attrIndex = 'toolTip' + index.upperCaseFirst();
|
||||
if (attributes[attrIndex])
|
||||
row.push(formatToolTip(attributes[attrIndex], value));
|
||||
});
|
||||
chartData.addRow(row);
|
||||
});
|
||||
|
||||
chart = new google.visualization.LineChart(element[0]);
|
||||
drawChart();
|
||||
}
|
||||
|
||||
function drawChart() {
|
||||
chart.draw(chartData, chartOptions);
|
||||
}
|
||||
|
||||
$.getScript("https://www.google.com/jsapi", function() {
|
||||
//google.load('visualization', '1.1', {packages: ['line'], callback:function(){
|
||||
google.load('visualization', '1', {
|
||||
packages: ['corechart'],
|
||||
callback: function() {
|
||||
chartLoaded = true;
|
||||
setupChart();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
scope.$watch("data", function(v) {
|
||||
setupChart();
|
||||
});
|
||||
|
||||
angular.element(window).bind('resize', function() {
|
||||
drawChart();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
angular.module("robware").directive("scopeInit", function(){
|
||||
return {
|
||||
restrict : 'E',
|
||||
link:function(scope, element, attributes){
|
||||
var content=element[0].innerHTML.trim();
|
||||
scope[attributes.value]=JSON.parse(content);
|
||||
element.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
<div class="contextMenu" ng-if="show" ng-style="{left:menuX,top:menuY}">
|
||||
<div ng-repeat="(name, func) in actions track by name" class="menuItem" ng-click="performAction(func)" ng-mouseover="changeSubMenuShowKey(name)">
|
||||
{{name}}<span class="arrow" ng-if="!isFunction(func)"> ›</span>
|
||||
<context-menu ng-if="!isFunction(func)" actions="func" is-child="true" ng-show="subMenuShowKey==name"></context-menu>
|
||||
</div>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
<div class="mapsContainer">Loading chart...</div>
|
|
@ -6,7 +6,7 @@ function CreateCookie(name, value, days) {
|
|||
var expires;
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
|
||||
expires = "; expires=" + date.toGMTString();
|
||||
}
|
||||
else {
|
||||
|
@ -58,88 +58,3 @@ Number.prototype.toString=function(input, shouldRound){
|
|||
|
||||
return round(this, input);
|
||||
};
|
||||
|
||||
$(function() {
|
||||
var panels = $("nav > dl > .sub-pages");
|
||||
var goIndicators = $("nav > dl > dt .go");
|
||||
var expandIndicators = $("nav > dl > dt .expand");
|
||||
panels.hide();
|
||||
expandIndicators.show();
|
||||
|
||||
$("nav > dl > dt").click(function(e) {
|
||||
var next = $(this).next();
|
||||
if (!next.hasClass("sub-pages")) {
|
||||
Navigate($(this).children("a").attr("href"));
|
||||
return;
|
||||
}
|
||||
panels.slideUp();
|
||||
goIndicators.hide();
|
||||
expandIndicators.show();
|
||||
if (next.is(":visible")) {
|
||||
return;
|
||||
}
|
||||
next.slideDown();
|
||||
$(this).children(".go").show();
|
||||
$(this).children(".expand").hide();
|
||||
});
|
||||
|
||||
$("nav dd").click(function(e) {
|
||||
Navigate($(this).children("a").attr("href"));
|
||||
});
|
||||
|
||||
$("nav a").click(function(e) {
|
||||
$(this).parent().click();
|
||||
return false;
|
||||
});
|
||||
|
||||
$("#body").css("padding-bottom", window.innerHeight - $("#buttons-right").offset().top);
|
||||
|
||||
$("form[ajaxForm]").submit(function(e) {
|
||||
e.preventDefault();
|
||||
form = $(this);
|
||||
$.ajax({
|
||||
url: form.attr("action"),
|
||||
method: form.attr("method"),
|
||||
data: form.serialize(),
|
||||
success: function(data) {
|
||||
var successFunction = form.attr("onsuccess");
|
||||
if (successFunction !== undefined && window[successFunction] !== undefined)
|
||||
window[successFunction](data);
|
||||
},
|
||||
error: function() {
|
||||
var errorFunction = form.attr("onerror");
|
||||
if (errorFunction !== undefined && window[errorFunction] !== undefined)
|
||||
window[errorFunction]();
|
||||
},
|
||||
});
|
||||
var postFunction = form.attr("onpost");
|
||||
if (postFunction !== undefined && window[postFunction] !== undefined)
|
||||
window[postFunction]();
|
||||
});
|
||||
|
||||
$("td").each(function() {
|
||||
var elem = $(this);
|
||||
if (/^[+-]?\d+(\.\d+)?$/.test(elem.text())) {
|
||||
elem.addClass("number");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).delegate('.allowTabInput', 'keydown', function(e) {
|
||||
var keyCode = e.keyCode || e.which;
|
||||
console.log(e);
|
||||
if (keyCode == 9) {
|
||||
e.preventDefault();
|
||||
var start = $(this).get(0).selectionStart;
|
||||
var end = $(this).get(0).selectionEnd;
|
||||
|
||||
// set textarea value to: text before caret + tab + text after caret
|
||||
$(this).val($(this).val().substring(0, start)
|
||||
+ "\t"
|
||||
+ $(this).val().substring(end));
|
||||
|
||||
// put caret at right position again
|
||||
$(this).get(0).selectionStart =
|
||||
$(this).get(0).selectionEnd = start + 1;
|
||||
}
|
||||
});
|
|
@ -1,60 +0,0 @@
|
|||
angular.module("robware").service('statusService', ["$http", function($http) {
|
||||
function parseProcessData(data) {
|
||||
var headers = data.shift();
|
||||
var cpuIndex = -1;
|
||||
var ignoreColNames = ["user", "pid", "vsz", "rss", "tty", "stat"];
|
||||
var ignoreCols = [];
|
||||
|
||||
var processHeaders = []
|
||||
for (var col in headers) {
|
||||
if (headers[col].toLowerCase() === "%cpu")
|
||||
cpuIndex = col;
|
||||
|
||||
if (ignoreColNames.indexOf(headers[col].toLowerCase()) > -1)
|
||||
ignoreCols.push(col);
|
||||
else
|
||||
processHeaders.push(headers[col]);
|
||||
}
|
||||
|
||||
data.sort(function (a, b) {
|
||||
cpuA = parseFloat(a[cpuIndex]);
|
||||
cpuB = parseFloat(b[cpuIndex]);
|
||||
if (cpuA > cpuB)
|
||||
return -1;
|
||||
if (cpuA < cpuB)
|
||||
return 1
|
||||
return 0;
|
||||
});
|
||||
|
||||
var processData = [];
|
||||
for (var row in data) {
|
||||
var obj = {};
|
||||
for (var col in data[row]) {
|
||||
if (ignoreCols.indexOf(col) === -1)
|
||||
obj[headers[col]] = data[row][col];
|
||||
}
|
||||
processData.push(obj);
|
||||
}
|
||||
|
||||
return [processHeaders, processData];
|
||||
}
|
||||
|
||||
this.getProcesses = function() {
|
||||
return $http.get('/status/getprocesses').then(function(response) {
|
||||
parsedData = parseProcessData(response.data);
|
||||
return {headers: parsedData[0], data: parsedData[1]};
|
||||
});
|
||||
};
|
||||
|
||||
this.getSystemInfo=function(){
|
||||
return $http.get('/status/getsysteminfo').then(function(response){
|
||||
return response.data;
|
||||
});
|
||||
};
|
||||
|
||||
this.getUptime=function(){
|
||||
return $http.get('/status/getuptime').then(function(response){
|
||||
return response.data;
|
||||
})
|
||||
};
|
||||
}]);
|
|
@ -1,13 +0,0 @@
|
|||
angular.module("robware").service('temperatureService', ["$http", function($http) {
|
||||
this.getReadings = function() {
|
||||
return $http.get('/temperature/getreadings', {dontShowSpinner:true}).then(function(response) {
|
||||
return response.data;
|
||||
});
|
||||
};
|
||||
|
||||
this.getCurrentTemperatureData = function() {
|
||||
return $http.get("/temperature/GetTemperatureData", {dontShowSpinner:true}).then(function(response) {
|
||||
return response.data;
|
||||
});
|
||||
}
|
||||
}]);
|
|
@ -1,31 +0,0 @@
|
|||
angular.module("robware").service('weightService', ["$http", function($http) {
|
||||
this.addWeight=function(weight, fat){
|
||||
return $http({
|
||||
method:'post',
|
||||
url:'/weight/add',
|
||||
data:{weight:weight, fat:fat},
|
||||
showSpinner:true
|
||||
}).then(function(response){
|
||||
return response.data;
|
||||
});
|
||||
};
|
||||
this.deleteWeight=function(id){
|
||||
return $http({
|
||||
method:'post',
|
||||
url:'/weight/delete',
|
||||
data:{id:id},
|
||||
showSpinner:true
|
||||
}).then(function(response){
|
||||
return response.data;
|
||||
});
|
||||
};
|
||||
this.getReadings=function(){
|
||||
return $http({
|
||||
method:'post',
|
||||
url:'/weight/getreadings',
|
||||
showSpinner:true
|
||||
}).then(function(response){
|
||||
return response.data;
|
||||
});
|
||||
};
|
||||
}]);
|
Loading…
Add table
Add a link
Reference in a new issue