A ton of progress, search start
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Tyler
2020-12-26 05:46:23 -05:00
parent bed34d5350
commit d086b29bcc
47 changed files with 87115 additions and 7581 deletions

View File

@ -1,22 +0,0 @@
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue');
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('example-component', require('./components/ExampleComponent.vue'));
const app = new Vue({
el: '#app'
});

View File

@ -1,23 +0,0 @@
<template>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Example Component</div>
<div class="panel-body">
I'm an example component!
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component mounted.')
}
}
</script>

View File

@ -1,38 +0,0 @@
// Body
$body-bg: #f5f8fa;
// Borders
$laravel-border-color: darken($body-bg, 10%);
$list-group-border: $laravel-border-color;
$navbar-default-border: $laravel-border-color;
$panel-default-border: $laravel-border-color;
$panel-inner-border: $laravel-border-color;
// Brands
$brand-primary: #3097D1;
$brand-info: #8eb4cb;
$brand-success: #2ab27b;
$brand-warning: #cbb956;
$brand-danger: #bf5329;
// Typography
$icon-font-path: "~bootstrap-sass/assets/fonts/bootstrap/";
$font-family-sans-serif: "Raleway", sans-serif;
$font-size-base: 14px;
$line-height-base: 1.6;
$text-color: #636b6f;
// Navbar
$navbar-default-bg: #fff;
// Buttons
$btn-default-color: $text-color;
// Inputs
$input-border: lighten($text-color, 40%);
$input-border-focus: lighten($brand-primary, 25%);
$input-color-placeholder: lighten($text-color, 30%);
// Panels
$panel-default-heading-bg: #fff;

View File

@ -1,9 +0,0 @@
// Fonts
@import url("https://fonts.googleapis.com/css?family=Raleway:300,400,600");
// Variables
@import "variables";
// Bootstrap
@import "~bootstrap-sass/assets/stylesheets/bootstrap";

133
resources/js/app.js vendored Normal file
View File

@ -0,0 +1,133 @@
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
$(document).ready(function(e) {
$.fn.dataTable.render.authorValue = function(_, context, book) {
let authors = [];
console.log(book);
for (let author of book.authors) {
authors.push(author.name);
}
return authors.join(', ');
};
var authorOptions = {
placeholder: 'Authors',
tags: true,
ajax: {
url: '/authors/search',
dataType: 'json'
}
};
var locationOptions = {
placeholder: 'Location',
tags: true
};
$('#add-form .select2-author').select2(authorOptions);
$('#add-form .select2-location').select2(locationOptions);
$('#add-form').on('click', '.remove-row', function(e) {
e.preventDefault();
$(this).closest('.form-row').remove();
});
$('#add-form').on('keydown', '.barcode_input', function(e) {
if (e.keyCode === 13) {
e.preventDefault();
}
});
$('#add-form').on('keyup', '.barcode_input', function (e) {
if (e.keyCode === 13) {
// Do something
e.preventDefault();
var $this = $(this),
$row = $this.closest('.form-row'),
barcodeValue = $this.val();
if (barcodeValue === '') {
return;
}
$.get('/lookup/' + barcodeValue, function(res) {
$row.find('input[name*=name]').val(res.title);
var $authors = $row.find('.select2-author');
$authors.children('option').remove();
for (var i = 0; i < res.authors.length; i++) {
$authors.append($('<option>', {value: res.authors[i], text: res.authors[i], selected: 'selected'}));
}
$authors.trigger('change');
}, 'json');
var count = emptyRowCount();
console.log('Empty rows:', count);
if (count < 1) {
var firstIndex = 0,
$container = $row.closest('.row-container');
for (var i = 0; i < 200; i++) {
if ($container.find('.form-row[data-index=' + i + ']').length < 1) {
firstIndex = i;
break;
}
}
var $template = $('#add-template'),
$clone = $template.clone();
$clone.attr('data-index', firstIndex);
$clone.find('input, select').each(function() {
$(this).attr('name', $(this).attr('name').replace('__INDEX__', firstIndex));
});
$clone.removeAttr('id');
$clone.find('input[type=text]').val('');
$clone.removeClass('invisible').addClass('form-row');
$container.append($clone);
setTimeout(function() {
$clone.find('.barcode_input').focus();
$clone.find('.select2-author').select2(authorOptions);
}, 150);
}
}
});
});
function emptyRowCount() {
var $barcodes = $('#add-form .barcode_input');
var count = 0;
$barcodes.each(function() {
if ($(this).val() == '') {
count++;
}
});
return count;
}

View File

@ -1,4 +1,3 @@
window._ = require('lodash');
/**
@ -8,9 +7,13 @@ window._ = require('lodash');
*/
try {
window.Popper = require('popper.js').default;
window.$ = window.jQuery = require('jquery');
require('bootstrap-sass');
require('bootstrap');
require('select2');
require('datatables.net-bs4');
require('datatables.net-buttons-bs4');
} catch (e) {}
/**
@ -23,31 +26,19 @@ window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
/**
* Next we will register the CSRF Token as a common header with Axios so that
* all outgoing HTTP requests automatically have it attached. This is just
* a simple convenience so we don't have to attach every token manually.
*/
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
/**
* Echo exposes an expressive API for subscribing to channels and listening
* for events that are broadcast by Laravel. Echo and event broadcasting
* allows your team to easily build robust real-time web applications.
*/
// import Echo from 'laravel-echo'
// import Echo from 'laravel-echo';
// window.Pusher = require('pusher-js');
// window.Echo = new Echo({
// broadcaster: 'pusher',
// key: 'your-pusher-key'
// key: process.env.MIX_PUSHER_APP_KEY,
// cluster: process.env.MIX_PUSHER_APP_CLUSTER,
// forceTLS: true
// });

14
resources/sass/app.scss vendored Normal file
View File

@ -0,0 +1,14 @@
// Bootstrap
@import "../../node_modules/bootstrap/scss/bootstrap";
// DataTables
@import "../../node_modules/datatables.net-bs4/css/dataTables.bootstrap4.css";
@import "../../node_modules/datatables.net-buttons-bs4/css/buttons.bootstrap4.css";
body {
padding-top: 5rem;
}
.form-row {
padding-bottom: 6px;
}

View File

@ -1,7 +1,8 @@
@extends('layouts.main')
@section('content')
<form id="add-form">
<form id="add-form" method="POST" action="{{ route('save') }}">
{{ csrf_field() }}
<div class="form-row justify-content-md-center">
<div class="col-4">
<select name="location" class="form-control select2-location">
@ -9,29 +10,21 @@
</div>
</div>
<br />
<div class="form-row">
<div class="col">
<input name="books[][barcode]" type="text" class="form-control barcode_input" placeholder="Barcode">
</div>
<div class="col-4">
<input name="books[][name]" type="text" class="form-control" placeholder="Name">
</div>
<div class="col">
<select name="books[][authors]" class="form-control select2-author" multiple="multiple">
</select>
</div>
<div class="row-container">
@if (!empty($old))
@foreach ($old as $index => $item)
@include('partials/row', [ 'index' => $index, 'item' => $item ])
@endforeach
@include('partials/row', [ 'index' => count($old), 'item' => [] ])
@else
@include('partials/row', [ 'index' => 0])
@endif
</div>
<div class="row">
<button class="btn btn-primary" name="save" type="submit">
Save
</button>
</div>
</form>
<div id="add-template" class="invisible">
<div class="col">
<input name="books[][barcode]" type="text" class="form-control barcode_input" placeholder="Barcode">
</div>
<div class="col-4">
<input name="books[][name]" type="text" class="form-control" placeholder="Name">
</div>
<div class="col">
<select name="books[][authors]" class="form-control select2-author" multiple="multiple">
</select>
</div>
</div>
@include('partials/row', [ 'id' => 'add-template', 'htmlClass' => 'invisible' ])
@endsection

View File

@ -0,0 +1,21 @@
@extends('layouts.main')
@section('content')
<table class="table table-compact">
<thead>
<th>Name</th>
<th>Authors</th>
<th>Location</th>
</thead>
<tbody>
@foreach ($rows as $row)
<tr>
<td>{{ $row->name }}</td>
<td>{{ $row->authors->pluck('name')->join(', ') }}</td>
<td>{{ $row->location->name }}</td>
</tr>
@endforeach
</tbody>
</table>
{{ $rows->links() }}
@endsection

View File

@ -8,49 +8,20 @@
<title>{{ config('app.name') }}</title>
<!-- Bootstrap core CSS -->
<link href="{{ url('css/bootstrap.min.css') }}" rel="stylesheet">
<link href="{{ mix('css/app.css') }}" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />
<link href="{{ url('css/select2-bs4.css') }}" rel="stylesheet">
<link href="{{ url('css/app.css') }}" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="#">{{ config('app.name') }}</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault"
aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="/">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="/add">Add</a>
</li>
</ul>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
@include('partials/navbar')
<main role="main" class="container">
@yield('content')
</main><!-- /.container -->
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
<script src="{{ url('js/bootstrap.min.js') }}"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
<script src="{{ url('js/app.js') }}"></script>
<script src="{{ mix('js/app.js') }}"></script>
<script src="{{ asset('vendor/datatables/buttons.server-side.js') }}"></script>
@stack('scripts')
</body>
</html>

View File

@ -0,0 +1,22 @@
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="#">{{ config('app.name') }}</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault"
aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="/">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="/add">Add</a>
</li>
</ul>
<form class="form-inline my-2 my-lg-0" action="{{ route('search') }}">
<input name="query" class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search" />
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>

View File

@ -0,0 +1,20 @@
<div {!! !empty($id) ? 'id="' . $id . '" ' : '' !!}class="form-row {{ $htmlClass ?? '' }}" data-index="{{ $index ?? '__INDEX__' }}">
<div class="col">
<input name="books[{{ $index ?? '__INDEX__' }}][barcode]" type="text" class="form-control barcode_input" placeholder="Barcode" value="{{ $item['barcode'] ?? '' }}">
</div>
<div class="col-4">
<input name="books[{{ $index ?? '__INDEX__' }}][name]" type="text" class="form-control" placeholder="Name" value="{{ $item['name'] ?? '' }}">
</div>
<div class="col">
<select name="books[{{ $index ?? '__INDEX__' }}][authors][]" class="form-control select2-author" multiple="multiple">
@if(!empty($item['authors']))
@foreach($item['authors'] as $author)
<option value="{{ $author }}" selected="selected">{{ $author }}</option>
@endforeach
@endif
</select>
</div>
<div class="col-1">
<button class="remove-row btn btn-danger">Remove</button>
</div>
</div>

View File

@ -1 +0,0 @@
@extends('layouts.main')