├── .gitignore ├── start.bat ├── logs └── readme.txt ├── frontend ├── img │ ├── favicon.ico │ ├── ajax-loader.gif │ ├── sidebar-1.jpg │ ├── sidebar-2.jpg │ ├── sidebar-3.jpg │ ├── sidebar-4.jpg │ └── sidebar-5.jpg ├── sass │ ├── lbd │ │ ├── mixins │ │ │ ├── _tabs.scss │ │ │ ├── _cards.scss │ │ │ ├── _navbars.scss │ │ │ ├── _icons.scss │ │ │ ├── _inputs.scss │ │ │ ├── _transparency.scss │ │ │ ├── _labels.scss │ │ │ ├── _social-buttons.scss │ │ │ ├── _morphing-buttons.scss │ │ │ ├── _buttons.scss │ │ │ ├── _chartist.scss │ │ │ └── _vendor-prefixes.scss │ │ ├── _mixins.scss │ │ ├── _tables.scss │ │ ├── _misc.scss │ │ ├── _footers.scss │ │ ├── _alerts.scss │ │ ├── _typography.scss │ │ ├── _buttons.scss │ │ ├── _dropdown.scss │ │ ├── _inputs.scss │ │ ├── _cards.scss │ │ ├── _checkbox-radio-switch.scss │ │ ├── _sidebar-and-main-panel.scss │ │ ├── _chartist.scss │ │ ├── _navbars.scss │ │ ├── _variables.scss │ │ └── _responsive.scss │ └── light-bootstrap-dashboard.scss ├── fonts │ ├── Pe-icon-7-stroke.eot │ ├── Pe-icon-7-stroke.ttf │ ├── Pe-icon-7-stroke.woff │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── js │ ├── npm.js │ ├── angular │ │ ├── show-errors.min.js │ │ ├── angular-resource.min.js │ │ └── angular-resource.min.js.map │ └── light-bootstrap-dashboard.js ├── app │ ├── app.js │ ├── angular-toggle-switch.js │ └── services.js ├── css │ ├── style.css │ ├── angular-toggle-switch-bootstrap-3.css │ └── pe-icon-7-stroke.css ├── index.html ├── advanced.html ├── rules.html ├── help.html └── entrylist.html ├── settings.js ├── .gitattributes ├── package.json ├── acServerManager.bat ├── README.md └── README_Linux.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /start.bat: -------------------------------------------------------------------------------- 1 | node server.js 2 | pause -------------------------------------------------------------------------------- /logs/readme.txt: -------------------------------------------------------------------------------- 1 | Dated Assetto Corsa Server Logs -------------------------------------------------------------------------------- /frontend/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jo3stevens/ACServerManager/HEAD/frontend/img/favicon.ico -------------------------------------------------------------------------------- /frontend/img/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jo3stevens/ACServerManager/HEAD/frontend/img/ajax-loader.gif -------------------------------------------------------------------------------- /frontend/img/sidebar-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jo3stevens/ACServerManager/HEAD/frontend/img/sidebar-1.jpg -------------------------------------------------------------------------------- /frontend/img/sidebar-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jo3stevens/ACServerManager/HEAD/frontend/img/sidebar-2.jpg -------------------------------------------------------------------------------- /frontend/img/sidebar-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jo3stevens/ACServerManager/HEAD/frontend/img/sidebar-3.jpg -------------------------------------------------------------------------------- /frontend/img/sidebar-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jo3stevens/ACServerManager/HEAD/frontend/img/sidebar-4.jpg -------------------------------------------------------------------------------- /frontend/img/sidebar-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jo3stevens/ACServerManager/HEAD/frontend/img/sidebar-5.jpg -------------------------------------------------------------------------------- /frontend/sass/lbd/mixins/_tabs.scss: -------------------------------------------------------------------------------- 1 | @mixin pill-style($color){ 2 | border: 1px solid $color; 3 | color: $color; 4 | } -------------------------------------------------------------------------------- /frontend/fonts/Pe-icon-7-stroke.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jo3stevens/ACServerManager/HEAD/frontend/fonts/Pe-icon-7-stroke.eot -------------------------------------------------------------------------------- /frontend/fonts/Pe-icon-7-stroke.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jo3stevens/ACServerManager/HEAD/frontend/fonts/Pe-icon-7-stroke.ttf -------------------------------------------------------------------------------- /frontend/fonts/Pe-icon-7-stroke.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jo3stevens/ACServerManager/HEAD/frontend/fonts/Pe-icon-7-stroke.woff -------------------------------------------------------------------------------- /frontend/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jo3stevens/ACServerManager/HEAD/frontend/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /frontend/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jo3stevens/ACServerManager/HEAD/frontend/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /frontend/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jo3stevens/ACServerManager/HEAD/frontend/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /frontend/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jo3stevens/ACServerManager/HEAD/frontend/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /settings.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | serverPath: '../server/', 3 | contentPath: '', 4 | sTrackerPath: '', 5 | username: '', 6 | password: '', 7 | port: 42555 8 | }; -------------------------------------------------------------------------------- /frontend/sass/lbd/mixins/_cards.scss: -------------------------------------------------------------------------------- 1 | @mixin filter($color){ 2 | @if $color == #FFFFFF{ 3 | background-color: rgba($color,.91); 4 | } @else { 5 | background-color: rgba($color,.69); 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /frontend/sass/lbd/mixins/_navbars.scss: -------------------------------------------------------------------------------- 1 | @mixin navbar-color($color){ 2 | background-color: $color; 3 | } 4 | 5 | @mixin center-item(){ 6 | left: 0; 7 | right: 0; 8 | margin-right: auto; 9 | margin-left: auto; 10 | position: absolute; 11 | } -------------------------------------------------------------------------------- /frontend/sass/lbd/mixins/_icons.scss: -------------------------------------------------------------------------------- 1 | @mixin icon-background ($icon-url){ 2 | background-image : url($icon-url); 3 | 4 | } 5 | 6 | @mixin icon-shape ($size, $padding, $border-radius) { 7 | height: $size; 8 | width: $size; 9 | padding: $padding; 10 | border-radius: $border-radius; 11 | display: inline-table; 12 | 13 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Declare files that will always have CRLF line endings on checkout. 5 | *.html text eol=crlf 6 | *.js text eol=crlf 7 | *.css text eol=crlf 8 | 9 | # Denote all files that are truly binary and should not be modified. 10 | *.png binary 11 | *.jpg binary 12 | *.ico binary 13 | *.gif binary 14 | -------------------------------------------------------------------------------- /frontend/sass/lbd/mixins/_inputs.scss: -------------------------------------------------------------------------------- 1 | @mixin input-size($padding-vertical, $padding-horizontal, $height){ 2 | padding: $padding-vertical $padding-horizontal; 3 | height: $height; 4 | } 5 | 6 | @mixin placeholder($color, $opacity){ 7 | color: $color; 8 | @include opacity(1); 9 | } 10 | 11 | @mixin light-form(){ 12 | border-radius: 0; 13 | border:0; 14 | padding: 0; 15 | background-color: transparent; 16 | 17 | } -------------------------------------------------------------------------------- /frontend/sass/lbd/_mixins.scss: -------------------------------------------------------------------------------- 1 | //Utilities 2 | 3 | @import "mixins/transparency"; 4 | @import "mixins/vendor-prefixes"; 5 | 6 | 7 | //Components 8 | 9 | @import "mixins/buttons"; 10 | @import "mixins/inputs"; 11 | @import "mixins/labels"; 12 | @import "mixins/tabs"; 13 | 14 | @import "mixins/navbars"; 15 | @import "mixins/icons"; 16 | @import "mixins/social-buttons"; 17 | 18 | @import "mixins/morphing-buttons"; 19 | 20 | @import "mixins/cards"; 21 | 22 | @import "mixins/chartist"; -------------------------------------------------------------------------------- /frontend/sass/lbd/mixins/_transparency.scss: -------------------------------------------------------------------------------- 1 | // Opacity 2 | 3 | @mixin opacity($opacity) { 4 | opacity: $opacity; 5 | // IE8 filter 6 | $opacity-ie: ($opacity * 100); 7 | filter: #{alpha(opacity=$opacity-ie)}; 8 | } 9 | 10 | @mixin black-filter($opacity){ 11 | top: 0; 12 | left: 0; 13 | height: 100%; 14 | width: 100%; 15 | position: absolute; 16 | background-color: rgba(17,17,17,$opacity); 17 | display: block; 18 | content: ""; 19 | z-index: 1; 20 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "acsm", 3 | "version": "0.0.3", 4 | "description": "Assetto Corsa Server Manager", 5 | "main": "server.js", 6 | "author": "Joe Stevens", 7 | "dependencies": { 8 | "express": "^4.14.1", 9 | "fs": "latest", 10 | "ini": "~1.3.4", 11 | "multi-ini": "~1.0.0", 12 | "body-parser": "~1.16.0", 13 | "child_process": "^1.0.2", 14 | "basic-auth-connect": "^1.0.0", 15 | "jsonfile": "^2.4.0", 16 | "util": "^0.10.3", 17 | "node.extend": "^1.1.6" 18 | } 19 | } -------------------------------------------------------------------------------- /frontend/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /frontend/app/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular 4 | .module('acServerManager', ['acServerManager.services', 'ui.bootstrap', 'ui.bootstrap.showErrors', 'toggle-switch']) 5 | 6 | .directive('stringToNumber', function() { 7 | return { 8 | require: 'ngModel', 9 | link: function(scope, element, attrs, ngModel) { 10 | ngModel.$parsers.push(function(value) { 11 | return '' + value; 12 | }); 13 | ngModel.$formatters.push(function(value) { 14 | return parseFloat(value, 10); 15 | }); 16 | } 17 | }; 18 | }); -------------------------------------------------------------------------------- /frontend/sass/lbd/mixins/_labels.scss: -------------------------------------------------------------------------------- 1 | @mixin label-style(){ 2 | padding: $padding-label-vertical $padding-label-horizontal; 3 | border: 1px solid $default-color; 4 | border-radius: $border-radius-small; 5 | color: $default-color; 6 | font-weight: $font-weight-semi; 7 | font-size: $font-size-small; 8 | text-transform: uppercase; 9 | display: inline-block; 10 | vertical-align: middle; 11 | } 12 | 13 | @mixin label-color($color){ 14 | border-color: $color; 15 | color: $color; 16 | } 17 | @mixin label-color-fill($color){ 18 | border-color: $color; 19 | color: $white-color; 20 | background-color: $color; 21 | } -------------------------------------------------------------------------------- /acServerManager.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cls 3 | cd content/tracks 4 | FOR /D %%G in (*) DO ( 5 | echo Removing existing ui folder for %%G 6 | rmdir "%~dp0server\content\tracks\%%G\ui\" /s /q 7 | echo Creating ui folder for %%G 8 | mkdir "%~dp0server\content\tracks\%%G\ui" 9 | echo Copying ui folder for %%G 10 | xcopy /s /e /y %%G\ui "%~dp0server\content\tracks\%%G\ui" 11 | ) 12 | cd ../cars 13 | FOR /D %%G in (*) DO ( 14 | echo Removing skins folder for %%G 15 | rmdir "%~dp0server\content\cars\%%G\skins\" /s /q 16 | echo Creating skins folder for %%G 17 | mkdir "%~dp0server\content\cars\%%G\skins" 18 | echo Copying skins directory structure for %%G 19 | xcopy /t /e /y %%G\skins "%~dp0server\content\cars\%%G\skins" 20 | ) -------------------------------------------------------------------------------- /frontend/sass/lbd/mixins/_social-buttons.scss: -------------------------------------------------------------------------------- 1 | @mixin social-buttons-color ($color){ 2 | 3 | border-color: $color; 4 | color: $color; 5 | 6 | &:hover, 7 | &:focus, 8 | &:active, 9 | &.active, 10 | .open > &.dropdown-toggle { 11 | background-color: $transparent-bg; 12 | color: $color; 13 | border-color: $color; 14 | opacity: 1; 15 | } 16 | 17 | &:disabled, 18 | &[disabled], 19 | &.disabled { 20 | background-color: $transparent-bg; 21 | border-color: $color; 22 | } 23 | 24 | &.btn-fill { 25 | color: $white-color; 26 | background-color: $color; 27 | opacity: 0.9; 28 | 29 | &:hover, 30 | &:focus, 31 | &:active, 32 | &.active, 33 | .open > &.dropdown-toggle{ 34 | background-color: $color; 35 | color: $white-color; 36 | opacity: 1; 37 | } 38 | 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /frontend/sass/lbd/mixins/_morphing-buttons.scss: -------------------------------------------------------------------------------- 1 | $prefixes: ('', '-moz-', '-webkit-', '-ms-') !default; 2 | 3 | @mixin circle-animation(){ 4 | @for $i from 0 to length($prefixes) { 5 | @include circle-animation-details(nth($prefixes, $i + 1)); 6 | } 7 | } 8 | 9 | @mixin circle-animation-details($name){ 10 | #{$name}animation-name: spin; 11 | #{$name}animation-duration: 1250ms; 12 | #{$name}animation-iteration-count: infinite; 13 | #{$name}animation-timing-function: linear; 14 | 15 | } 16 | @keyframes spin { 17 | from { transform:rotate(0deg); } 18 | to { transform:rotate(360deg); } 19 | } 20 | 21 | @-webkit-keyframes spin { 22 | from { -webkit-transform: rotate(0deg); } 23 | to { -webkit-transform: rotate(360deg); } 24 | } 25 | 26 | @-moz-keyframes spin { 27 | from { -moz-transform: rotate(0deg); } 28 | to { -moz-transform: rotate(360deg); } 29 | } 30 | 31 | @-ms-keyframes spin { 32 | from { -ms-transform: rotate(0deg); } 33 | to { -ms-transform: rotate(360deg); } 34 | } -------------------------------------------------------------------------------- /frontend/sass/light-bootstrap-dashboard.scss: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | 4 | ========================================================= 5 | * Light Bootstrap Dashboard - v1.3.1.0 6 | ========================================================= 7 | 8 | * Product Page: http://www.creative-tim.com/product/light-bootstrap-dashboard 9 | * Copyright 2017 Creative Tim (http://www.creative-tim.com) 10 | * Licensed under MIT (https://github.com/creativetimofficial/light-bootstrap-dashboard/blob/master/LICENSE.md) 11 | 12 | ========================================================= 13 | 14 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 15 | 16 | */ 17 | 18 | @import "lbd/variables"; 19 | @import "lbd/mixins"; 20 | 21 | @import "lbd/typography"; 22 | 23 | // Core CSS 24 | @import "lbd/misc"; 25 | @import "lbd/sidebar-and-main-panel"; 26 | @import "lbd/buttons"; 27 | @import "lbd/inputs"; 28 | 29 | @import "lbd/alerts"; 30 | @import "lbd/tables"; 31 | 32 | @import "lbd/checkbox-radio-switch"; 33 | @import "lbd/navbars"; 34 | @import "lbd/footers"; 35 | 36 | // Fancy Stuff 37 | @import "lbd/dropdown"; 38 | @import "lbd/cards"; 39 | @import "lbd/chartist"; 40 | @import "lbd/responsive"; 41 | -------------------------------------------------------------------------------- /frontend/sass/lbd/_tables.scss: -------------------------------------------------------------------------------- 1 | .table{ 2 | 3 | .radio, 4 | .checkbox{ 5 | position: relative; 6 | height: 20px; 7 | display: block; 8 | width: 20px; 9 | padding: 0px 0px; 10 | margin: 0px 5px; 11 | text-align: center; 12 | 13 | .icons{ 14 | left: 5px; 15 | } 16 | } 17 | > thead > tr > th, 18 | > tbody > tr > th, 19 | > tfoot > tr > th, 20 | > thead > tr > td, 21 | > tbody > tr > td, 22 | > tfoot > tr > td{ 23 | padding: 12px 8px; 24 | vertical-align: middle; 25 | } 26 | 27 | > thead > tr > th{ 28 | border-bottom-width: 1px; 29 | font-size: $font-size-small; 30 | text-transform: uppercase; 31 | color: $dark-gray; 32 | font-weight: $font-weight-normal; 33 | padding-bottom: 5px; 34 | } 35 | 36 | .td-actions .btn{ 37 | @include opacity(0.36); 38 | 39 | &.btn-xs{ 40 | padding-left: 3px; 41 | padding-right: 3px; 42 | } 43 | } 44 | .td-actions{ 45 | min-width: 90px; 46 | } 47 | 48 | > tbody > tr{ 49 | position: relative; 50 | 51 | &:hover{ 52 | .td-actions .btn{ 53 | @include opacity(1); 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /frontend/sass/lbd/_misc.scss: -------------------------------------------------------------------------------- 1 | /* General overwrite */ 2 | body, 3 | .wrapper{ 4 | min-height: 100vh; 5 | position: relative; 6 | } 7 | a{ 8 | color: $info-color; 9 | 10 | &:hover, &:focus{ 11 | color: $info-states-color; 12 | text-decoration: none; 13 | } 14 | } 15 | 16 | a:focus, a:active, 17 | button::-moz-focus-inner, 18 | input::-moz-focus-inner, 19 | input[type="reset"]::-moz-focus-inner, 20 | input[type="button"]::-moz-focus-inner, 21 | input[type="submit"]::-moz-focus-inner, 22 | select::-moz-focus-inner, 23 | input[type="file"] > input[type="button"]::-moz-focus-inner{ 24 | outline:0; 25 | } 26 | .ui-slider-handle:focus, 27 | .navbar-toggle, 28 | input:focus { 29 | outline : 0 !important; 30 | } 31 | 32 | /* Animations */ 33 | .form-control, 34 | .input-group-addon, 35 | .tagsinput, 36 | .navbar, 37 | .navbar .alert{ 38 | @include transition($general-transition-time, $transition-linear); 39 | } 40 | 41 | .sidebar .nav a, 42 | .table > tbody > tr .td-actions .btn{ 43 | @include transition($fast-transition-time, $transition-ease-in); 44 | } 45 | 46 | .btn{ 47 | @include transition($ultra-fast-transition-time, $transition-ease-in); 48 | } 49 | .fa{ 50 | width: 18px; 51 | text-align: center; 52 | } 53 | .margin-top{ 54 | margin-top: 50px; 55 | } 56 | 57 | .wrapper{ 58 | position: relative; 59 | top: 0; 60 | height: 100vh; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /frontend/js/angular/show-errors.min.js: -------------------------------------------------------------------------------- 1 | /*! angular-bootstrap-show-errors (version 2.3.0) 2015-01-19 */ 2 | (function(){var a;a=angular.module("ui.bootstrap.showErrors",[]),a.directive("showErrors",["$timeout","showErrorsConfig","$interpolate",function(a,b,c){var d,e,f;return e=function(a){var c;return c=b.trigger,a&&null!=a.trigger&&(c=a.trigger),c},d=function(a){var c;return c=b.showSuccess,a&&null!=a.showSuccess&&(c=a.showSuccess),c},f=function(b,f,g,h){var i,j,k,l,m,n,o,p;if(i=!1,m=b.$eval(g.showErrors),n=d(m),p=e(m),j=f[0].querySelector(".form-control[name]"),l=angular.element(j),k=c(l.attr("name")||"")(b),!k)throw"show-errors element has no child input elements with a 'name' attribute and a 'form-control' class";return l.bind(p,function(){return i=!0,o(h[k].$invalid)}),b.$watch(function(){return h[k]&&h[k].$invalid},function(a){return i?o(a):void 0}),b.$on("show-errors-check-validity",function(){return o(h[k].$invalid)}),b.$on("show-errors-reset",function(){return a(function(){return f.removeClass("has-error"),f.removeClass("has-success"),i=!1},0,!1)}),o=function(a){return f.toggleClass("has-error",a),n?f.toggleClass("has-success",!a):void 0}},{restrict:"A",require:"^form",compile:function(a,b){if(-1===b.showErrors.indexOf("skipFormGroupCheck")&&!a.hasClass("form-group")&&!a.hasClass("input-group"))throw"show-errors element does not have the 'form-group' or 'input-group' class";return f}}}]),a.provider("showErrorsConfig",function(){var a,b;a=!1,b="blur",this.showSuccess=function(b){return a=b},this.trigger=function(a){return b=a},this.$get=function(){return{showSuccess:a,trigger:b}}})}).call(this); -------------------------------------------------------------------------------- /frontend/sass/lbd/mixins/_buttons.scss: -------------------------------------------------------------------------------- 1 | // Mixin for generating new styles 2 | @mixin btn-styles($btn-color, $btn-states-color) { 3 | border-color: $btn-color; 4 | color: $btn-color; 5 | 6 | &:hover, 7 | &:focus, 8 | &:active, 9 | &.active, 10 | .open > &.dropdown-toggle { 11 | background-color: $transparent-bg; 12 | color: $btn-states-color; 13 | border-color: $btn-states-color; 14 | } 15 | 16 | &.disabled, 17 | &:disabled, 18 | &[disabled], 19 | fieldset[disabled] & { 20 | &, 21 | &:hover, 22 | &:focus, 23 | &.focus, 24 | &:active, 25 | &.active { 26 | background-color: $transparent-bg; 27 | border-color: $btn-color; 28 | } 29 | } 30 | 31 | 32 | &.btn-fill { 33 | color: $white-color; 34 | background-color: $btn-color; 35 | @include opacity(1); 36 | 37 | &:hover, 38 | &:focus, 39 | &:active, 40 | &.active, 41 | .open > &.dropdown-toggle{ 42 | background-color: $btn-states-color; 43 | color: $white-color; 44 | } 45 | 46 | .caret{ 47 | border-top-color: $white-color; 48 | } 49 | } 50 | 51 | .caret{ 52 | border-top-color: $btn-color; 53 | } 54 | } 55 | 56 | 57 | @mixin btn-size($padding-vertical, $padding-horizontal, $font-size, $border){ 58 | font-size: $font-size; 59 | border-radius: $border; 60 | padding: $padding-vertical $padding-horizontal; 61 | 62 | &.btn-round{ 63 | padding: $padding-vertical + 1 $padding-horizontal; 64 | } 65 | 66 | &.btn-simple{ 67 | padding: $padding-vertical + 2 $padding-horizontal; 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /frontend/sass/lbd/_footers.scss: -------------------------------------------------------------------------------- 1 | .footer{ 2 | background-color: $white-color; 3 | line-height: $line-height; 4 | 5 | nav > ul{ 6 | list-style: none; 7 | margin: 0; 8 | padding: 0; 9 | font-weight: normal; 10 | 11 | a:not(.btn){ 12 | color: $dark-gray; 13 | display: block; 14 | margin-bottom: 3px; 15 | &:hover, 16 | &:focus{ 17 | color: $default-states-color; 18 | } 19 | } 20 | } 21 | .social-area{ 22 | padding: 15px 0; 23 | h5{ 24 | padding-bottom: 15px; 25 | } 26 | } 27 | .social-area > a:not(.btn){ 28 | color: $dark-gray; 29 | display: inline-block; 30 | vertical-align: top; 31 | padding: $padding-social-a; 32 | font-size: $font-size-large-navbar; 33 | font-weight: normal; 34 | line-height: $line-height; 35 | text-align: center; 36 | &:hover, 37 | &:focus{ 38 | color: $default-states-color; 39 | } 40 | } 41 | .copyright{ 42 | color: $default-states-color; 43 | padding: 10px 15px; 44 | margin: 10px 3px; 45 | line-height: 20px; 46 | font-size: $font-size-base; 47 | } 48 | hr{ 49 | border-color: $medium-gray; 50 | } 51 | .title{ 52 | color: $default-states-color; 53 | } 54 | } 55 | 56 | .footer-default{ 57 | background-color: $smoke-bg; 58 | } 59 | 60 | .footer:not(.footer-big){ 61 | nav > ul{ 62 | font-size: $font-size-base; 63 | li{ 64 | margin-left: 20px; 65 | float: left; 66 | } 67 | a{ 68 | padding: 10px 0px; 69 | margin: 10px 10px 10px 0px; 70 | } 71 | } 72 | } 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /frontend/sass/lbd/_alerts.scss: -------------------------------------------------------------------------------- 1 | .alert{ 2 | border: 0; 3 | border-radius: 0; 4 | color: #FFFFFF; 5 | padding: 10px 15px; 6 | font-size: 14px; 7 | 8 | .container &{ 9 | border-radius: 4px; 10 | 11 | } 12 | .navbar &{ 13 | border-radius: 0; 14 | left: 0; 15 | position: absolute; 16 | right: 0; 17 | top: 85px; 18 | width: 100%; 19 | z-index: 3; 20 | } 21 | .navbar:not(.navbar-transparent) &{ 22 | top: 70px; 23 | } 24 | 25 | span[data-notify="icon"]{ 26 | font-size: 30px; 27 | display: block; 28 | left: 15px; 29 | position: absolute; 30 | top: 50%; 31 | margin-top: -15px; 32 | } 33 | 34 | button.close{ 35 | position: absolute; 36 | right: 10px; 37 | top: 50%; 38 | margin-top: -13px; 39 | z-index: 1033; 40 | background-color: #FFFFFF; 41 | display: block; 42 | border-radius: 50%; 43 | opacity: .4; 44 | line-height: 11px; 45 | width: 25px; 46 | height: 25px; 47 | outline: 0 !important; 48 | text-align: center; 49 | padding: 3px; 50 | font-weight: 300; 51 | 52 | &:hover{ 53 | opacity: .55; 54 | } 55 | } 56 | 57 | .close ~ span{ 58 | display: block; 59 | max-width: 89%; 60 | } 61 | 62 | &[data-notify="container"]{ 63 | padding: 10px 10px 10px 20px; 64 | border-radius: $border-radius-base; 65 | } 66 | 67 | &.alert-with-icon{ 68 | padding-left: 65px; 69 | } 70 | } 71 | .alert-info{ 72 | background-color: $azure-navbar; 73 | } 74 | .alert-success { 75 | background-color: $green-navbar; 76 | } 77 | .alert-warning { 78 | background-color: $orange-navbar; 79 | } 80 | .alert-danger { 81 | background-color: $red-navbar; 82 | } 83 | -------------------------------------------------------------------------------- /frontend/sass/lbd/_typography.scss: -------------------------------------------------------------------------------- 1 | /* Font Smoothing */ 2 | body, 3 | h1, .h1, 4 | h2, .h2, 5 | h3, .h3, 6 | h4, .h4, 7 | h5, .h5, 8 | h6, .h6, 9 | p, 10 | .navbar, 11 | .brand, 12 | .btn-simple, 13 | .alert, 14 | a, 15 | .td-name, 16 | td, 17 | button.close{ 18 | -moz-osx-font-smoothing: grayscale; 19 | -webkit-font-smoothing: antialiased; 20 | font-family: "Roboto","Helvetica Neue",Arial,sans-serif; 21 | font-weight: $font-weight-normal; 22 | } 23 | 24 | h1, .h1, h2, .h2, h3, .h3, h4, .h4{ 25 | font-weight: $font-weight-light; 26 | margin: $margin-large-vertical 0 $margin-base-vertical; 27 | } 28 | 29 | h1, .h1 { 30 | font-size: $font-size-h1; 31 | } 32 | h2, .h2{ 33 | font-size: $font-size-h2; 34 | } 35 | h3, .h3{ 36 | font-size: $font-size-h3; 37 | margin: 20px 0 10px; 38 | } 39 | h4, .h4{ 40 | font-size: $font-size-h4; 41 | line-height: 30px; 42 | } 43 | h5, .h5 { 44 | font-size: $font-size-h5; 45 | margin-bottom: 15px; 46 | } 47 | h6, .h6{ 48 | font-size: $font-size-h6; 49 | font-weight: $font-weight-bold; 50 | text-transform: uppercase; 51 | } 52 | p{ 53 | font-size: $font-paragraph; 54 | line-height: $line-height-general; 55 | } 56 | 57 | h1 small, h2 small, h3 small, h4 small, h5 small, h6 small, .h1 small, .h2 small, .h3 small, .h4 small, .h5 small, .h6 small, h1 .small, h2 .small, h3 .small, h4 .small, h5 .small, h6 .small, .h1 .small, .h2 .small, .h3 .small, .h4 .small, .h5 .small, .h6 .small { 58 | color: $dark-gray; 59 | font-weight: $font-weight-light; 60 | line-height: $line-height-general; 61 | } 62 | 63 | h1 small, h2 small, h3 small, h1 .small, h2 .small, h3 .small { 64 | font-size: 60%; 65 | } 66 | 67 | h1 .subtitle{ 68 | display: block; 69 | margin: 0 0 $margin-large-vertical; 70 | } 71 | 72 | .text-muted{ 73 | color: #9A9A9A; 74 | } 75 | .text-primary, .text-primary:hover{ 76 | color: #1D62F0 !important; 77 | } 78 | .text-info, .text-info:hover{ 79 | color: $info-color !important; 80 | } 81 | .text-success, .text-success:hover{ 82 | color: $success-color !important; 83 | } 84 | .text-warning, .text-warning:hover{ 85 | color: $warning-color !important; 86 | } 87 | .text-danger, .text-danger:hover{ 88 | color: $danger-color !important; 89 | } 90 | 91 | -------------------------------------------------------------------------------- /frontend/css/style.css: -------------------------------------------------------------------------------- 1 | body { padding-top: 0px;} 2 | 3 | .starter-template { padding: 40px 15px; } 4 | 5 | .top5 { margin-top:5px; } 6 | .top7 { margin-top:7px; } 7 | .top10 { margin-top:10px; } 8 | .top15 { margin-top:15px; } 9 | .top17 { margin-top:17px; } 10 | .top30 { margin-top:30px; } 11 | 12 | .bottom5 { margin-bottom:5px; } 13 | .bottom7 { margin-bottom:7px; } 14 | .bottom10 { margin-bottom:10px; } 15 | .bottom15 { margin-bottom:15px; } 16 | .bottom17 { margin-bottom:17px; } 17 | .bottom30 { margin-bottom:30px; } 18 | 19 | .left {float: left;} 20 | .right {float: right;} 21 | 22 | .alerts { 23 | top: 51px; 24 | left: 0px; 25 | position: fixed; 26 | width: 100%; 27 | z-index: 1; 28 | } 29 | 30 | [ng\:cloak], [ng-cloak], .ng-cloak { 31 | display: none !important; 32 | } 33 | 34 | .all-icons [class*="pe-"]{ 35 | font-size: 40px; 36 | } 37 | .all-icons input{ 38 | border: 0; 39 | } 40 | .all-icons .font-icon-detail{ 41 | text-align: center; 42 | padding: 45px 0px 30px; 43 | border: 1px solid #e5e5e5; 44 | border-radius: 6px; 45 | margin: 15px 0; 46 | } 47 | .all-icons .font-icon-detail input{ 48 | margin: 25px auto 0; 49 | width: 100%; 50 | text-align: center; 51 | display: block; 52 | color: #aaa; 53 | font-size: 13px; 54 | } 55 | 56 | @media (min-width: 992px){ 57 | .typo-line{ 58 | padding-left: 140px; 59 | margin-bottom: 40px; 60 | position: relative; 61 | } 62 | 63 | .typo-line .category{ 64 | transform: translateY(-50%); 65 | top: 50%; 66 | left: 0px; 67 | position: absolute; 68 | } 69 | } 70 | 71 | .places-buttons .btn{ 72 | margin-bottom: 30px 73 | } 74 | .sidebar .nav > li.active-pro{ 75 | position: absolute; 76 | width: 100%; 77 | bottom: 10px; 78 | } 79 | .sidebar .nav > li.active-pro a{ 80 | background: rgba(255, 255, 255, 0.14); 81 | opacity: 1; 82 | color: #FFFFFF; 83 | } 84 | 85 | .table-upgrade td:nth-child(2), 86 | .table-upgrade td:nth-child(3){ 87 | text-align: center; 88 | } 89 | 90 | .checkbox, .checkbox label { 91 | padding-left: 0px; !important 92 | } 93 | 94 | .checkbox { 95 | margin-top: 0px; !important 96 | } 97 | 98 | .checkbox input { 99 | display: block; !important 100 | } -------------------------------------------------------------------------------- /frontend/sass/lbd/_buttons.scss: -------------------------------------------------------------------------------- 1 | .btn{ 2 | border-width: $border-thick; 3 | background-color: $transparent-bg; 4 | font-weight: $font-weight-normal; 5 | 6 | @include opacity(.8); 7 | padding: $padding-base-vertical $padding-base-horizontal; 8 | 9 | @include btn-styles($default-color, $default-states-color); 10 | 11 | &:hover, 12 | &:focus{ 13 | @include opacity(1); 14 | outline: 0 !important; 15 | } 16 | &:active, 17 | &.active, 18 | .open > &.dropdown-toggle { 19 | @include box-shadow(none); 20 | outline: 0 !important; 21 | } 22 | 23 | &.btn-icon{ 24 | padding: $padding-base-vertical; 25 | } 26 | 27 | } 28 | 29 | // Apply the mixin to the buttons 30 | //.btn-default { @include btn-styles($default-color, $default-states-color); } 31 | .btn-primary { @include btn-styles($primary-color, $primary-states-color); } 32 | .btn-success { @include btn-styles($success-color, $success-states-color); } 33 | .btn-info { @include btn-styles($info-color, $info-states-color); } 34 | .btn-warning { @include btn-styles($warning-color, $warning-states-color); } 35 | .btn-danger { @include btn-styles($danger-color, $danger-states-color); } 36 | .btn-neutral { 37 | @include btn-styles($white-color, $white-color); 38 | 39 | &:active, 40 | &.active, 41 | .open > &.dropdown-toggle{ 42 | background-color: $white-color; 43 | color: $default-color; 44 | } 45 | 46 | &.btn-fill, 47 | &.btn-fill:hover, 48 | &.btn-fill:focus{ 49 | color: $default-color; 50 | } 51 | 52 | &.btn-simple:active, 53 | &.btn-simple.active{ 54 | background-color: transparent; 55 | } 56 | } 57 | 58 | .btn{ 59 | &:disabled, 60 | &[disabled], 61 | &.disabled{ 62 | @include opacity(.5); 63 | } 64 | } 65 | .btn-round{ 66 | border-width: $border-thin; 67 | border-radius: $btn-round-radius !important; 68 | padding: $padding-round-vertical $padding-round-horizontal; 69 | 70 | &.btn-icon{ 71 | padding: $padding-round-vertical; 72 | } 73 | } 74 | .btn-simple{ 75 | border: $none; 76 | font-size: $font-size-medium; 77 | padding: $padding-base-vertical $padding-base-horizontal; 78 | 79 | &.btn-icon{ 80 | padding: $padding-base-vertical; 81 | } 82 | } 83 | .btn-lg{ 84 | @include btn-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $border-radius-large); 85 | font-weight: $font-weight-normal; 86 | } 87 | .btn-sm{ 88 | @include btn-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $border-radius-small); 89 | } 90 | .btn-xs { 91 | @include btn-size($padding-xs-vertical, $padding-xs-horizontal, $font-size-small, $border-radius-small); 92 | } 93 | .btn-wd { 94 | min-width: 140px; 95 | } 96 | 97 | .btn-group.select{ 98 | width: 100%; 99 | } 100 | .btn-group.select .btn{ 101 | text-align: left; 102 | } 103 | .btn-group.select .caret{ 104 | position: absolute; 105 | top: 50%; 106 | margin-top: -1px; 107 | right: 8px; 108 | } 109 | -------------------------------------------------------------------------------- /frontend/sass/lbd/_dropdown.scss: -------------------------------------------------------------------------------- 1 | .dropdown-menu{ 2 | visibility: hidden; 3 | margin: 0; 4 | padding: 0; 5 | border-radius: $border-radius-extreme; 6 | display: block; 7 | z-index: 9000; 8 | position: absolute; 9 | 10 | @include opacity(0); 11 | @include box-shadow($dropdown-shadow); 12 | 13 | .open &{ 14 | @include opacity(1); 15 | visibility: visible; 16 | } 17 | .select &{ 18 | border-radius: $border-radius-bottom; 19 | @include box-shadow(none); 20 | @include transform-origin($select-coordinates); 21 | @include transform-scale(1); 22 | @include transition($fast-transition-time, $transition-linear); 23 | margin-top: -20px; 24 | } 25 | .select.open &{ 26 | margin-top: -1px; 27 | } 28 | 29 | > li > a { 30 | padding: $padding-base-vertical $padding-base-horizontal; 31 | color: #333333; 32 | 33 | img{ 34 | margin-top: -3px; 35 | } 36 | } 37 | > li > a:focus{ 38 | outline: 0 !important; 39 | } 40 | 41 | .btn-group.select &{ 42 | min-width: 100%; 43 | } 44 | 45 | > li:first-child > a{ 46 | border-top-left-radius: $border-radius-extreme; 47 | border-top-right-radius: $border-radius-extreme; 48 | } 49 | 50 | > li:last-child > a{ 51 | border-bottom-left-radius: $border-radius-extreme; 52 | border-bottom-right-radius: $border-radius-extreme; 53 | } 54 | 55 | .select & > li:first-child > a{ 56 | border-radius: 0; 57 | border-bottom: 0 none; 58 | } 59 | 60 | > li > a:hover, 61 | > li > a:focus { 62 | background-color: $smoke-bg; 63 | color: #333333; 64 | opacity: 1; 65 | text-decoration: none; 66 | } 67 | 68 | &.dropdown-blue > li > a:hover, 69 | &.dropdown-blue > li > a:focus{ 70 | background-color: $light-blue; 71 | } 72 | &.dropdown-azure > li > a:hover, 73 | &.dropdown-azure > li > a:focus{ 74 | background-color: $light-azure; 75 | } 76 | &.ct-green > li > a:hover, 77 | &.ct-green > li > a:focus{ 78 | background-color: $light-green; 79 | } 80 | &.dropdown-orange > li > a:hover, 81 | &.dropdown-orange > li > a:focus{ 82 | background-color: $light-orange; 83 | } 84 | &.dropdown-red > li > a:hover, 85 | &.dropdown-red > li > a:focus{ 86 | background-color: $light-red; 87 | } 88 | 89 | } 90 | 91 | .dropdown-with-icons{ 92 | > li > a{ 93 | padding-left: 0px; 94 | line-height: 28px; 95 | } 96 | i{ 97 | text-align: center; 98 | line-height: 28px; 99 | float: left; 100 | 101 | &[class^="pe-"]{ 102 | font-size: 24px; 103 | width: 46px; 104 | } 105 | &[class^="fa"]{ 106 | font-size: 14px; 107 | width: 38px; 108 | } 109 | } 110 | } 111 | 112 | //fix bug for the select items in btn-group 113 | .btn-group.select{ 114 | overflow: hidden; 115 | } 116 | .btn-group.select.open{ 117 | overflow: visible; 118 | } 119 | 120 | 121 | -------------------------------------------------------------------------------- /frontend/sass/lbd/mixins/_chartist.scss: -------------------------------------------------------------------------------- 1 | // Scales for responsive SVG containers 2 | $ct-scales: ((1), (15/16), (8/9), (5/6), (4/5), (3/4), (2/3), (5/8), (1/1.618), (3/5), (9/16), (8/15), (1/2), (2/5), (3/8), (1/3), (1/4)) !default; 3 | $ct-scales-names: (ct-square, ct-minor-second, ct-major-second, ct-minor-third, ct-major-third, ct-perfect-fourth, ct-perfect-fifth, ct-minor-sixth, ct-golden-section, ct-major-sixth, ct-minor-seventh, ct-major-seventh, ct-octave, ct-major-tenth, ct-major-eleventh, ct-major-twelfth, ct-double-octave) !default; 4 | 5 | // Class names to be used when generating CSS 6 | $ct-class-chart: ct-chart !default; 7 | $ct-class-chart-line: ct-chart-line !default; 8 | $ct-class-chart-bar: ct-chart-bar !default; 9 | $ct-class-horizontal-bars: ct-horizontal-bars !default; 10 | $ct-class-chart-pie: ct-chart-pie !default; 11 | $ct-class-chart-donut: ct-chart-donut !default; 12 | $ct-class-label: ct-label !default; 13 | $ct-class-series: ct-series !default; 14 | $ct-class-line: ct-line !default; 15 | $ct-class-point: ct-point !default; 16 | $ct-class-area: ct-area !default; 17 | $ct-class-bar: ct-bar !default; 18 | $ct-class-slice-pie: ct-slice-pie !default; 19 | $ct-class-slice-donut: ct-slice-donut !default; 20 | $ct-class-grid: ct-grid !default; 21 | $ct-class-vertical: ct-vertical !default; 22 | $ct-class-horizontal: ct-horizontal !default; 23 | $ct-class-start: ct-start !default; 24 | $ct-class-end: ct-end !default; 25 | 26 | // Container ratio 27 | $ct-container-ratio: (1/1.618) !default; 28 | 29 | // Text styles for labels 30 | $ct-text-color: rgba(0, 0, 0, 0.4) !default; 31 | $ct-text-size: 1.3rem !default; 32 | $ct-text-align: flex-start !default; 33 | $ct-text-justify: flex-start !default; 34 | $ct-text-line-height: 1; 35 | 36 | // Grid styles 37 | $ct-grid-color: rgba(0, 0, 0, 0.2) !default; 38 | $ct-grid-dasharray: 2px !default; 39 | $ct-grid-width: 1px !default; 40 | 41 | // Line chart properties 42 | $ct-line-width: 3px !default; 43 | $ct-line-dasharray: false !default; 44 | $ct-point-size: 8px !default; 45 | // Line chart point, can be either round or square 46 | $ct-point-shape: round !default; 47 | // Area fill transparency between 0 and 1 48 | $ct-area-opacity: 0.8 !default; 49 | 50 | // Bar chart bar width 51 | $ct-bar-width: 10px !default; 52 | 53 | // Donut width (If donut width is to big it can cause issues where the shape gets distorted) 54 | $ct-donut-width: 60px !default; 55 | 56 | // If set to true it will include the default classes and generate CSS output. If you're planning to use the mixins you 57 | // should set this property to false 58 | $ct-include-classes: true !default; 59 | 60 | // If this is set to true the CSS will contain colored series. You can extend or change the color with the 61 | // properties below 62 | $ct-include-colored-series: $ct-include-classes !default; 63 | 64 | // If set to true this will include all responsive container variations using the scales defined at the top of the script 65 | $ct-include-alternative-responsive-containers: $ct-include-classes !default; 66 | 67 | // Series names and colors. This can be extended or customized as desired. Just add more series and colors. 68 | $ct-series-names: (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) !default; 69 | $ct-series-colors: ( 70 | $new-blue, 71 | $new-red, 72 | $new-orange, 73 | $new-purple, 74 | $new-green, 75 | $new-dark-blue, 76 | $new-black, 77 | $social-google, 78 | $social-tumblr, 79 | $social-youtube, 80 | $social-twitter, 81 | $social-pinterest, 82 | $social-behance, 83 | #6188e2, 84 | #a748ca 85 | ) !default; -------------------------------------------------------------------------------- /frontend/js/angular/angular-resource.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.3.15 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(I,d,B){'use strict';function D(f,q){q=q||{};d.forEach(q,function(d,h){delete q[h]});for(var h in f)!f.hasOwnProperty(h)||"$"===h.charAt(0)&&"$"===h.charAt(1)||(q[h]=f[h]);return q}var w=d.$$minErr("$resource"),C=/^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;d.module("ngResource",["ng"]).provider("$resource",function(){var f=this;this.defaults={stripTrailingSlashes:!0,actions:{get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}}}; 7 | this.$get=["$http","$q",function(q,h){function t(d,g){this.template=d;this.defaults=s({},f.defaults,g);this.urlParams={}}function v(x,g,l,m){function c(b,k){var c={};k=s({},g,k);r(k,function(a,k){u(a)&&(a=a());var d;if(a&&a.charAt&&"@"==a.charAt(0)){d=b;var e=a.substr(1);if(null==e||""===e||"hasOwnProperty"===e||!C.test("."+e))throw w("badmember",e);for(var e=e.split("."),n=0,g=e.length;n' + 16 | '
' + 17 | '' + 18 | '' + 19 | '' + 20 | '
' + 21 | '', 22 | compile: function(element, attrs) { 23 | if (angular.isUndefined(attrs.onLabel)) { 24 | attrs.onLabel = 'Yes'; 25 | } 26 | if (angular.isUndefined(attrs.offLabel)) { 27 | attrs.offLabel = 'No'; 28 | } 29 | if (angular.isUndefined(attrs.knobLabel)) { 30 | attrs.knobLabel = '\u00a0'; 31 | } 32 | if (angular.isUndefined(attrs.isDisabled)) { 33 | attrs.isDisabled = false; 34 | } 35 | if (angular.isUndefined(attrs.html)) { 36 | attrs.html = false; 37 | } 38 | if (angular.isUndefined(attrs.tabindex)) { 39 | attrs.tabindex = 0; 40 | } 41 | 42 | return function postLink(scope, iElement, iAttrs, ngModel) { 43 | iElement.attr('tabindex', attrs.tabindex); 44 | 45 | scope.toggle = function toggle() { 46 | if (!scope.isDisabled) { 47 | scope.model = !scope.model; 48 | ngModel.$setViewValue(scope.model); 49 | scope.onChange(); 50 | } 51 | }; 52 | 53 | var spaceCharCode = 32; 54 | scope.onKeyPress = function onKeyPress($event) { 55 | if ($event.charCode == spaceCharCode && !$event.altKey && !$event.ctrlKey && !$event.metaKey) { 56 | scope.toggle(); 57 | $event.preventDefault(); 58 | } 59 | }; 60 | 61 | ngModel.$formatters.push(function(modelValue) { 62 | return modelValue; 63 | }); 64 | 65 | ngModel.$parsers.push(function(viewValue) { 66 | return viewValue; 67 | }); 68 | 69 | ngModel.$viewChangeListeners.push(function() { 70 | scope.$eval(attrs.ngChange); 71 | }); 72 | 73 | ngModel.$render = function() { 74 | scope.model = ngModel.$viewValue; 75 | }; 76 | 77 | var bindSpan = function(span, html) { 78 | span = angular.element(span); 79 | var bindAttributeName = (html === true) ? 'ng-bind-html' : 'ng-bind'; 80 | 81 | // remove old ng-bind attributes 82 | span.removeAttr('ng-bind-html'); 83 | span.removeAttr('ng-bind'); 84 | 85 | if (angular.element(span).hasClass("switch-left")) 86 | span.attr(bindAttributeName, 'onLabel'); 87 | if (span.hasClass("knob")) 88 | span.attr(bindAttributeName, 'knobLabel'); 89 | if (span.hasClass("switch-right")) 90 | span.attr(bindAttributeName, 'offLabel'); 91 | 92 | $compile(span)(scope, function(cloned, scope) { 93 | span.replaceWith(cloned); 94 | }); 95 | }; 96 | 97 | // add ng-bind attribute to each span element. 98 | // NOTE: you need angular-sanitize to use ng-bind-html 99 | var bindSwitch = function(iElement, html) { 100 | angular.forEach(iElement[0].children[0].children, function(span, index) { 101 | bindSpan(span, html); 102 | }); 103 | }; 104 | 105 | scope.$watch('html', function(newValue) { 106 | bindSwitch(iElement, newValue); 107 | }); 108 | }; 109 | } 110 | }; 111 | }]); 112 | -------------------------------------------------------------------------------- /frontend/sass/lbd/_inputs.scss: -------------------------------------------------------------------------------- 1 | .form-control::-moz-placeholder{ 2 | @include placeholder($medium-gray,1); 3 | } 4 | .form-control:-moz-placeholder{ 5 | @include placeholder($medium-gray,1); 6 | } 7 | .form-control::-webkit-input-placeholder{ 8 | @include placeholder($medium-gray,1); 9 | } 10 | .form-control:-ms-input-placeholder{ 11 | @include placeholder($medium-gray,1); 12 | } 13 | 14 | .form-control { 15 | background-color: $white-bg; 16 | border: 1px solid $light-gray; 17 | border-radius: $border-radius-base; 18 | color: #565656; 19 | @include input-size($padding-base-vertical, $padding-base-horizontal - 4, $height-base); 20 | @include box-shadow(none); 21 | 22 | &:focus{ 23 | background-color: $white-bg; 24 | border: 1px solid $medium-dark-gray; 25 | @include box-shadow(none); 26 | outline: 0 !important; 27 | color: #333333; 28 | } 29 | 30 | .has-success &, 31 | .has-error &, 32 | .has-success &:focus, 33 | .has-error &:focus{ 34 | border-color: $light-gray; 35 | @include box-shadow(none); 36 | } 37 | 38 | .has-success &{ 39 | color: $success-color; 40 | } 41 | .has-success &:focus{ 42 | border-color: $success-color; 43 | } 44 | .has-error &{ 45 | color: $danger-color; 46 | } 47 | .has-error &:focus{ 48 | border-color: $danger-color; 49 | } 50 | 51 | & + .form-control-feedback{ 52 | border-radius: $border-radius-large; 53 | font-size: $font-size-base; 54 | margin-top: -7px; 55 | position: absolute; 56 | right: 10px; 57 | top: 50%; 58 | vertical-align: middle; 59 | } 60 | 61 | .open &{ 62 | border-radius: $border-radius-base $border-radius-base 0 0; 63 | border-bottom-color: transparent; 64 | } 65 | } 66 | 67 | .input-lg{ 68 | height: 55px; 69 | padding: $padding-large-vertical $padding-large-horizontal; 70 | } 71 | 72 | .has-error{ 73 | .form-control-feedback{ 74 | color: $danger-color; 75 | } 76 | } 77 | .has-success{ 78 | .form-control-feedback{ 79 | color: $success-color 80 | } 81 | } 82 | 83 | 84 | .input-group-addon { 85 | background-color: $white-color; 86 | border: 1px solid $light-gray; 87 | border-radius: $border-radius-base; 88 | 89 | .has-success &, 90 | .has-error &{ 91 | background-color: $white-color; 92 | border: 1px solid $light-gray; 93 | } 94 | .has-error .form-control:focus + &{ 95 | border-color: $danger-color; 96 | color: $danger-color; 97 | } 98 | .has-success .form-control:focus + &{ 99 | border-color: $success-color; 100 | color: $success-color; 101 | } 102 | .form-control:focus + &, 103 | .form-control:focus ~ &{ 104 | background-color: $white-color; 105 | border-color: $dark-gray; 106 | } 107 | } 108 | 109 | .input-group .form-control:first-child, 110 | .input-group-addon:first-child, 111 | .input-group-btn:first-child > .dropdown-toggle, 112 | .input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) { 113 | border-right: 0 none; 114 | } 115 | .input-group .form-control:last-child, 116 | .input-group-addon:last-child, 117 | .input-group-btn:last-child > .dropdown-toggle, 118 | .input-group-btn:first-child > .btn:not(:first-child) { 119 | border-left: 0 none; 120 | } 121 | .form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control { 122 | background-color: $smoke-bg; 123 | color: $default-color; 124 | cursor: not-allowed; 125 | } 126 | 127 | .input-group-btn .btn{ 128 | border-width: $border-thin; 129 | padding: $padding-round-vertical $padding-base-horizontal; 130 | } 131 | .input-group-btn .btn-default:not(.btn-fill){ 132 | border-color: $medium-gray; 133 | } 134 | 135 | .input-group-btn:last-child > .btn{ 136 | margin-left: 0; 137 | } 138 | 139 | .input-group-focus .input-group-addon{ 140 | border-color: $dark-gray; 141 | } 142 | -------------------------------------------------------------------------------- /frontend/sass/lbd/_cards.scss: -------------------------------------------------------------------------------- 1 | .card{ 2 | border-radius: $border-radius-base; 3 | box-shadow: 0 1px 2px rgba(0,0,0,.05),0 0 0 1px rgba(63,63,68,.1); 4 | background-color: #FFFFFF; 5 | margin-bottom: 30px; 6 | 7 | .image{ 8 | width: 100%; 9 | overflow: hidden; 10 | height: 260px; 11 | border-radius: $border-radius-base $border-radius-base 0 0; 12 | position: relative; 13 | -webkit-transform-style: preserve-3d; 14 | -moz-transform-style: preserve-3d; 15 | transform-style: preserve-3d; 16 | 17 | img { 18 | width: 100%; 19 | } 20 | } 21 | .filter{ 22 | position: absolute; 23 | z-index: 2; 24 | background-color: rgba(0,0,0,.68); 25 | top: 0; 26 | left: 0; 27 | width: 100%; 28 | height: 100%; 29 | text-align: center; 30 | 31 | @include opacity(0); 32 | 33 | .btn{ 34 | @include vertical-align(); 35 | } 36 | } 37 | &:hover .filter{ 38 | @include opacity(1); 39 | } 40 | .btn-hover{ 41 | @include opacity(0); 42 | } 43 | &:hover .btn-hover{ 44 | @include opacity(1); 45 | } 46 | .content{ 47 | padding: 15px 15px 10px 15px; 48 | } 49 | .header{ 50 | padding: 15px 15px 0; 51 | } 52 | .category, 53 | label{ 54 | font-size: $font-size-base; 55 | font-weight: $font-weight-normal; 56 | color: $dark-gray; 57 | margin-bottom: 0px; 58 | 59 | i{ 60 | font-size: $font-paragraph; 61 | } 62 | } 63 | 64 | label{ 65 | font-size: $font-size-small; 66 | margin-bottom: 5px; 67 | text-transform: uppercase; 68 | } 69 | 70 | .title{ 71 | margin: $none; 72 | color: $black-color; 73 | font-weight: $font-weight-light; 74 | } 75 | .avatar{ 76 | width: 30px; 77 | height: 30px; 78 | overflow: hidden; 79 | border-radius: 50%; 80 | margin-right: 5px; 81 | } 82 | .description{ 83 | font-size: $font-size-base; 84 | color: #333; 85 | } 86 | .footer{ 87 | padding: 0; 88 | background-color: $transparent-bg; 89 | line-height: 30px; 90 | 91 | .legend{ 92 | padding: 5px 0; 93 | } 94 | 95 | hr{ 96 | margin-top: 5px; 97 | margin-bottom: 5px; 98 | } 99 | } 100 | .stats{ 101 | color: #a9a9a9; 102 | } 103 | .footer div{ 104 | display: inline-block; 105 | } 106 | 107 | .author{ 108 | font-size: $font-size-small; 109 | font-weight: $font-weight-bold; 110 | text-transform: uppercase; 111 | } 112 | .author i{ 113 | font-size: $font-size-base; 114 | } 115 | h6{ 116 | font-size: $font-size-small; 117 | margin: 0; 118 | } 119 | &.card-separator:after{ 120 | height: 100%; 121 | right: -15px; 122 | top: 0; 123 | width: 1px; 124 | background-color: $medium-gray; 125 | content: ""; 126 | position: absolute; 127 | } 128 | 129 | .ct-chart{ 130 | margin: 30px 0 30px; 131 | height: 245px; 132 | } 133 | 134 | .table{ 135 | tbody td:first-child, 136 | thead th:first-child{ 137 | padding-left: 15px; 138 | } 139 | 140 | tbody td:last-child, 141 | thead th:last-child{ 142 | padding-right: 15px; 143 | } 144 | } 145 | 146 | .alert{ 147 | border-radius: $border-radius-base; 148 | position: relative; 149 | 150 | &.alert-with-icon{ 151 | padding-left: 65px; 152 | } 153 | } 154 | } 155 | .card-user{ 156 | .image{ 157 | height: 110px; 158 | } 159 | .image-plain{ 160 | height: 0; 161 | margin-top: 110px; 162 | } 163 | .author{ 164 | text-align: center; 165 | text-transform: none; 166 | margin-top: -70px; 167 | } 168 | .avatar{ 169 | width: 124px; 170 | height: 124px; 171 | border: 5px solid #FFFFFF; 172 | position: relative; 173 | margin-bottom: 15px; 174 | 175 | &.border-gray{ 176 | border-color: #EEEEEE; 177 | } 178 | } 179 | .title{ 180 | line-height: 24px; 181 | } 182 | .content{ 183 | min-height: 240px; 184 | } 185 | } 186 | 187 | .card-user, 188 | .card-price{ 189 | .footer{ 190 | padding: 5px 15px 10px; 191 | } 192 | hr{ 193 | margin: 5px 15px; 194 | } 195 | } 196 | .card-plain{ 197 | background-color: transparent; 198 | box-shadow: none; 199 | border-radius: 0; 200 | 201 | .image{ 202 | border-radius: 4px; 203 | } 204 | } 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ACServerManager 2 | Web based server manager for Assetto Corsa directly manipulating the ini files on the server as an alternative to the windows app and having to copy files to your server. 3 | 4 | Start and stop the server, and stracker directly from the application, meaning you can make changes to the server configuration and restart the server directly from your browser or mobile phone. 5 | 6 | ## ACServerManager on Windows 7 | This is the installation guide for a Windows machine, to review the Linux installation guide go [here](https://github.com/jo3stevens/ACServerManager/blob/master/README_Linux.md). 8 | 9 | ## Updates 10 | 27/01/2017: 11 | * Update to UI layout 12 | * Added restart feature for AC & sTracker server 13 | 14 | 17/10/2015: 15 | * Bug fix when switching between two tracks with multiple track configs 16 | * Added Max Ballast and UDP Plugin fields to Advanced page 17 | * Added new setting for contentPath allowing server and content folders to be seperated (this happens when using a manager package from the kunos tool). If this setting it left empty it will assume the content folder is inside the server folder 18 | 19 | 22/08/2015: 20 | * Finished adding all the new settings from 1.2 including tyres and weather 21 | 22 | ## Prep 23 | NOTE: If you've been using the new windows server manager that came with 1.2 then you may not need this step as when you package the server files it does the same thing. 24 | 25 | The application needs some additional files added to the server/content/tracks and server/content/cars folders to be able to choose track configurations and car skins. 26 | 27 | Copy acServerManager.bat to your root aessettocorsa folder and run it to copy the required folders into server/content/*. You'll then need to copy the content folder to your server. 28 | 29 | For tracks it will copy the ui folder which will contain sub folders when there are multiple track configurations. It will also copy the contents of these directories which contains additional track information which is displayed when choosing a track. 30 | 31 | For cars it will copy the skins/* folder structure but not the files; this is just to be able to choose the skin when setting up the entry list. 32 | 33 | ## Install Node.js 34 | To install Node.js, follow the installation guide on its home page [here](https://nodejs.org). 35 | 36 | ## Install ACServerManager 37 | Create a directory called 'acmanager', go into that directory and click [here](https://github.com/jo3stevens/ACServerManager/archive/master.zip) to download the latest version. Extract 38 | the contents of the zip file into the directory. 39 | 40 | ## ACServerManager Configuration 41 | To configure your manager's settings, open the 'settings.js' file. You'll see a number of variables, point the 'serverPath' 42 | to your Assetto Corsa Server directory. You can configure your username, password & port settings for ACServerManager, also 43 | if you use sTracker, point the 'sTrackerPath' variable to your installation. 44 | 45 | * serverPath: The path to your server folder containing acServer.exe 46 | * sTrackerPath: The path to your stracker folder container stracker.exe (If you don't run stracker just leave this as an empty string ('') to disable it 47 | * username/password: Set these values if you want basic authentication on the application 48 | * port: The port that the application will listen on (Be sure to open up this port on firewalls) 49 | 50 | Note: I've currently set the Assetto Corsa Server installation to one directory up in 'server', change if necessary. 51 | 52 | ## Firewall 53 | If your machine has a firewall enabled (i.e) windows firewall, you'll need to open / allow the ACServerManager port defined in your settings.js file. 54 | 55 | ## Running ACServerManager 56 | You first need to make sure you have the necessary Node.js dependencies, run the following command in the command prompt in the same directory as the 'server.js' file: 57 | ``` 58 | npm install 59 | ``` 60 | To run ACServerManager, execute the 'start.bat' file. If you see no errors, ACServerManager should now be running. 61 | 62 | ## Using ACServerManager 63 | * Browse to the application using your servers IP and the chosen port (or any DNS configured) 64 | * Click the 'Start' button under Assetto Corsa Server section 65 | * If using sTracker wait until the AC server has started and then click 'Start' in the sTracker Server section 66 | 67 | The server should now be running. You'll be able to see any server output in the command window and it will be logged to a file in the 'ACServerManager/log' folder. 68 | 69 | You can change any of settings and it will be applied directly to server_cfg.ini and entry_list.ini on the server. After making a change just stop and start the server from the Server Status page to apply the changes to Assetto Corsa Server. 70 | 71 | Note, the server may fail to start in some cases if the Assetto Corsa Server cannot connect to the master server. Make sure you portforward / open 72 | the necessary ports for the server to function correctly. 73 | 74 | ## Screenshots 75 | ### Server Status 76 | ![Server Status](http://deltahosting.dyndns.org:8080/acmanager/screen-cap-1.JPG) 77 | 78 | ### Server Configuration 79 | ![Server Config](http://deltahosting.dyndns.org:8080/acmanager/screen-cap-2.JPG) 80 | 81 | ### Entry List 82 | ![Entry List](http://deltahosting.dyndns.org:8080/acmanager/screen-cap-3.JPG) 83 | 84 | ### Rules 85 | ![Rules](http://deltahosting.dyndns.org:8080/acmanager/screen-cap-4.JPG) 86 | 87 | ### Advanced 88 | ![Advanced](http://deltahosting.dyndns.org:8080/acmanager/screen-cap-5.JPG) 89 | -------------------------------------------------------------------------------- /frontend/css/angular-toggle-switch-bootstrap-3.css: -------------------------------------------------------------------------------- 1 | .ats-switch { 2 | border: 1px solid; 3 | cursor: pointer; 4 | display: inline-block; 5 | text-align: left; 6 | overflow: hidden; 7 | line-height: 8px; 8 | min-width: 100px; 9 | } 10 | .ats-switch.disabled { 11 | opacity: 0.5; 12 | filter: alpha(opacity=50); 13 | cursor: default !important; 14 | } 15 | .ats-switch.disabled .switch-left, 16 | .ats-switch.disabled .switch-right, 17 | .ats-switch.disabled .knob { 18 | cursor: default !important; 19 | } 20 | .ats-switch span { 21 | cursor: pointer; 22 | display: inline-block; 23 | float: left; 24 | height: 100%; 25 | line-height: 20px; 26 | padding: 4px; 27 | text-align: center; 28 | width: 33%; 29 | white-space: nowrap; 30 | box-sizing: border-box; 31 | -o-box-sizing: border-box; 32 | -moz-box-sizing: border-box; 33 | -webkit-box-sizing: border-box; 34 | } 35 | .ats-switch > div { 36 | position: relative; 37 | width: 150%; 38 | } 39 | .ats-switch .knob { 40 | background: red; 41 | border-left: 1px solid #ccc; 42 | border-right: 1px solid #ccc; 43 | background-color: #f5f5f5; 44 | width: 34%; 45 | z-index: 100; 46 | } 47 | .ats-switch .switch-on { 48 | left: 0%; 49 | } 50 | .ats-switch .switch-off { 51 | left: -50%; 52 | } 53 | .ats-switch .swtich-left, 54 | .ats-switch .switch-right { 55 | z-index: 1; 56 | } 57 | .ats-switch .switch-left { 58 | color: #fff; 59 | background: #005fcc; 60 | } 61 | .ats-switch .switch-right { 62 | color: #333; 63 | background: #f0f0f0; 64 | } 65 | .ats-switch .switch-animate { 66 | transition: left 0.5s; 67 | -o-transition: left 0.5s; 68 | -moz-transition: left 0.5s; 69 | -webkit-transition: left 0.5s; 70 | } 71 | .ats-switch { 72 | display: inline-block; 73 | cursor: pointer; 74 | border-radius: 4px; 75 | border: 1px solid; 76 | border-color: #ccc; 77 | position: relative; 78 | text-align: left; 79 | overflow: hidden; 80 | line-height: 8px; 81 | -webkit-user-select: none; 82 | -moz-user-select: none; 83 | -ms-user-select: none; 84 | -o-user-select: none; 85 | user-select: none; 86 | vertical-align: middle; 87 | min-width: 100px; 88 | -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; 89 | transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; 90 | } 91 | .ats-switch:hover { 92 | border-color: #66afe9; 93 | outline: 0; 94 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); 95 | box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); 96 | } 97 | .ats-switch.disabled:hover { 98 | border-color: #ccc; 99 | -webkit-box-shadow: inset 0 0 0 rgba(0,0,0,0), 0 0 0 rgba(0,0,0,0); 100 | box-shadow: inset 0 0 0 rgba(0,0,0,0), 0 0 0 rgba(0,0,0,0); 101 | } 102 | .ats-switch .knob { 103 | border-right: none; 104 | border-left: none; 105 | text-align: center; 106 | margin-top: -1px; 107 | margin-bottom: -1px; 108 | z-index: 100; 109 | background: #fff; 110 | } 111 | .ats-switch .knob i { 112 | color: #000; 113 | text-shadow: 0 1px 0 #fff; 114 | line-height: 18px; 115 | pointer-events: none; 116 | } 117 | .ats-switch .switch-left, 118 | .ats-switch .switch-right, 119 | .ats-switch .knob { 120 | min-height: 28px; 121 | } 122 | .ats-switch.switch-mini { 123 | min-width: 72px; 124 | } 125 | .ats-switch.switch-mini .switch-left, 126 | .ats-switch.switch-mini .switch-right, 127 | .ats-switch.switch-mini .knob { 128 | padding-bottom: 4px; 129 | padding-top: 4px; 130 | font-size: 10px; 131 | line-height: 9px; 132 | min-height: 18px; 133 | } 134 | .ats-switch.switch-mini i.switch-mini-icons { 135 | height: 1.20em; 136 | line-height: 9px; 137 | vertical-align: text-top; 138 | text-align: center; 139 | transform: scale(0.6); 140 | margin-top: -1px; 141 | margin-bottom: -1px; 142 | } 143 | .ats-switch.switch-small { 144 | min-width: 80px; 145 | } 146 | .ats-switch.switch-small .switch-left, 147 | .ats-switch.switch-small .switch-right, 148 | .ats-switch.switch-small .knob { 149 | padding-bottom: 3px; 150 | padding-top: 3px; 151 | font-size: 12px; 152 | line-height: 18px; 153 | min-height: 24px; 154 | } 155 | .ats-switch.switch-large { 156 | min-width: 120px; 157 | } 158 | .ats-switch.switch-large .switch-left, 159 | .ats-switch.switch-large .switch-right, 160 | .ats-switch.switch-large .knob { 161 | padding-bottom: 9px; 162 | padding-top: 9px; 163 | font-size: 16px; 164 | line-height: normal; 165 | min-height: 34px; 166 | } 167 | .ats-switch span.switch-left { 168 | color: #fff; 169 | background: #428bca; 170 | } 171 | .ats-switch span.switch-right { 172 | color: #000; 173 | background: #eeeeee; 174 | } 175 | .ats-switch.switch-primary span.switch-left { 176 | color: #fff; 177 | background: #428bca; 178 | } 179 | .ats-switch.switch-info span.switch-left { 180 | color: #fff; 181 | background: #5bc0de; 182 | } 183 | .ats-switch.switch-success span.switch-left { 184 | color: #fff; 185 | background: #5cb85c; 186 | } 187 | .ats-switch.switch-warning span.switch-left { 188 | background: #f0ad4e; 189 | color: #fff; 190 | } 191 | .ats-switch.switch-danger span.switch-left { 192 | color: #fff; 193 | background: #d9534f; 194 | } 195 | .ats-switch.switch-default span.switch-left { 196 | color: #000; 197 | background: #eeeeee; 198 | } 199 | -------------------------------------------------------------------------------- /README_Linux.md: -------------------------------------------------------------------------------- 1 | # ACServerManager 2 | Web based server manager for Assetto Corsa directly manipulating the ini files on the server as an alternative to the windows app and having to copy files to your server. 3 | 4 | Start and stop the server, and stracker directly from the application, meaning you can make changes to the server configuration and restart the server directly from your browser or mobile phone. 5 | 6 | ## ACServerManager on Linux 7 | This is the installation guide for a Linux machine, to review the Windows installation guide go [here](https://github.com/jo3stevens/ACServerManager/blob/master/README.md). 8 | 9 | ## Updates 10 | 27/01/2017: 11 | * Update to UI layout 12 | * Added restart feature for AC & sTracker server 13 | 14 | 17/10/2015: 15 | * Bug fix when switching between two tracks with multiple track configs 16 | * Added Max Ballast and UDP Plugin fields to Advanced page 17 | * Added new setting for contentPath allowing server and content folders to be seperated (this happens when using a manager package from the kunos tool). If this setting it left empty it will assume the content folder is inside the server folder 18 | 19 | 22/08/2015: 20 | * Finished adding all the new settings from 1.2 including tyres and weather 21 | 22 | ## Details 23 | First you'll need to install Node.js on your machine. It's best to use an application 24 | like [NVM](https://github.com/creationix/nvm) to manage the installation of Node.js on Linux based machines. 25 | After installing Node.js, install [PM2](https://github.com/Unitech/pm2) when using this 26 | version of AC Server Manager, it's basically Node.js application management tool with tons of features 27 | for production use. PM2 will make sure your web application stays online and, auto restarts if it crashes. 28 | 29 | ## Install NVM 30 | To install NVM, follow the installation guide on its GitHub page [here](https://github.com/creationix/nvm). Please install NVM on the same account you run your Assetto Corsa Server. 31 | 32 | ## Install Node.js 33 | Using NVM, run the following command to install the latest version: 34 | ``` 35 | nvm install node 36 | ``` 37 | If you would like to install a specific version using NVM then run something like this: 38 | ``` 39 | nvm install 6.9.4 40 | ``` 41 | ## Install PM2 42 | To install PM2, follow the installation guide on its GitHub page [here](https://github.com/Unitech/pm2). Please install PM2 on the same account you run your Assetto Corsa Server. 43 | 44 | ## Install ACServerManager 45 | Create a directory called 'acmanager', cd into that directory and run this command to download the latest version: 46 | ``` 47 | wget https://github.com/jo3stevens/ACServerManager/archive/master.zip 48 | ``` 49 | Unzip the file & clean up, by running: 50 | ``` 51 | unzip master.zip; mv ACServerManager-master/* .; rm -R ACServerManager-master; rm master.zip 52 | ``` 53 | You'll need to first configure your manager's settings before you can run the application. 54 | ## ACServerManager Configuration 55 | To configure your manager's settings, open the 'settings.js' file. You'll see a number of variables, point the 'serverPath' 56 | to your Assetto Corsa Server directory. You can configure your username, password & port settings for ACServerManager, also 57 | if you use sTracker, point the 'sTrackerPath' variable to your installation. 58 | 59 | * serverPath: The path to your server folder containing acServer.exe 60 | * sTrackerPath: The path to your stracker folder container stracker.exe (If you don't run stracker just leave this as an empty string ('') to disable it 61 | * username/password: Set these values if you want basic authentication on the application 62 | * port: The port that the application will listen on (Be sure to open up this port on firewalls) 63 | 64 | Note: I've currently set the Assetto Corsa Server installation to one directory up in 'server', change if necessary. 65 | 66 | ## Firewall 67 | If your machine has a firewall enabled (i.e) iptables, you'll need to open / allow the ACServerManager port defined in your settings.js file. 68 | 69 | ## Running ACServerManager 70 | You first need to make sure you have the necessary Node.js dependencies, run: 71 | ``` 72 | npm install 73 | ``` 74 | To run ACServerManager using PM2 run the following command: 75 | ``` 76 | pm2 start server.js 77 | ``` 78 | To monitor applications running with PM2 run: 79 | ``` 80 | pm2 list 81 | ``` 82 | There many useful commands to manage applications using PM2, reference their GitHub page. 83 | 84 | ## Using ACServerManager 85 | * Browse to the application using your servers IP and the chosen port (or any DNS configured) 86 | * Click the 'Start' button under Assetto Corsa Server section 87 | * If using sTracker wait until the AC server has started and then click 'Start' in the sTracker Server section 88 | 89 | The server should now be running. You'll be able to see any server output in the command window and it will be logged to a file in the 'ACServerManager/log' folder. 90 | 91 | You can change any of settings and it will be applied directly to server_cfg.ini and entry_list.ini on the server. After making a change just stop and start the server from the Server Status page to apply the changes to Assetto Corsa Server. 92 | 93 | Note, the server may fail to start in some cases if the Assetto Corsa Server cannot connect to the master server. Make sure you portforward / open 94 | the necessary ports for the server to function correctly. 95 | 96 | ## Screenshots 97 | ### Server Status 98 | ![Server Status](http://deltahosting.dyndns.org:8080/acmanager/screen-cap-1.JPG) 99 | 100 | ### Server Configuration 101 | ![Server Config](http://deltahosting.dyndns.org:8080/acmanager/screen-cap-2.JPG) 102 | 103 | ### Entry List 104 | ![Entry List](http://deltahosting.dyndns.org:8080/acmanager/screen-cap-3.JPG) 105 | 106 | ### Rules 107 | ![Rules](http://deltahosting.dyndns.org:8080/acmanager/screen-cap-4.JPG) 108 | 109 | ### Advanced 110 | ![Advanced](http://deltahosting.dyndns.org:8080/acmanager/screen-cap-5.JPG) 111 | -------------------------------------------------------------------------------- /frontend/sass/lbd/_checkbox-radio-switch.scss: -------------------------------------------------------------------------------- 1 | /* Checkbox and radio */ 2 | .checkbox, 3 | .radio { 4 | margin-bottom: 12px; 5 | padding-left: 32px; 6 | position: relative; 7 | -webkit-transition: color 0.25s linear; 8 | transition: color 0.25s linear; 9 | font-size: 14px; 10 | font-weight: normal; 11 | line-height: 1.5; 12 | color: #333333; 13 | } 14 | .checkbox input, 15 | .radio input { 16 | outline: none !important; 17 | display: none; 18 | } 19 | .checkbox .icons, 20 | .radio .icons { 21 | color: $medium-gray; 22 | display: block; 23 | height: 20px; 24 | left: 0; 25 | position: absolute; 26 | top: 0; 27 | width: 20px; 28 | text-align: center; 29 | line-height: 21px; 30 | font-size: 20px; 31 | cursor: pointer; 32 | -webkit-transition: color 0.2s linear; 33 | transition: color 0.2s linear; 34 | } 35 | 36 | 37 | .checkbox .icons .first-icon, 38 | .radio .icons .first-icon, 39 | .checkbox .icons .second-icon, 40 | .radio .icons .second-icon { 41 | display: inline-table; 42 | position: absolute; 43 | left: 0; 44 | top: 0; 45 | background-color: transparent; 46 | margin: 0; 47 | @include opacity(1); 48 | } 49 | .checkbox .icons .second-icon, 50 | .radio .icons .second-icon { 51 | @include opacity(0); 52 | } 53 | .checkbox:hover, 54 | .radio:hover { 55 | -webkit-transition: color 0.2s linear; 56 | transition: color 0.2s linear; 57 | } 58 | .checkbox:hover .first-icon, 59 | .radio:hover .first-icon { 60 | @include opacity(0); 61 | } 62 | .checkbox:hover .second-icon, 63 | .radio:hover .second-icon { 64 | @include opacity (1); 65 | } 66 | .checkbox.checked, 67 | .radio.checked { 68 | color: $info-color; 69 | } 70 | .checkbox.checked .first-icon, 71 | .radio.checked .first-icon { 72 | opacity: 0; 73 | filter: alpha(opacity=0); 74 | } 75 | .checkbox.checked .second-icon, 76 | .radio.checked .second-icon { 77 | opacity: 1; 78 | filter: alpha(opacity=100); 79 | color: $info-color; 80 | -webkit-transition: color 0.2s linear; 81 | transition: color 0.2s linear; 82 | } 83 | .checkbox.disabled, 84 | .radio.disabled { 85 | cursor: default; 86 | color: $medium-gray !important; 87 | } 88 | .checkbox.disabled .icons, 89 | .radio.disabled .icons { 90 | color: $medium-gray !important; 91 | } 92 | .checkbox.disabled .first-icon, 93 | .radio.disabled .first-icon { 94 | opacity: 1; 95 | filter: alpha(opacity=100); 96 | } 97 | .checkbox.disabled .second-icon, 98 | .radio.disabled .second-icon { 99 | opacity: 0; 100 | filter: alpha(opacity=0); 101 | } 102 | .checkbox.disabled.checked .icons, 103 | .radio.disabled.checked .icons { 104 | color: $medium-gray; 105 | } 106 | .checkbox.disabled.checked .first-icon, 107 | .radio.disabled.checked .first-icon { 108 | opacity: 0; 109 | filter: alpha(opacity=0); 110 | } 111 | .checkbox.disabled.checked .second-icon, 112 | .radio.disabled.checked .second-icon { 113 | opacity: 1; 114 | filter: alpha(opacity=100); 115 | color: #D9D9D9; 116 | } 117 | 118 | 119 | 120 | /* ============================================================ 121 | * bootstrapSwitch v1.3 by Larentis Mattia @spiritualGuru 122 | * http://www.larentis.eu/switch/ 123 | * ============================================================ 124 | * Licensed under the Apache License, Version 2.0 125 | * http://www.apache.org/licenses/LICENSE-2.0 126 | * ============================================================ */ 127 | .has-switch { 128 | border-radius: 30px; 129 | cursor: pointer; 130 | display: inline-block; 131 | line-height: 1.72222; 132 | overflow: hidden; 133 | position: relative; 134 | text-align: left; 135 | width: 60px; 136 | 137 | -webkit-user-select: none; 138 | -moz-user-select: none; 139 | -ms-user-select: none; 140 | -o-user-select: none; 141 | user-select: none; 142 | 143 | /* this code is for fixing safari bug with hidden overflow for border-radius */ 144 | -webkit-mask: url('../img/mask.png') 0 0 no-repeat; 145 | -webkit-mask-size: 60px 24px; 146 | mask: url('../img/mask.png') 0 0 no-repeat; 147 | } 148 | .has-switch.deactivate { 149 | opacity: 0.5; 150 | filter: alpha(opacity=50); 151 | cursor: default !important; 152 | } 153 | .has-switch.deactivate label, 154 | .has-switch.deactivate span { 155 | cursor: default !important; 156 | } 157 | .has-switch > div { 158 | position: relative; 159 | top: 0; 160 | width: 100px; 161 | } 162 | .has-switch > div.switch-animate { 163 | -webkit-transition: left 0.25s ease-out; 164 | transition: left 0.25s ease-out; 165 | } 166 | .has-switch > div.switch-off { 167 | left: -35px; 168 | } 169 | 170 | .has-switch > div.switch-on { 171 | left: 0; 172 | } 173 | .has-switch > div label { 174 | background-color: #FFFFFF; 175 | @include icon-gradient (rgba(255,255,255,1), rgba(241,241,242,1)); 176 | 177 | box-shadow: 0 1px 1px #FFFFFF inset, 0 1px 1px rgba(0, 0, 0, 0.25); 178 | cursor: pointer; 179 | } 180 | .has-switch input[type=checkbox] { 181 | display: none; 182 | } 183 | .has-switch span { 184 | /* box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2) inset; */ 185 | cursor: pointer; 186 | float: left; 187 | font-size: 11px; 188 | font-weight: 400; 189 | height: 24px; 190 | line-height: 15px; 191 | margin: 0; 192 | padding-bottom: 6px; 193 | padding-top: 5px; 194 | position: relative; 195 | text-align: center; 196 | text-indent: -10px; 197 | width: 50%; 198 | z-index: 1; 199 | -webkit-transition: 0.25s ease-out; 200 | transition: 0.25s ease-out; 201 | } 202 | .has-switch span.switch-left { 203 | background-color: $info-color; 204 | border-left: 1px solid rgba(0, 0, 0, 0); 205 | border-radius: 30px 0 0 30px; 206 | color: #FFFFFF; 207 | } 208 | .has-switch .switch-off span.switch-left{ 209 | background-color: $medium-gray; 210 | } 211 | .has-switch span.switch-right { 212 | border-radius: 0 30px 30px 0; 213 | background-color: $info-color; 214 | color: #ffffff; 215 | text-indent: 1px; 216 | } 217 | .has-switch .switch-off span.switch-right{ 218 | background-color: $medium-gray; 219 | } 220 | 221 | .has-switch label { 222 | border-radius: 12px; 223 | float: left; 224 | height: 22px; 225 | margin: 1px -13px; 226 | padding: 0; 227 | position: relative; 228 | transition: all 0.25s ease-out 0s; 229 | vertical-align: middle; 230 | width: 22px; 231 | z-index: 100; 232 | -webkit-transition: 0.25s ease-out; 233 | transition: 0.25s ease-out; 234 | } 235 | .has-switch .switch-on .fa-check:before{ 236 | margin-left: 10px; 237 | } 238 | .has-switch:hover .switch-on label{ 239 | margin: 1px -17px; 240 | width: 26px; 241 | } 242 | .has-switch:hover .switch-off label{ 243 | margin: 1px -13px; 244 | width: 26px; 245 | } 246 | 247 | -------------------------------------------------------------------------------- /frontend/js/light-bootstrap-dashboard.js: -------------------------------------------------------------------------------- 1 | /*! 2 | 3 | ========================================================= 4 | * Light Bootstrap Dashboard - v1.3.1.0 5 | ========================================================= 6 | 7 | * Product Page: http://www.creative-tim.com/product/light-bootstrap-dashboard 8 | * Copyright 2017 Creative Tim (http://www.creative-tim.com) 9 | * Licensed under MIT (https://github.com/creativetimofficial/light-bootstrap-dashboard/blob/master/LICENSE.md) 10 | 11 | ========================================================= 12 | 13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 14 | 15 | */ 16 | 17 | var searchVisible = 0; 18 | var transparent = true; 19 | 20 | var transparentDemo = true; 21 | var fixedTop = false; 22 | 23 | var navbar_initialized = false; 24 | 25 | $(document).ready(function(){ 26 | window_width = $(window).width(); 27 | 28 | // check if there is an image set for the sidebar's background 29 | lbd.checkSidebarImage(); 30 | 31 | // Init navigation toggle for small screens 32 | if(window_width <= 991){ 33 | lbd.initRightMenu(); 34 | } 35 | 36 | // Activate the tooltips 37 | $('[rel="tooltip"]').tooltip(); 38 | 39 | // Activate the switches with icons 40 | if($('.switch').length != 0){ 41 | $('.switch')['bootstrapSwitch'](); 42 | } 43 | // Activate regular switches 44 | if($("[data-toggle='switch']").length != 0){ 45 | $("[data-toggle='switch']").wrap('
').parent().bootstrapSwitch(); 46 | } 47 | 48 | $('.form-control').on("focus", function(){ 49 | $(this).parent('.input-group').addClass("input-group-focus"); 50 | }).on("blur", function(){ 51 | $(this).parent(".input-group").removeClass("input-group-focus"); 52 | }); 53 | 54 | // Fixes sub-nav not working as expected on IOS 55 | $('body').on('touchstart.dropdown', '.dropdown-menu', function (e) { e.stopPropagation(); }); 56 | }); 57 | 58 | // activate collapse right menu when the windows is resized 59 | $(window).resize(function(){ 60 | if($(window).width() <= 991){ 61 | lbd.initRightMenu(); 62 | } 63 | }); 64 | 65 | lbd = { 66 | misc:{ 67 | navbar_menu_visible: 0 68 | }, 69 | 70 | checkSidebarImage: function(){ 71 | $sidebar = $('.sidebar'); 72 | image_src = $sidebar.data('image'); 73 | 74 | if(image_src !== undefined){ 75 | sidebar_container = '