14 Commits

54 changed files with 19772 additions and 60144 deletions

View File

@@ -1,53 +0,0 @@
<?php
namespace App\Events;
use \App\Item;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class RefreshPage implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Item
*
* @var Item
*/
public $item;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Item $item)
{
$this->item = $item;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return ['touchedItem'];
}
public function broadcastAs()
{
return 'RefreshPage';
}
}

View File

@@ -5,20 +5,12 @@ namespace App\Events;
use \App\Item; use \App\Item;
use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
class ReturnItem class ReturnItem
{ {
use Dispatchable, InteractsWithSockets, SerializesModels; use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Item
*
* @var Item
*/
public $item; public $item;
/** /**
@@ -40,11 +32,6 @@ class ReturnItem
*/ */
public function broadcastOn() public function broadcastOn()
{ {
return new PrivateChannel('touchedItem'); return new PrivateChannel('channel-name');
}
public function broadcastAs()
{
return 'ReturnItem';
} }
} }

View File

@@ -2,7 +2,6 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Events\RefreshPage;
use App\Events\ReturnItem; use App\Events\ReturnItem;
use App\Item; use App\Item;
use App\User; use App\User;
@@ -33,7 +32,6 @@ class TakeController extends Controller
); );
} }
RefreshPage::dispatch($item);
return redirect('home'); return redirect('home');
} }
@@ -57,8 +55,7 @@ class TakeController extends Controller
); );
} }
RefreshPage::dispatch($item); event(new ReturnItem($item));
ReturnItem::dispatch($item);
return redirect('home'); return redirect('home');
} }
} }

View File

@@ -51,7 +51,7 @@ class Kernel extends HttpKernel
* *
* @var array * @var array
*/ */
protected $middlewareAliases = [ protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class, 'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,

View File

@@ -2,7 +2,7 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware; use Fideloper\Proxy\TrustProxies as Middleware;
use Illuminate\Http\Request; use Illuminate\Http\Request;
class TrustProxies extends Middleware class TrustProxies extends Middleware
@@ -19,10 +19,5 @@ class TrustProxies extends Middleware
* *
* @var int * @var int
*/ */
protected $headers = protected $headers = Request::HEADER_X_FORWARDED_ALL;
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB;
} }

View File

@@ -22,6 +22,7 @@ class AuthServiceProvider extends ServiceProvider
*/ */
public function boot() public function boot()
{ {
$this->registerPolicies();
// //
} }

View File

@@ -5,24 +5,23 @@
"license": "MIT", "license": "MIT",
"type": "project", "type": "project",
"require": { "require": {
"php": "^8.0.2", "php": "^7.3.0",
"inertiajs/inertia-laravel": "^0.6.11", "fideloper/proxy": "^4.4",
"laravel/framework": "^10.0", "laravel/framework": "^8.0",
"laravel/ui": "^4.0",
"laravel/helpers": "^1.4", "laravel/helpers": "^1.4",
"laravel/tinker": "^2.4.1", "laravel/tinker": "^2.4.1",
"pusher/pusher-php-server": "^7.2" "laravel/ui": "^3.0"
}, },
"require-dev": { "require-dev": {
"beyondcode/laravel-dump-server": "^1.0", "beyondcode/laravel-dump-server": "^1.0",
"filp/whoops": "^2.0", "filp/whoops": "^2.0",
"fzaninotto/faker": "^1.4", "fzaninotto/faker": "^1.4",
"mockery/mockery": "^1.0", "mockery/mockery": "^1.0",
"nunomaduro/collision": "^7.0", "nunomaduro/collision": "^5.0",
"nunomaduro/larastan": "^2.9.5", "nunomaduro/larastan": "^0.7.4",
"nunomaduro/phpinsights": "*", "nunomaduro/phpinsights": "^1.14",
"phpstan/phpstan": "^1.10.66", "phpstan/phpstan": "^0.12.85",
"phpunit/phpunit": "^10.0" "phpunit/phpunit": "^9.0"
}, },
"autoload": { "autoload": {
"classmap": [ "classmap": [
@@ -64,6 +63,6 @@
"dealerdirect/phpcodesniffer-composer-installer": true "dealerdirect/phpcodesniffer-composer-installer": true
} }
}, },
"minimum-stability": "stable", "minimum-stability": "dev",
"prefer-stable": true "prefer-stable": true
} }

6842
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -156,7 +156,7 @@ return [
*/ */
App\Providers\AppServiceProvider::class, App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class, App\Providers\AuthServiceProvider::class,
App\Providers\BroadcastServiceProvider::class, // App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class, App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class, App\Providers\RouteServiceProvider::class,

View File

@@ -1,36 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('jobs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('queue')->index();
$table->longText('payload');
$table->unsignedTinyInteger('attempts');
$table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('available_at');
$table->unsignedInteger('created_at');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('jobs');
}
};

17117
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,26 +1,26 @@
{ {
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "vite", "dev": "npm run development",
"build": "vite build" "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": "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",
"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"
}, },
"devDependencies": { "devDependencies": {
"axios": "^1.1.3", "axios": "^0.21",
"bootstrap": "^4.6.0", "bootstrap": "^4.6.0",
"cross-env": "^5.2.1", "cross-env": "^5.2.1",
"jquery": "^3.5.1", "jquery": "^3.5.1",
"laravel-echo": "^1.14.1", "laravel-mix": "^6.0.18",
"laravel-vite-plugin": "^0.7.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"popper.js": "^1.16.1", "popper.js": "^1.16.1",
"postcss": "^8.4.19",
"pusher-js": "^7.4.1",
"resolve-url-loader": "^3.1.3", "resolve-url-loader": "^3.1.3",
"sass": "^1.56.1", "sass": "^1.32.12",
"sass-loader": "^8.0.2", "sass-loader": "^8.0.2",
"vite": "^3.2.3" "vue": "^2.6.12",
}, "vue-template-compiler": "^2.6.12"
"dependencies": {
"moment": "^2.29.4"
} }
} }

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import"https://js.pusher.com/7.2/pusher.min.js";var n=new Pusher("93b3e504421787295454",{cluster:"us2"}),o=n.subscribe("touchedItem");o.bind("RefreshPage",function(e){window.location.reload(),console.log(JSON.stringify(e))});

View File

@@ -1,12 +0,0 @@
{
"resources/js/app.js": {
"file": "assets/app.4993c47e.js",
"src": "resources/js/app.js",
"isEntry": true
},
"resources/js/pusher.js": {
"file": "assets/pusher.a7756fcc.js",
"src": "resources/js/pusher.js",
"isEntry": true
}
}

9252
public/css/app.css vendored

File diff suppressed because one or more lines are too long

0
public/favicon.ico Normal file
View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

46234
public/js/app.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1 +1,4 @@
{} {
"/js/app.js": "/js/app.js",
"/css/app.css": "/css/app.css"
}

62
resources/js/app.js vendored
View File

@@ -5,10 +5,9 @@
* building robust, powerful web applications using Vue and Laravel. * building robust, powerful web applications using Vue and Laravel.
*/ */
import './bootstrap'; require('./bootstrap');
import moment from "moment";
// window.Vue = require('vue'); window.Vue = require('vue');
/** /**
* Next, we will create a fresh Vue application instance and attach it to * Next, we will create a fresh Vue application instance and attach it to
@@ -16,59 +15,8 @@ import moment from "moment";
* or customize the JavaScript scaffolding to fit your unique needs. * or customize the JavaScript scaffolding to fit your unique needs.
*/ */
// Vue.component('example-component', require('./components/ExampleComponent.vue')); Vue.component('example-component', require('./components/ExampleComponent.vue'));
// const app = new Vue({ const app = new Vue({
// el: '#app' el: '#app'
// });
function updateTime() {
var dates = document.getElementsByClassName("takenItemDate");
for (let i = 0; i < dates.length; i++) {
let time = dates.item(i).innerText;
let fromNow = moment(time).fromNow();
let id = "itemPassedTime_" + dates.item(i).id;
document.getElementById(id).innerText = fromNow;
}
}
updateTime();
setInterval(updateTime, 1 * 60 * 1000);
function setFaviconNumber(number) {
var canvas = document.createElement('canvas'),
ctx,
img = document.createElement('img'),
link = document.getElementById('favicon').cloneNode(true);
if (canvas.getContext) {
canvas.height = canvas.width = 48; // set the size
ctx = canvas.getContext('2d');
img.onload = function () { // once the image has loaded
ctx.drawImage(this, 0, 0);
ctx.font = 'bold 35px "helvetica", sans-serif';
ctx.fillStyle = '#ffff66';
ctx.fillText(number, 3, 25);
link.href = canvas.toDataURL('image/png');
document.body.appendChild(link);
};
img.src = 'favicon.png';
}
};
usedItems = document.getElementById("usedItems").innerText;
setFaviconNumber(usedItems);
/**
* Source:
* https://www.designcise.com/web/tutorial/how-to-detect-if-the-browser-tab-is-active-or-not-using-javascript
*/
document.addEventListener('visibilitychange', function (event) {
if (document.hidden) {
console.log('not visible');
} else {
updateTime();
}
}); });

View File

@@ -1,5 +1,18 @@
import _ from 'lodash';
window._ = _; window._ = require('lodash');
window.Popper = require('popper.js').default;
/**
* We'll load jQuery and the Bootstrap jQuery plugin which provides support
* for JavaScript based Bootstrap features such as modals and tabs. This
* code may be modified to fit the specific needs of your application.
*/
try {
window.$ = window.jQuery = require('jquery');
require('bootstrap');
} catch (e) {}
/** /**
* We'll load the axios HTTP library which allows us to easily issue requests * We'll load the axios HTTP library which allows us to easily issue requests
@@ -7,28 +20,37 @@ window._ = _;
* CSRF token as a header based on the value of the "XSRF" token cookie. * CSRF token as a header based on the value of the "XSRF" token cookie.
*/ */
import axios from 'axios'; window.axios = require('axios');
window.axios = axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 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 * Echo exposes an expressive API for subscribing to channels and listening
* for events that are broadcast by Laravel. Echo and event broadcasting * for events that are broadcast by Laravel. Echo and event broadcasting
* allows your team to easily build robust real-time web applications. * allows your team to easily build robust real-time web applications.
*/ */
import Echo from 'laravel-echo'; // import Echo from 'laravel-echo'
import Pusher from 'pusher-js'; // window.Pusher = require('pusher-js');
window.Pusher = Pusher;
window.Echo = new Echo({ // window.Echo = new Echo({
broadcaster: 'pusher', // broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY, // key: process.env.MIX_PUSHER_APP_KEY,
wsHost: import.meta.env.VITE_PUSHER_HOST ? import.meta.env.VITE_PUSHER_HOST : `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`, // cluster: process.env.MIX_PUSHER_APP_CLUSTER,
wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80, // encrypted: true
wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443, // });
forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
enabledTransports: ['ws', 'wss'],
});

View File

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

View File

@@ -1,10 +0,0 @@
import 'https://js.pusher.com/7.2/pusher.min.js';
var pusher = new Pusher('93b3e504421787295454', {
cluster: 'us2'
});
var channel = pusher.subscribe('touchedItem');
channel.bind('RefreshPage', function(data) {
window.location.reload();
console.log(JSON.stringify(data));
});

View File

@@ -2,7 +2,15 @@
@section('content') @section('content')
@vite('resources/js/pusher.js') <script type="text/javascript">
setInterval(
function() {
if (!document.hasFocus() ) {
window.location.reload(true);
}
},
2*60000); //NOTE: period is passed in milliseconds
</script>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">

View File

@@ -1,7 +1,6 @@
@if ($item->used_by == \Auth::id()) @if ($item->used_by == \Auth::id())
<form action="/take" method="POST" class="form-inline"> <form action="/take" method="POST" class="form-inline">
<em id="itemPassedTime_{{$item->id}}" class="pr-sm-2 ml-auto">{{\Carbon\Carbon::parse($item->updated_at)->diffForHumans()}}</em> <em class="pr-sm-2 ml-auto">{{\Carbon\Carbon::parse($item->updated_at)->diffForHumans()}}</em>
<div hidden class="takenItemDate" id="{{$item->id}}">{{\Carbon\Carbon::parse($item->updated_at)->format('Y-m-d\TH:i:s.uP')}}</div>
<div class="w-100 d-xm-block d-sm-none"></div> <div class="w-100 d-xm-block d-sm-none"></div>
{{ csrf_field() }} {{ csrf_field() }}
@method('DELETE') @method('DELETE')
@@ -17,9 +16,8 @@
@if ($item->waiting_user_id && $item->waiting_user_id != \Auth::id()) @if ($item->waiting_user_id && $item->waiting_user_id != \Auth::id())
<strong>> {{str_limit($users[$item->waiting_user_id], 15, '...')}}</strong> <strong>> {{str_limit($users[$item->waiting_user_id], 15, '...')}}</strong>
@endif @endif
<small id="itemPassedTime_{{$item->id}}">({{$item->updated_at->diffForHumans()}})</small> <small>({{$item->updated_at->diffForHumans()}})</small>
</em> </em>
<div hidden class="takenItemDate" id="{{$item->id}}">{{$item->updated_at->format('Y-m-d\TH:i:s.uP')}}</div>
<div class="w-100 d-xm-block d-sm-none"></div> <div class="w-100 d-xm-block d-sm-none"></div>
{{ csrf_field() }} {{ csrf_field() }}
<input type="hidden" name="item" value="{{$item->id}}"> <input type="hidden" name="item" value="{{$item->id}}">

View File

@@ -11,7 +11,7 @@
<title>{{ config('app.name', 'Laravel') }} {{ isset($usedItems) && $usedItems > 0 ? "(${usedItems})" : '' }}</title> <title>{{ config('app.name', 'Laravel') }} {{ isset($usedItems) && $usedItems > 0 ? "(${usedItems})" : '' }}</title>
<!-- Scripts --> <!-- Scripts -->
@vite('resources/js/app.js') <script src="{{ asset('js/app.js') }}" defer></script>
<!-- Fonts --> <!-- Fonts -->
<link rel="dns-prefetch" href="https://fonts.gstatic.com"> <link rel="dns-prefetch" href="https://fonts.gstatic.com">
@@ -19,12 +19,9 @@
<!-- Styles --> <!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet"> <link href="{{ asset('css/app.css') }}" rel="stylesheet">
<link id="favicon" rel="icon" type="image/png" href="favicon.png" />
</head> </head>
<body> <body>
<div hidden id="usedItems">{{ isset($usedItems) && $usedItems > 0 ? $usedItems : '' }}</div>
<div id="app"> <div id="app">
<nav class="navbar navbar-expand-md navbar-light navbar-laravel"> <nav class="navbar navbar-expand-md navbar-light navbar-laravel">
<div class="container"> <div class="container">

View File

@@ -5,7 +5,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>Share It</title> <title>Share It</title>
<link id="favicon" rel="icon" type="image/png" href="favicon.png" />
<!-- Fonts --> <!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet" type="text/css"> <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet" type="text/css">

View File

@@ -14,8 +14,3 @@
Broadcast::channel('App.User.{id}', function ($user, $id) { Broadcast::channel('App.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id; return (int) $user->id === (int) $id;
}); });
Broadcast::channel('touchedItem', function ($user) {
return true;
/* return $user->id === Item::findOrNew($itemId)->users->find($user->id)->id; */
});

View File

@@ -1,2 +1 @@
echo "Homestead password is: vagrant" ssh homestead -t "cd code/Bruno\ Fontes/shareit; bash --login"
ssh homestead -t "cd shareit; bash --login"

View File

@@ -1,7 +1,6 @@
#!/bin/zsh #!/bin/zsh
export VAGRANT_CWD=/home/bruno/development/Homestead/ export VAGRANT_CWD=/home/bruno/development/Homestead/
vagrant up vagrant up
eval $DEV_BROWSER http://shareit.test \ #builtin cd ~/development/laravelHomestead && /usr/bin/vagrant up && builtin cd -
https://mailtrap.io/inboxes/455614/messages \ #~/Apps/firefox/firefox-bin http://shareit.test
https://dashboard.pusher.com/apps/1505830/console \ #~/Apps/firefox/firefox-bin https://mailtrap.io/inboxes/455614/messages
&

View File

@@ -1 +1 @@
ssh homestead -t 'cd shareit; /usr/local/bin/composer update; npm update; echo; echo -n "Press enter to exit..."; read' ssh homestead -t 'cd shareit; php7.3 /usr/local/bin/composer update; npm update; echo; echo -n "Press enter to exit..."; read'

28
vite.config.js vendored
View File

@@ -1,28 +0,0 @@
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
// import react from '@vitejs/plugin-react';
// import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [
laravel([
// 'resources/css/app.css',
'resources/js/app.js',
'resources/js/pusher.js',
]),
// react(),
// vue({
// template: {
// transformAssetUrls: {
// base: null,
// includeAbsolute: false,
// },
// },
// }),
],
resolve: {
alias: {
'@': '/resources/js'
}
}
});

15
webpack.mix.js vendored Normal file
View File

@@ -0,0 +1,15 @@
const mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');