just getting it her

This commit is contained in:
nathan wagner
2022-03-03 14:52:22 -05:00
commit ffc1246564
83 changed files with 3806 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
#body {
padding-top: 10px;
}
.navbar {
background-color: white;
border: 0;
margin-bottom: 20px;
}
.navbar .container {
background-color: #008a00;
background-image: -moz-linear-gradient(top, #008a00, #006b00);
background-image: -ms-linear-gradient(top, #008a00, #006b00);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#008a00), to(#006b00));
background-image: -webkit-linear-gradient(top, #008a00, #006b00);
background-image: -o-linear-gradient(top, #008a00, #006b00);
background-image: linear-gradient(top, #008a00, #006b00);
}
.navbar .navbar-brand {
color: white;
}
.navbar .navbar-brand:hover {
color: white;
}
.btn {
background-color: white;
}
.icon-white {
color: white;
}

View File

@@ -0,0 +1,59 @@
/* From https://github.com/sixfootsixdesigns/Bootstrap-3-Grid-Columns-Clearing */
/* clear first in row in ie 8 or lower */
.multi-columns-row .first-in-row {
clear: left;
}
/* clear the first in row for any block that has the class "multi-columns-row" */
.multi-columns-row .col-xs-6:nth-child(2n + 3) { clear: left; }
.multi-columns-row .col-xs-4:nth-child(3n + 4) { clear: left; }
.multi-columns-row .col-xs-3:nth-child(4n + 5) { clear: left; }
.multi-columns-row .col-xs-2:nth-child(6n + 7) { clear: left; }
.multi-columns-row .col-xs-1:nth-child(12n + 13) { clear: left; }
@media (min-width: 768px) {
/* reset previous grid */
.multi-columns-row .col-xs-6:nth-child(2n + 3) { clear: none; }
.multi-columns-row .col-xs-4:nth-child(3n + 4) { clear: none; }
.multi-columns-row .col-xs-3:nth-child(4n + 5) { clear: none; }
.multi-columns-row .col-xs-2:nth-child(6n + 7) { clear: none; }
.multi-columns-row .col-xs-1:nth-child(12n + 13) { clear: none; }
/* clear first in row for small columns */
.multi-columns-row .col-sm-6:nth-child(2n + 3) { clear: left; }
.multi-columns-row .col-sm-4:nth-child(3n + 4) { clear: left; }
.multi-columns-row .col-sm-3:nth-child(4n + 5) { clear: left; }
.multi-columns-row .col-sm-2:nth-child(6n + 7) { clear: left; }
.multi-columns-row .col-sm-1:nth-child(12n + 13) { clear: left; }
}
@media (min-width: 992px) {
/* reset previous grid */
.multi-columns-row .col-sm-6:nth-child(2n + 3) { clear: none; }
.multi-columns-row .col-sm-4:nth-child(3n + 4) { clear: none; }
.multi-columns-row .col-sm-3:nth-child(4n + 5) { clear: none; }
.multi-columns-row .col-sm-2:nth-child(6n + 7) { clear: none; }
.multi-columns-row .col-sm-1:nth-child(12n + 13) { clear: none; }
/* clear first in row for medium columns */
.multi-columns-row .col-md-6:nth-child(2n + 3) { clear: left; }
.multi-columns-row .col-md-4:nth-child(3n + 4) { clear: left; }
.multi-columns-row .col-md-3:nth-child(4n + 5) { clear: left; }
.multi-columns-row .col-md-2:nth-child(6n + 7) { clear: left; }
.multi-columns-row .col-md-1:nth-child(12n + 13) { clear: left; }
}
@media (min-width: 1200px) {
/* reset previous grid */
.multi-columns-row .col-md-6:nth-child(2n + 3) { clear: none; }
.multi-columns-row .col-md-4:nth-child(3n + 4) { clear: none; }
.multi-columns-row .col-md-3:nth-child(4n + 5) { clear: none; }
.multi-columns-row .col-md-2:nth-child(6n + 7) { clear: none; }
.multi-columns-row .col-md-1:nth-child(12n + 13) { clear: none; }
/* clear first in row for large columns */
.multi-columns-row .col-lg-6:nth-child(2n + 3) { clear: left; }
.multi-columns-row .col-lg-4:nth-child(3n + 4) { clear: left; }
.multi-columns-row .col-lg-3:nth-child(4n + 5) { clear: left; }
.multi-columns-row .col-lg-2:nth-child(6n + 7) { clear: left; }
.multi-columns-row .col-lg-1:nth-child(12n + 13) { clear: left; }
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,47 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" class="en" ng-app="SpringMusic">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="description" content="Spring Music">
<meta name="title" content="Spring Music">
<link rel="shortcut icon" href="favicon.ico">
<title>Spring Music</title>
<link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.1.1/css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="css/app.css">
<link rel="stylesheet" type="text/css" href="css/multi-columns-row.css">
</head>
<body>
<div class="container">
<div class="row">
<div ng-include="'templates/header.html'"></div>
</div>
<div id="body" class="row">
<ng-view></ng-view>
</div>
<div class="row">
<div ng-include="'templates/footer.html'"></div>
</div>
</div>
<script type="text/javascript" src="webjars/jquery/2.1.0/jquery.min.js"></script>
<script type="text/javascript" src="webjars/angularjs/1.2.16/angular.js"></script>
<script type="text/javascript" src="webjars/angularjs/1.2.16/angular-resource.js"></script>
<script type="text/javascript" src="webjars/angularjs/1.2.16/angular-route.js"></script>
<script type="text/javascript" src="webjars/angular-ui/0.4.0/angular-ui.js"></script>
<script type="text/javascript" src="webjars/angular-ui-bootstrap/0.10.0/ui-bootstrap.js"></script>
<script type="text/javascript" src="webjars/angular-ui-bootstrap/0.10.0/ui-bootstrap-tpls.js"></script>
<script type="text/javascript" src="webjars/bootstrap/3.1.1/js/bootstrap.js"></script>
<script type="text/javascript" src="js/app.js"></script>
<script type="text/javascript" src="js/albums.js"></script>
<script type="text/javascript" src="js/errors.js"></script>
<script type="text/javascript" src="js/info.js"></script>
<script type="text/javascript" src="js/status.js"></script>
</body>
</html>

View File

@@ -0,0 +1,199 @@
angular.module('albums', ['ngResource', 'ui.bootstrap']).
factory('Albums', function ($resource) {
return $resource('albums');
}).
factory('Album', function ($resource) {
return $resource('albums/:id', {id: '@id'});
}).
factory("EditorStatus", function () {
var editorEnabled = {};
var enable = function (id, fieldName) {
editorEnabled = { 'id': id, 'fieldName': fieldName };
};
var disable = function () {
editorEnabled = {};
};
var isEnabled = function(id, fieldName) {
return (editorEnabled['id'] == id && editorEnabled['fieldName'] == fieldName);
};
return {
isEnabled: isEnabled,
enable: enable,
disable: disable
}
});
function AlbumsController($scope, $modal, Albums, Album, Status) {
function list() {
$scope.albums = Albums.query();
}
function clone (obj) {
return JSON.parse(JSON.stringify(obj));
}
function saveAlbum(album) {
Albums.save(album,
function () {
Status.success("Album saved");
list();
},
function (result) {
Status.error("Error saving album: " + result.status);
}
);
}
$scope.addAlbum = function () {
var addModal = $modal.open({
templateUrl: 'templates/albumForm.html',
controller: AlbumModalController,
resolve: {
album: function () {
return {};
},
action: function() {
return 'add';
}
}
});
addModal.result.then(function (album) {
saveAlbum(album);
});
};
$scope.updateAlbum = function (album) {
var updateModal = $modal.open({
templateUrl: 'templates/albumForm.html',
controller: AlbumModalController,
resolve: {
album: function() {
return clone(album);
},
action: function() {
return 'update';
}
}
});
updateModal.result.then(function (album) {
saveAlbum(album);
});
};
$scope.deleteAlbum = function (album) {
Album.delete({id: album.id},
function () {
Status.success("Album deleted");
list();
},
function (result) {
Status.error("Error deleting album: " + result.status);
}
);
};
$scope.setAlbumsView = function (viewName) {
$scope.albumsView = "templates/" + viewName + ".html";
};
$scope.init = function() {
list();
$scope.setAlbumsView("grid");
$scope.sortField = "name";
$scope.sortDescending = false;
};
}
function AlbumModalController($scope, $modalInstance, album, action) {
$scope.albumAction = action;
$scope.yearPattern = /^[1-2]\d{3}$/;
$scope.album = album;
$scope.ok = function () {
$modalInstance.close($scope.album);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
};
function AlbumEditorController($scope, Albums, Status, EditorStatus) {
$scope.enableEditor = function (album, fieldName) {
$scope.newFieldValue = album[fieldName];
EditorStatus.enable(album.id, fieldName);
};
$scope.disableEditor = function () {
EditorStatus.disable();
};
$scope.isEditorEnabled = function (album, fieldName) {
return EditorStatus.isEnabled(album.id, fieldName);
};
$scope.save = function (album, fieldName) {
if ($scope.newFieldValue === "") {
return false;
}
album[fieldName] = $scope.newFieldValue;
Albums.save({}, album,
function () {
Status.success("Album saved");
list();
},
function (result) {
Status.error("Error saving album: " + result.status);
}
);
$scope.disableEditor();
};
$scope.disableEditor();
}
angular.module('albums').
directive('inPlaceEdit', function () {
return {
restrict: 'E',
transclude: true,
replace: true,
scope: {
ipeFieldName: '@fieldName',
ipeInputType: '@inputType',
ipeInputClass: '@inputClass',
ipePattern: '@pattern',
ipeModel: '=model'
},
template:
'<div>' +
'<span ng-hide="isEditorEnabled(ipeModel, ipeFieldName)" ng-click="enableEditor(ipeModel, ipeFieldName)">' +
'<span ng-transclude></span>' +
'</span>' +
'<span ng-show="isEditorEnabled(ipeModel, ipeFieldName)">' +
'<div class="input-append">' +
'<input type="{{ipeInputType}}" name="{{ipeFieldName}}" class="{{ipeInputClass}}" ' +
'ng-required ng-pattern="{{ipePattern}}" ng-model="newFieldValue" ' +
'ui-keyup="{enter: \'save(ipeModel, ipeFieldName)\', esc: \'disableEditor()\'}"/>' +
'<div class="btn-group btn-group-xs" role="toolbar">' +
'<button ng-click="save(ipeModel, ipeFieldName)" type="button" class="btn"><span class="glyphicon glyphicon-ok"></span></button>' +
'<button ng-click="disableEditor()" type="button" class="btn"><span class="glyphicon glyphicon-remove"></span></button>' +
'</div>' +
'</div>' +
'</span>' +
'</div>',
controller: 'AlbumEditorController'
};
});

14
bin/main/static/js/app.js Normal file
View File

@@ -0,0 +1,14 @@
angular.module('SpringMusic', ['albums', 'errors', 'status', 'info', 'ngRoute', 'ui.directives']).
config(function ($locationProvider, $routeProvider) {
// $locationProvider.html5Mode(true);
$routeProvider.when('/errors', {
controller: 'ErrorsController',
templateUrl: 'templates/errors.html'
});
$routeProvider.otherwise({
controller: 'AlbumsController',
templateUrl: 'templates/albums.html'
});
}
);

View File

@@ -0,0 +1,37 @@
angular.module('errors', ['ngResource']).
factory('Errors', function ($resource) {
return $resource('errors', {}, {
kill: { url: 'errors/kill' },
throw: { url: 'errors/throw' }
});
});
function ErrorsController($scope, Errors, Status) {
$scope.kill = function() {
Errors.kill({},
function () {
Status.error("The application should have been killed, but returned successfully instead.");
},
function (result) {
if (result.status === 502)
Status.error("An error occurred as expected, the application backend was killed: " + result.status);
else
Status.error("An unexpected error occurred: " + result.status);
}
);
};
$scope.throwException = function() {
Errors.throw({},
function () {
Status.error("An exception should have been thrown, but was not.");
},
function (result) {
if (result.status === 500)
Status.error("An error occurred as expected: " + result.status);
else
Status.error("An unexpected error occurred: " + result.status);
}
);
};
}

View File

@@ -0,0 +1,8 @@
angular.module('info', ['ngResource']).
factory('Info', function ($resource) {
return $resource('appinfo');
});
function InfoController($scope, Info) {
$scope.info = Info.get();
}

View File

@@ -0,0 +1,38 @@
angular.module('status', []).
factory("Status", function () {
var status = null;
var success = function (message) {
this.status = { isError: false, message: message };
};
var error = function (message) {
this.status = { isError: true, message: message };
};
var clear = function () {
this.status = null;
};
return {
status: status,
success: success,
error: error,
clear: clear
}
});
function StatusController($scope, Status) {
$scope.$watch(
function () {
return Status.status;
},
function (status) {
$scope.status = status;
},
true);
$scope.clearStatus = function () {
Status.clear();
};
}

View File

@@ -0,0 +1,32 @@
<div class="modal-header">
<h3 ng-show="albumAction === 'add'">Add an album</h3>
<h3 ng-show="albumAction === 'update'">Edit an album</h3>
</div>
<div class="modal-body">
<form name="albumForm" role="form">
<div class="form-group has-feedback" ng-class="{'has-warning': albumForm.title.$invalid, 'has-success': albumForm.title.$valid}">
<label for="title">Album Title</label>
<input type="text" class="form-control input-large" id="title" name="title" required ng-model="album.title">
<span class="glyphicon form-control-feedback" ng-class="{'glyphicon-warning-sign': albumForm.title.$invalid, 'glyphicon-ok': albumForm.title.$valid}"></span>
</div>
<div class="form-group has-feedback" ng-class="{'has-warning': albumForm.artist.$invalid, 'has-success': albumForm.artist.$valid}">
<label for="artist">Artist</label>
<input type="text" class="form-control input-large" id="artist" name="artist" required ng-model="album.artist">
<span class="glyphicon form-control-feedback" ng-class="{'glyphicon-warning-sign': albumForm.artist.$invalid, 'glyphicon-ok': albumForm.artist.$valid}"></span>
</div>
<div class="form-group has-feedback" ng-class="{'has-warning': albumForm.releaseYear.$invalid, 'has-success': albumForm.releaseYear.$valid}">
<label for="releaseYear">Release Year</label>
<input type="text" class="form-control input-small" id="releaseYear" name="releaseYear" required ng-model="album.releaseYear" ng-pattern=yearPattern>
<span class="glyphicon form-control-feedback" ng-class="{'glyphicon-warning-sign': albumForm.releaseYear.$invalid, 'glyphicon-ok': albumForm.releaseYear.$valid}"></span>
</div>
<div class="form-group has-feedback" ng-class="{'has-warning': albumForm.genre.$invalid, 'has-success': albumForm.genre.$valid}">
<label for="genre">Genre</label>
<input type="text" class="form-control input-medium" id=genre name="genre" required ng-model="album.genre">
<span class="glyphicon form-control-feedback" ng-class="{'glyphicon-warning-sign': albumForm.genre.$invalid, 'glyphicon-ok': albumForm.genre.$valid}"></span>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-primary btn-md active" ng-disabled="albumForm.$invalid" ng-click="ok()" >OK</button>
<button class="btn btn-warning btn-md active" ng-click="cancel()">Cancel</button>
</div>

View File

@@ -0,0 +1,29 @@
<div id="albums" ng-init="init()">
<div class="page-header">
<h1>Albums</h1>
<div>
<span> [ view as: </span>
<a href="" ng-click="setAlbumsView('grid')"><span class="glyphicon glyphicon-th"></span></a>
<a href="" ng-click="setAlbumsView('list')"><span class="glyphicon glyphicon-th-list"></span></a>
<span> | sort by: </span>
<a href="" ng-click="sortField='title'">title</a>
<a href="" ng-click="sortField='artist'">artist</a>
<a href="" ng-click="sortField='releaseYear'">year</a>
<a href="" ng-click="sortField='genre'">genre</a>
<a href="" ng-click="sortDescending=!sortDescending">
<span class="glyphicon" ng-class="{'glyphicon-chevron-up' : !sortDescending, 'glyphicon-chevron-down' : sortDescending}"></span>
</a>
<span> | </span>
<a href="" ng-click="addAlbum()"><span class="glyphicon glyphicon-plus"></span>add an album</a>
<span> ] </span>
</div>
</div>
<div class="row">
<div ng-include src="'templates/status.html'"></div>
</div>
<div class="row multi-columns-row">
<div ng-include src="albumsView"></div>
</div>
</div>

View File

@@ -0,0 +1,22 @@
<div id="errors" class="col-xs-12" ng-controller="ErrorsController">
<div class="page-header">
<h1>Force Errors</h1>
</div>
<div class="row">
<div ng-include src="'templates/status.html'"></div>
</div>
<div class="row">
<form role="form">
<div class="form-group">
<h3>Kill this instance of the application</h3>
<a ng-click="kill()" class="btn btn-primary btn-lg active" role="button">Kill</a>
</div>
<div class="form-group">
<h3>Force an exception to be thrown from the application</h3>
<a ng-click="throwException()" class="btn btn-primary btn-lg active" role="button">Throw Exception</a>
</div>
</form>
</div>
</div>

View File

@@ -0,0 +1,3 @@
<div id="footer" class="row">
</div>

View File

@@ -0,0 +1,31 @@
<div class="col-xs-6 col-sm-3 col-md-3 col-lg-3" ng-repeat="album in albums | orderBy:sortField:sortDescending">
<div class="thumbnail">
<div class="caption">
<h4>
<in-place-edit field-name='title' input-type='text' input-class='input-medium' model=album>{{album.title}}</in-place-edit>
</h4>
<h4>
<in-place-edit field-name='artist' input-type='text' input-class='input-medium' model=album>{{album.artist}}</in-place-edit>
</h4>
<h5>
<in-place-edit field-name='releaseYear' input-type='text' input-class='input-small' model=album>{{album.releaseYear}}</in-place-edit>
</h5>
<h5>
<in-place-edit field-name='genre' input-type='text' input-class='input-small' model=album>{{album.genre}}</in-place-edit>
</h5>
<div class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<span class="glyphicon glyphicon-cog"></span>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<li role="presentation"><a ng-click="updateAlbum(album)">edit</a></li>
<li role="presentation"><a ng-click="deleteAlbum(album)">delete</a></li>
</ul>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,24 @@
<div id="header" ng-controller="InfoController" class="col-xs-12">
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="#">Spring Music <span class="glyphicon glyphicon-music"></span></a>
<ul class="navbar-nav">
<!--<li></li>-->
</ul>
</div>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<span class="glyphicon glyphicon-info-sign icon-white"></span>
</a>
<ul class="dropdown-menu">
<li><a><strong>Profiles:</strong> {{info.profiles.join()}}</a></li>
<li><a><strong>Services:</strong> {{info.services.join()}}</a></li>
</ul>
</li>
</ul>
</div>
</nav>
</div>

View File

@@ -0,0 +1,38 @@
<div class="col-xs-12">
<table class="table table-striped">
<thead>
<tr>
<th>Album Title</th>
<th>Artist</th>
<th>Year</th>
<th>Genre</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="album in albums | orderBy:sortField:sortDescending">
<td>
<in-place-edit field-name='title' input-type='text' input-class='input-large' model=album>{{album.title}}</in-place-edit>
</td>
<td>
<in-place-edit field-name='artist' input-type='artist' input-class='input-large' model=album>{{album.artist}}</in-place-edit>
</td>
<td>
<in-place-edit field-name='releaseYear' input-type='text' input-class='input-small' model=album>{{album.releaseYear}}</in-place-edit>
</td>
<td>
<in-place-edit field-name='genre' input-type='text' input-class='input-medium' model=album>{{album.genre}}</in-place-edit>
</td>
<td class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<span class="glyphicon glyphicon-cog"></span>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<li role="presentation"><a ng-click="updateAlbum(album)">edit</a></li>
<li role="presentation"><a ng-click="deleteAlbum(album)">delete</a></li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>

View File

@@ -0,0 +1,8 @@
<div class="col-xs-12" id="status" ng-controller="StatusController">
<div id="alert" ng-show="status">
<div class="alert" ng-class="{'alert-success': !status.isError, 'alert-danger': status.isError}">
<button type="button" class="close" ng-click="clearStatus()"><span class="glyphicon glyphicon-remove-circle"></span></button>
<p>{{status.message}}</p>
</div>
</div>
</div>