A ton of progress, search start
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
bed34d5350
commit
d086b29bcc
@ -4,15 +4,13 @@ namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class BookController extends Controller
|
||||
{
|
||||
class BookController extends Controller {
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
public function index() {
|
||||
//
|
||||
}
|
||||
|
||||
@ -21,64 +19,58 @@ class BookController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
public function create() {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
public function store(Request $request) {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
public function show($id) {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
public function edit($id) {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
public function update(Request $request, $id) {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
public function destroy($id) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Location;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class LocationController extends Controller {
|
||||
@ -37,10 +38,16 @@ class LocationController extends Controller {
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return mixed
|
||||
*/
|
||||
public function show($id) {
|
||||
//
|
||||
$location = Location::find($id);
|
||||
|
||||
if (!$location) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return view('location', [ 'location' => $location ]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,12 +2,73 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Author;
|
||||
use App\Models\Book;
|
||||
use App\Models\Location;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class MainController extends Controller {
|
||||
public function index() {
|
||||
return view('welcome');
|
||||
$rows = Book::paginate(15);
|
||||
|
||||
return view('index', [ 'rows' => $rows ]);
|
||||
}
|
||||
|
||||
public function add() {
|
||||
return view('add');
|
||||
public function search(Request $request) {
|
||||
$this->validate($request, [
|
||||
'query' => [ 'required' ]
|
||||
]);
|
||||
|
||||
$rows = Book::where('name', 'LIKE', '%' . $request->get('query') . '%')->paginate(15);
|
||||
|
||||
return view('index', [ 'rows' => $rows ]);
|
||||
}
|
||||
|
||||
public function add(Request $request) {
|
||||
return view('add', [
|
||||
'old' => array_filter($request->old('books', []), function($item) {
|
||||
return !empty($item['barcode']);
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
public function save(Request $request) {
|
||||
$this->validate($request, [
|
||||
'location' => [ 'required' ]
|
||||
]);
|
||||
|
||||
$input = array_filter($request->get('books'), function($item) {
|
||||
return !empty($item['barcode']) && !empty($item['name']);
|
||||
});
|
||||
|
||||
$this->getValidationFactory()->make($input, [
|
||||
'*.barcode' => [ 'required' ],
|
||||
'*.name' => [ 'required' ]
|
||||
]);
|
||||
|
||||
$location = Location::firstOrCreate([
|
||||
'name' => trim($request->get('location'))
|
||||
]);
|
||||
|
||||
foreach ($input as $item) {
|
||||
$book = Book::create([
|
||||
'location_id' => $location->id,
|
||||
'barcode' => $item['barcode'],
|
||||
'name' => $item['name']
|
||||
]);
|
||||
|
||||
$authors = [];
|
||||
|
||||
foreach (Arr::get($item, 'authors') as $author) {
|
||||
$authors[] = Author::firstOrCreate([
|
||||
'name' => $author
|
||||
]);
|
||||
}
|
||||
|
||||
$authors = array_map(function($author) { return $author->id; }, $authors);
|
||||
|
||||
$book->authors()->attach($authors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Author extends Authenticatable {
|
||||
class Author extends Model {
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
@ -2,9 +2,15 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use App\Services\Search\BookConfigurator;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use ScoutElastic\Searchable;
|
||||
|
||||
class Book extends Authenticatable {
|
||||
class Book extends Model {
|
||||
|
||||
use Searchable;
|
||||
|
||||
protected $indexConfigurator = BookConfigurator::class;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
@ -12,14 +18,28 @@ class Book extends Authenticatable {
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'location_id', 'barcode', 'name',
|
||||
];
|
||||
|
||||
public function author() {
|
||||
return $this->hasMany(Author::class);
|
||||
public function authors() {
|
||||
return $this->belongsToMany(Author::class, 'book_authors');
|
||||
}
|
||||
|
||||
public function location() {
|
||||
return $this->belongsTo(Location::class);
|
||||
}
|
||||
|
||||
protected $mapping = [
|
||||
'properties' => [
|
||||
'name' => [
|
||||
'type' => 'text',
|
||||
// Also you can configure multi-fields, more details you can find here https://www.elastic.co/guide/en/elasticsearch/reference/current/multi-fields.html
|
||||
'fields' => [
|
||||
'raw' => [
|
||||
'type' => 'keyword',
|
||||
]
|
||||
]
|
||||
],
|
||||
]
|
||||
];
|
||||
}
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Location extends Authenticatable {
|
||||
class Location extends Model {
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
22
app/Services/Search/BookConfigurator.php
Normal file
22
app/Services/Search/BookConfigurator.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
namespace App\Services\Search;
|
||||
|
||||
use ScoutElastic\IndexConfigurator;
|
||||
|
||||
class BookConfigurator extends IndexConfigurator
|
||||
{
|
||||
// It's not obligatory to determine name. By default it'll be a snaked class name without `IndexConfigurator` part.
|
||||
protected $name = 'books';
|
||||
|
||||
// You can specify any settings you want, for example, analyzers.
|
||||
protected $settings = [
|
||||
'analysis' => [
|
||||
'analyzer' => [
|
||||
'es_std' => [
|
||||
'type' => 'standard',
|
||||
'stopwords' => '_spanish_'
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
@ -6,15 +6,16 @@
|
||||
"type": "project",
|
||||
"require": {
|
||||
"php": "^7.3|^8.0",
|
||||
"babenkoivan/scout-elasticsearch-driver": "^4.2",
|
||||
"fideloper/proxy": "^4.4",
|
||||
"fruitcake/laravel-cors": "^2.0",
|
||||
"google/apiclient": "^2.2",
|
||||
"guzzlehttp/guzzle": "^7.0.1",
|
||||
"laravel/framework": "^8.12",
|
||||
"laravel/scout": "^8.5",
|
||||
"laravel/tinker": "^2.5",
|
||||
"laravel/ui": "^3.0",
|
||||
"sunra/php-simple-html-dom-parser": "^1.5",
|
||||
"yajra/laravel-datatables-oracle": "^9.0"
|
||||
"sunra/php-simple-html-dom-parser": "^1.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"facade/ignition": "^2.5",
|
||||
|
1461
composer.lock
generated
1461
composer.lock
generated
File diff suppressed because it is too large
Load Diff
32
package.json
32
package.json
@ -2,20 +2,32 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "npm run development",
|
||||
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"watch": "npm run development -- --watch",
|
||||
"watch-poll": "npm run watch -- --watch-poll",
|
||||
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --disable-host-check --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"prod": "npm run production",
|
||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --config=node_modules/laravel-mix/setup/webpack.config.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"axios": "^0.17",
|
||||
"bootstrap-sass": "^3.3.7",
|
||||
"cross-env": "^5.1",
|
||||
"@ttskch/select2-bootstrap4-theme": "^1.3.4",
|
||||
"axios": "^0.19",
|
||||
"bootstrap": "^4.0.0",
|
||||
"cross-env": "^7.0",
|
||||
"datatables.net-bs4": "^1.10.23",
|
||||
"datatables.net-buttons-bs4": "^1.6.5",
|
||||
"jquery": "^3.2",
|
||||
"laravel-mix": "^1.0",
|
||||
"lodash": "^4.17.4",
|
||||
"vue": "^2.5.7"
|
||||
"laravel-mix": "^5.0.1",
|
||||
"lodash": "^4.17.19",
|
||||
"popper.js": "^1.12",
|
||||
"resolve-url-loader": "^2.3.1",
|
||||
"sass": "^1.20.1",
|
||||
"sass-loader": "^8.0.0",
|
||||
"select2": "^4.0.13",
|
||||
"vue": "^2.5.17",
|
||||
"vue-template-compiler": "^2.6.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"vue-router": "^3.4.9"
|
||||
}
|
||||
}
|
||||
|
11293
public/css/app.css
vendored
11293
public/css/app.css
vendored
File diff suppressed because it is too large
Load Diff
2931
public/css/bootstrap-grid.css
vendored
2931
public/css/bootstrap-grid.css
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
10
public/css/bootstrap-grid.min.css
vendored
10
public/css/bootstrap-grid.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
90
public/css/bootstrap-reboot.css
vendored
90
public/css/bootstrap-reboot.css
vendored
@ -1,8 +1,8 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v4.0.0-beta.2 (https://getbootstrap.com)
|
||||
* Copyright 2011-2017 The Bootstrap Authors
|
||||
* Copyright 2011-2017 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* Bootstrap Reboot v4.5.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2020 The Bootstrap Authors
|
||||
* Copyright 2011-2020 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/
|
||||
*,
|
||||
@ -15,22 +15,16 @@ html {
|
||||
font-family: sans-serif;
|
||||
line-height: 1.15;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-ms-overflow-style: scrollbar;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
@-ms-viewport {
|
||||
width: device-width;
|
||||
}
|
||||
|
||||
article, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section {
|
||||
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
@ -39,8 +33,8 @@ body {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
[tabindex="-1"]:focus {
|
||||
outline: none !important;
|
||||
[tabindex="-1"]:focus:not(:focus-visible) {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
hr {
|
||||
@ -63,9 +57,11 @@ abbr[title],
|
||||
abbr[data-original-title] {
|
||||
text-decoration: underline;
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
border-bottom: 0;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
@ -101,10 +97,6 @@ blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
@ -134,7 +126,6 @@ a {
|
||||
color: #007bff;
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
-webkit-text-decoration-skip: objects;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
@ -142,25 +133,21 @@ a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:not([href]):not([tabindex]) {
|
||||
a:not([href]):not([class]) {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover {
|
||||
a:not([href]):not([class]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:not([href]):not([tabindex]):focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace;
|
||||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
@ -180,21 +167,9 @@ img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
svg:not(:root) {
|
||||
svg {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
a,
|
||||
area,
|
||||
button,
|
||||
[role="button"],
|
||||
input:not([type="range"]),
|
||||
label,
|
||||
select,
|
||||
summary,
|
||||
textarea {
|
||||
-ms-touch-action: manipulation;
|
||||
touch-action: manipulation;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
@ -204,18 +179,19 @@ table {
|
||||
caption {
|
||||
padding-top: 0.75rem;
|
||||
padding-bottom: 0.75rem;
|
||||
color: #868e96;
|
||||
color: #6c757d;
|
||||
text-align: left;
|
||||
caption-side: bottom;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
margin-bottom: .5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
@ -248,13 +224,28 @@ select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role="button"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
button,
|
||||
html [type="button"],
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
button:not(:disabled),
|
||||
[type="button"]:not(:disabled),
|
||||
[type="reset"]:not(:disabled),
|
||||
[type="submit"]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
@ -269,13 +260,6 @@ input[type="checkbox"] {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
input[type="date"],
|
||||
input[type="time"],
|
||||
input[type="datetime-local"],
|
||||
input[type="month"] {
|
||||
-webkit-appearance: listbox;
|
||||
}
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
resize: vertical;
|
||||
@ -314,7 +298,6 @@ progress {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
[type="search"]::-webkit-search-cancel-button,
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
@ -330,6 +313,7 @@ output {
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
template {
|
||||
|
File diff suppressed because one or more lines are too long
10
public/css/bootstrap-reboot.min.css
vendored
10
public/css/bootstrap-reboot.min.css
vendored
@ -1,8 +1,8 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v4.0.0-beta.2 (https://getbootstrap.com)
|
||||
* Copyright 2011-2017 The Bootstrap Authors
|
||||
* Copyright 2011-2017 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* Bootstrap Reboot v4.5.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2020 The Bootstrap Authors
|
||||
* Copyright 2011-2020 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}@-ms-viewport{width:device-width}article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}[role=button],a,area,button,input:not([type=range]),label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#868e96;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item}template{display:none}[hidden]{display:none!important}
|
||||
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
|
||||
/*# sourceMappingURL=bootstrap-reboot.min.css.map */
|
File diff suppressed because one or more lines are too long
5245
public/css/bootstrap.css
vendored
5245
public/css/bootstrap.css
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
10
public/css/bootstrap.min.css
vendored
10
public/css/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
61357
public/js/app.js
vendored
61357
public/js/app.js
vendored
File diff suppressed because it is too large
Load Diff
8262
public/js/bootstrap.bundle.js
vendored
8262
public/js/bootstrap.bundle.js
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
8
public/js/bootstrap.bundle.min.js
vendored
8
public/js/bootstrap.bundle.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3362
public/js/bootstrap.js
vendored
3362
public/js/bootstrap.js
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
8
public/js/bootstrap.min.js
vendored
8
public/js/bootstrap.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
22
resources/assets/js/app.js
vendored
22
resources/assets/js/app.js
vendored
@ -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'
|
||||
});
|
@ -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>
|
38
resources/assets/sass/_variables.scss
vendored
38
resources/assets/sass/_variables.scss
vendored
@ -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;
|
9
resources/assets/sass/app.scss
vendored
9
resources/assets/sass/app.scss
vendored
@ -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
133
resources/js/app.js
vendored
Normal 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;
|
||||
}
|
@ -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
14
resources/sass/app.scss
vendored
Normal 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;
|
||||
}
|
@ -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
|
21
resources/views/index.blade.php
Normal file
21
resources/views/index.blade.php
Normal 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
|
@ -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>
|
||||
|
22
resources/views/partials/navbar.blade.php
Normal file
22
resources/views/partials/navbar.blade.php
Normal 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>
|
20
resources/views/partials/row.blade.php
Normal file
20
resources/views/partials/row.blade.php
Normal 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>
|
@ -1 +0,0 @@
|
||||
@extends('layouts.main')
|
@ -13,6 +13,8 @@
|
||||
|
||||
Route::get('/', 'MainController@index');
|
||||
Route::get('/add', 'MainController@add');
|
||||
Route::post('/save', 'MainController@save')->name('save');
|
||||
Route::get('/search', 'MainController@search')->name('search');
|
||||
|
||||
Route::get('/lookup/{isbn}', 'LookupController@lookup');
|
||||
|
||||
|
6
webpack.mix.js
vendored
6
webpack.mix.js
vendored
@ -1,4 +1,4 @@
|
||||
let mix = require('laravel-mix');
|
||||
const mix = require('laravel-mix');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -11,5 +11,5 @@ let mix = require('laravel-mix');
|
||||
|
|
||||
*/
|
||||
|
||||
mix.js('resources/assets/js/app.js', 'public/js')
|
||||
.sass('resources/assets/sass/app.scss', 'public/css');
|
||||
mix.js('resources/js/app.js', 'public/js')
|
||||
.sass('resources/sass/app.scss', 'public/css');
|
||||
|
Loading…
Reference in New Issue
Block a user