Merge pull request #99 from inertiajs/upgrade
Upgrade Ping CRM to latest version of Inertia.js
This commit is contained in:
commit
57593efb25
|
@ -1,15 +1,32 @@
|
|||
module.exports = {
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:vue/recommended',
|
||||
],
|
||||
extends: ['eslint:recommended', 'plugin:vue/recommended'],
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020,
|
||||
sourceType: 'module',
|
||||
},
|
||||
env: {
|
||||
amd: true,
|
||||
browser: true,
|
||||
es6: true,
|
||||
},
|
||||
rules: {
|
||||
"indent": ['error', 2],
|
||||
'quotes': ['warn', 'single'],
|
||||
'semi': ['warn', 'never'],
|
||||
indent: ['error', 2],
|
||||
quotes: ['warn', 'single'],
|
||||
semi: ['warn', 'never'],
|
||||
'no-unused-vars': ['error', { vars: 'all', args: 'after-used', ignoreRestSiblings: true }],
|
||||
'comma-dangle': ['warn', 'always-multiline'],
|
||||
'vue/max-attributes-per-line': false,
|
||||
'vue/require-default-prop': false,
|
||||
'vue/singleline-html-element-content-newline': false,
|
||||
}
|
||||
'vue/max-attributes-per-line': 'off',
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/singleline-html-element-content-newline': 'off',
|
||||
'vue/html-self-closing': [
|
||||
'warn',
|
||||
{
|
||||
html: {
|
||||
void: 'always',
|
||||
normal: 'always',
|
||||
component: 'always',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"printWidth": 10000,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "all",
|
||||
"htmlWhitespaceSensitivity": "css"
|
||||
}
|
|
@ -20,7 +20,7 @@ class ContactsController extends Controller
|
|||
->orderByName()
|
||||
->filter(Request::only('search', 'trashed'))
|
||||
->paginate()
|
||||
->transform(function ($contact) {
|
||||
->through(function ($contact) {
|
||||
return [
|
||||
'id' => $contact->id,
|
||||
'name' => $contact->name,
|
||||
|
|
|
@ -18,7 +18,15 @@ class OrganizationsController extends Controller
|
|||
->orderBy('name')
|
||||
->filter(Request::only('search', 'trashed'))
|
||||
->paginate()
|
||||
->only('id', 'name', 'phone', 'city', 'deleted_at'),
|
||||
->through(function ($organization) {
|
||||
return [
|
||||
'id' => $organization->id,
|
||||
'name' => $organization->name,
|
||||
'phone' => $organization->phone,
|
||||
'city' => $organization->city,
|
||||
'deleted_at' => $organization->deleted_at,
|
||||
];
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ class HandleInertiaRequests extends Middleware
|
|||
'first_name' => $request->user()->first_name,
|
||||
'last_name' => $request->user()->last_name,
|
||||
'email' => $request->user()->email,
|
||||
'role' => $request->user()->role,
|
||||
'owner' => $request->user()->owner,
|
||||
'account' => [
|
||||
'id' => $request->user()->account->id,
|
||||
'name' => $request->user()->account->name,
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Pagination\UrlWindow;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use League\Glide\Server;
|
||||
|
@ -18,12 +14,6 @@ class AppServiceProvider extends ServiceProvider
|
|||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->registerGlide();
|
||||
$this->registerLengthAwarePaginator();
|
||||
}
|
||||
|
||||
protected function registerGlide()
|
||||
{
|
||||
$this->app->bind(Server::class, function ($app) {
|
||||
return Server::create([
|
||||
|
@ -35,75 +25,13 @@ class AppServiceProvider extends ServiceProvider
|
|||
});
|
||||
}
|
||||
|
||||
protected function registerLengthAwarePaginator()
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->app->bind(LengthAwarePaginator::class, function ($app, $values) {
|
||||
return new class(...array_values($values)) extends LengthAwarePaginator {
|
||||
public function only(...$attributes)
|
||||
{
|
||||
return $this->transform(function ($item) use ($attributes) {
|
||||
return $item->only($attributes);
|
||||
});
|
||||
}
|
||||
|
||||
public function transform($callback)
|
||||
{
|
||||
$this->items->transform($callback);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'data' => $this->items->toArray(),
|
||||
'links' => $this->links(),
|
||||
];
|
||||
}
|
||||
|
||||
public function links($view = null, $data = [])
|
||||
{
|
||||
$this->appends(Request::all());
|
||||
|
||||
$window = UrlWindow::make($this);
|
||||
|
||||
$elements = array_filter([
|
||||
$window['first'],
|
||||
is_array($window['slider']) ? '...' : null,
|
||||
$window['slider'],
|
||||
is_array($window['last']) ? '...' : null,
|
||||
$window['last'],
|
||||
]);
|
||||
|
||||
return Collection::make($elements)->flatMap(function ($item) {
|
||||
if (is_array($item)) {
|
||||
return Collection::make($item)->map(function ($url, $page) {
|
||||
return [
|
||||
'url' => $url,
|
||||
'label' => $page,
|
||||
'active' => $this->currentPage() === $page,
|
||||
];
|
||||
});
|
||||
} else {
|
||||
return [
|
||||
[
|
||||
'url' => null,
|
||||
'label' => '...',
|
||||
'active' => false,
|
||||
],
|
||||
];
|
||||
}
|
||||
})->prepend([
|
||||
'url' => $this->previousPageUrl(),
|
||||
'label' => 'Previous',
|
||||
'active' => false,
|
||||
])->push([
|
||||
'url' => $this->nextPageUrl(),
|
||||
'label' => 'Next',
|
||||
'active' => false,
|
||||
]);
|
||||
}
|
||||
};
|
||||
});
|
||||
//
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.3.0",
|
||||
"php": "^7.3|^8.0",
|
||||
"ext-exif": "*",
|
||||
"ext-gd": "*",
|
||||
"facade/ignition": "^2.3.6",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
34
package.json
34
package.json
|
@ -2,31 +2,31 @@
|
|||
"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": "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",
|
||||
"development": "mix",
|
||||
"watch": "mix watch",
|
||||
"watch-poll": "mix watch -- --watch-options-poll=1000",
|
||||
"hot": "mix watch --hot",
|
||||
"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": "mix --production"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fullhuman/postcss-purgecss": "^1.3.0",
|
||||
"@inertiajs/inertia": "^0.3.1",
|
||||
"@inertiajs/inertia-vue": "^0.2.3",
|
||||
"@inertiajs/progress": "^0.1.0",
|
||||
"cross-env": "^5.2.1",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-plugin-vue": "^5.2.3",
|
||||
"laravel-mix": "^5.0.1",
|
||||
"lodash": "^4.17.15",
|
||||
"@inertiajs/inertia": "^0.8.5",
|
||||
"@inertiajs/inertia-vue": "^0.5.5",
|
||||
"@inertiajs/progress": "^0.2.4",
|
||||
"autoprefixer": "^10.2.4",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-vue": "^7.5.0",
|
||||
"laravel-mix": "^6.0.6",
|
||||
"lodash": "^4.17.21",
|
||||
"popper.js": "^1.16.0",
|
||||
"portal-vue": "^1.5.1",
|
||||
"postcss": "^8.2.6",
|
||||
"postcss-import": "^12.0.1",
|
||||
"postcss-nesting": "^7.0.1",
|
||||
"resolve-url-loader": "^2.3.2",
|
||||
"tailwindcss": "^1.2.0-canary.5",
|
||||
"tailwindcss": "^2.0.3",
|
||||
"vue": "^2.6.11",
|
||||
"vue-loader": "^15.9.6",
|
||||
"vue-meta": "^2.3.1",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
"vue-template-compiler": "^2.6.12"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* Reset */
|
||||
@import "tailwindcss/base";
|
||||
@import "reset";
|
||||
@import 'tailwindcss/base';
|
||||
@import 'reset';
|
||||
|
||||
/* Components */
|
||||
@import "tailwindcss/components";
|
||||
@import "buttons";
|
||||
@import "form";
|
||||
@import 'tailwindcss/components';
|
||||
@import 'buttons';
|
||||
@import 'form';
|
||||
|
||||
/* Utilities */
|
||||
@import "tailwindcss/utilities";
|
||||
@import 'tailwindcss/utilities';
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
.btn-indigo {
|
||||
@apply px-6 py-3 rounded bg-indigo-600 text-white text-sm font-bold whitespace-no-wrap;
|
||||
|
||||
&:hover, &:focus { @apply bg-orange-500 }
|
||||
@apply px-6 py-3 rounded bg-indigo-600 text-white text-sm leading-4 font-bold whitespace-nowrap hover:bg-orange-400 focus:bg-orange-400;
|
||||
}
|
||||
|
||||
.btn-spinner,
|
||||
|
@ -15,15 +13,19 @@
|
|||
font-size: 10px;
|
||||
position: relative;
|
||||
text-indent: -9999em;
|
||||
border-top: .2em solid white;
|
||||
border-right: .2em solid white;
|
||||
border-bottom: .2em solid white;
|
||||
border-left: .2em solid transparent;
|
||||
border-top: 0.2em solid white;
|
||||
border-right: 0.2em solid white;
|
||||
border-bottom: 0.2em solid white;
|
||||
border-left: 0.2em solid transparent;
|
||||
transform: translateZ(0);
|
||||
animation: spinning 1s infinite linear;
|
||||
}
|
||||
|
||||
@keyframes spinning {
|
||||
0% { transform: rotate(0deg) }
|
||||
100% { transform: rotate(360deg) }
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,19 @@
|
|||
.form-label {
|
||||
@apply .mb-2 .block .text-gray-700 .select-none;
|
||||
@apply mb-2 block text-gray-700 select-none;
|
||||
}
|
||||
|
||||
.form-input,
|
||||
.form-textarea,
|
||||
.form-select {
|
||||
@apply .p-2 .leading-normal .block .w-full .border .text-gray-700 .bg-white .font-sans .rounded .text-left .appearance-none .relative;
|
||||
|
||||
&:focus,
|
||||
&.focus {
|
||||
@apply .border-indigo-500;
|
||||
box-shadow: 0 0 0 1px theme('colors.indigo.500');
|
||||
}
|
||||
@apply p-2 leading-normal block w-full border text-gray-700 bg-white font-sans rounded text-left appearance-none relative focus:border-indigo-400 focus:ring;
|
||||
|
||||
&::placeholder {
|
||||
@apply .text-gray-500 .opacity-100;
|
||||
@apply text-gray-500 opacity-100;
|
||||
}
|
||||
}
|
||||
|
||||
.form-select {
|
||||
@apply .pr-6;
|
||||
@apply pr-6;
|
||||
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAQCAYAAAAMJL+VAAAABGdBTUEAALGPC/xhBQAAAQtJREFUOBG1lEEOgjAQRalbGj2OG9caOACn4ALGtfEuHACiazceR1PWOH/CNA3aMiTaBDpt/7zPdBKy7M/DCL9pGkvxxVp7KsvyJftL5rZt1865M+Ucq6pyyF3hNcI7Cuu+728QYn/JQA5yKaempxuZmQngOwEaYx55nu+1lQh8GIatMGi+01NwBcEmhxBqK4nAPZJ78K0KKFAJmR3oPp8+Iwgob0Oa6+TLoeCvRx+mTUYf/FVBGTPRwDkfLxnaSrRwcH0FWhNOmrkWYbE2XEicqgSa1J0LQ+aPCuQgZiLnwewbGuz5MGoAhcIkCQcjaTBjMgtXGURMVHC1wcQEy0J+Zlj8bKAnY1/UzDe2dbAVqfXn6wAAAABJRU5ErkJggg==');
|
||||
background-size: 0.7rem;
|
||||
|
@ -27,20 +21,16 @@
|
|||
background-position: right 0.7rem center;
|
||||
|
||||
&::-ms-expand {
|
||||
@apply .opacity-0;
|
||||
@apply opacity-0;
|
||||
}
|
||||
}
|
||||
|
||||
.form-error {
|
||||
@apply .text-red-700 .mt-2 .text-sm;
|
||||
}
|
||||
|
||||
.form-input.error,
|
||||
.form-textarea.error,
|
||||
.form-select.error {
|
||||
@apply .border-red-600;
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 1px theme('colors.red.600');
|
||||
}
|
||||
@apply border-red-500 focus:ring focus:ring-red-200;
|
||||
}
|
||||
|
||||
.form-error {
|
||||
@apply text-red-700 mt-2 text-sm;
|
||||
}
|
||||
|
|
|
@ -2,20 +2,20 @@
|
|||
<div class="p-6 bg-indigo-800 min-h-screen flex justify-center items-center">
|
||||
<div class="w-full max-w-md">
|
||||
<logo class="block mx-auto w-full max-w-xs fill-white" height="50" />
|
||||
<form class="mt-8 bg-white rounded-lg shadow-xl overflow-hidden" @submit.prevent="submit">
|
||||
<form class="mt-8 bg-white rounded-lg shadow-xl overflow-hidden" @submit.prevent="login">
|
||||
<div class="px-10 py-12">
|
||||
<h1 class="text-center font-bold text-3xl">Welcome Back!</h1>
|
||||
<div class="mx-auto mt-6 w-24 border-b-2" />
|
||||
<text-input v-model="form.email" :error="errors.email" class="mt-10" label="Email" type="email" autofocus autocapitalize="off" />
|
||||
<text-input v-model="form.password" class="mt-6" label="Password" type="password" />
|
||||
<text-input v-model="form.email" :error="form.errors.email" class="mt-10" label="Email" type="email" autofocus autocapitalize="off" />
|
||||
<text-input v-model="form.password" :error="form.errors.password" class="mt-6" label="Password" type="password" />
|
||||
<label class="mt-6 select-none flex items-center" for="remember">
|
||||
<input id="remember" v-model="form.remember" class="mr-1" type="checkbox">
|
||||
<input id="remember" v-model="form.remember" class="mr-1" type="checkbox" />
|
||||
<span class="text-sm">Remember Me</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="px-10 py-4 bg-gray-100 border-t border-gray-200 flex justify-between items-center">
|
||||
<div class="px-10 py-4 bg-gray-100 border-t border-gray-100 flex justify-between items-center">
|
||||
<a class="hover:underline" tabindex="-1" href="#reset-password">Forget password?</a>
|
||||
<loading-button :loading="sending" class="btn-indigo" type="submit">Login</loading-button>
|
||||
<loading-button :loading="form.processing" class="btn-indigo" type="submit">Login</loading-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -23,9 +23,9 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import LoadingButton from '@/Shared/LoadingButton'
|
||||
import Logo from '@/Shared/Logo'
|
||||
import TextInput from '@/Shared/TextInput'
|
||||
import LoadingButton from '@/Shared/LoadingButton'
|
||||
|
||||
export default {
|
||||
metaInfo: { title: 'Login' },
|
||||
|
@ -34,31 +34,23 @@ export default {
|
|||
Logo,
|
||||
TextInput,
|
||||
},
|
||||
props: {
|
||||
errors: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
sending: false,
|
||||
form: {
|
||||
form: this.$inertia.form({
|
||||
email: 'johndoe@example.com',
|
||||
password: 'secret',
|
||||
remember: null,
|
||||
},
|
||||
remember: false,
|
||||
}),
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
const data = {
|
||||
email: this.form.email,
|
||||
password: this.form.password,
|
||||
remember: this.form.remember,
|
||||
}
|
||||
|
||||
this.$inertia.post(this.route('login.attempt'), data, {
|
||||
onStart: () => this.sending = true,
|
||||
onFinish: () => this.sending = false,
|
||||
})
|
||||
login() {
|
||||
this.form
|
||||
.transform(data => ({
|
||||
...data,
|
||||
remember: data.remember ? 'on' : '',
|
||||
}))
|
||||
.post(this.route('login.attempt'))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -4,29 +4,29 @@
|
|||
<inertia-link class="text-indigo-400 hover:text-indigo-600" :href="route('contacts')">Contacts</inertia-link>
|
||||
<span class="text-indigo-400 font-medium">/</span> Create
|
||||
</h1>
|
||||
<div class="bg-white rounded shadow overflow-hidden max-w-3xl">
|
||||
<form @submit.prevent="submit">
|
||||
<div class="bg-white rounded-md shadow overflow-hidden max-w-3xl">
|
||||
<form @submit.prevent="store">
|
||||
<div class="p-8 -mr-6 -mb-8 flex flex-wrap">
|
||||
<text-input v-model="form.first_name" :error="errors.first_name" class="pr-6 pb-8 w-full lg:w-1/2" label="First name" />
|
||||
<text-input v-model="form.last_name" :error="errors.last_name" class="pr-6 pb-8 w-full lg:w-1/2" label="Last name" />
|
||||
<select-input v-model="form.organization_id" :error="errors.organization_id" class="pr-6 pb-8 w-full lg:w-1/2" label="Organization">
|
||||
<text-input v-model="form.first_name" :error="form.errors.first_name" class="pr-6 pb-8 w-full lg:w-1/2" label="First name" />
|
||||
<text-input v-model="form.last_name" :error="form.errors.last_name" class="pr-6 pb-8 w-full lg:w-1/2" label="Last name" />
|
||||
<select-input v-model="form.organization_id" :error="form.errors.organization_id" class="pr-6 pb-8 w-full lg:w-1/2" label="Organization">
|
||||
<option :value="null" />
|
||||
<option v-for="organization in organizations" :key="organization.id" :value="organization.id">{{ organization.name }}</option>
|
||||
</select-input>
|
||||
<text-input v-model="form.email" :error="errors.email" class="pr-6 pb-8 w-full lg:w-1/2" label="Email" />
|
||||
<text-input v-model="form.phone" :error="errors.phone" class="pr-6 pb-8 w-full lg:w-1/2" label="Phone" />
|
||||
<text-input v-model="form.address" :error="errors.address" class="pr-6 pb-8 w-full lg:w-1/2" label="Address" />
|
||||
<text-input v-model="form.city" :error="errors.city" class="pr-6 pb-8 w-full lg:w-1/2" label="City" />
|
||||
<text-input v-model="form.region" :error="errors.region" class="pr-6 pb-8 w-full lg:w-1/2" label="Province/State" />
|
||||
<select-input v-model="form.country" :error="errors.country" class="pr-6 pb-8 w-full lg:w-1/2" label="Country">
|
||||
<text-input v-model="form.email" :error="form.errors.email" class="pr-6 pb-8 w-full lg:w-1/2" label="Email" />
|
||||
<text-input v-model="form.phone" :error="form.errors.phone" class="pr-6 pb-8 w-full lg:w-1/2" label="Phone" />
|
||||
<text-input v-model="form.address" :error="form.errors.address" class="pr-6 pb-8 w-full lg:w-1/2" label="Address" />
|
||||
<text-input v-model="form.city" :error="form.errors.city" class="pr-6 pb-8 w-full lg:w-1/2" label="City" />
|
||||
<text-input v-model="form.region" :error="form.errors.region" class="pr-6 pb-8 w-full lg:w-1/2" label="Province/State" />
|
||||
<select-input v-model="form.country" :error="form.errors.country" class="pr-6 pb-8 w-full lg:w-1/2" label="Country">
|
||||
<option :value="null" />
|
||||
<option value="CA">Canada</option>
|
||||
<option value="US">United States</option>
|
||||
</select-input>
|
||||
<text-input v-model="form.postal_code" :error="errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
||||
<text-input v-model="form.postal_code" :error="form.errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
||||
</div>
|
||||
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex justify-end items-center">
|
||||
<loading-button :loading="sending" class="btn-indigo" type="submit">Create Contact</loading-button>
|
||||
<div class="px-8 py-4 bg-gray-50 border-t border-gray-100 flex justify-end items-center">
|
||||
<loading-button :loading="form.processing" class="btn-indigo" type="submit">Create Contact</loading-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -35,27 +35,25 @@
|
|||
|
||||
<script>
|
||||
import Layout from '@/Shared/Layout'
|
||||
import LoadingButton from '@/Shared/LoadingButton'
|
||||
import SelectInput from '@/Shared/SelectInput'
|
||||
import TextInput from '@/Shared/TextInput'
|
||||
import SelectInput from '@/Shared/SelectInput'
|
||||
import LoadingButton from '@/Shared/LoadingButton'
|
||||
|
||||
export default {
|
||||
metaInfo: { title: 'Create Contact' },
|
||||
layout: Layout,
|
||||
components: {
|
||||
LoadingButton,
|
||||
SelectInput,
|
||||
TextInput,
|
||||
},
|
||||
layout: Layout,
|
||||
props: {
|
||||
errors: Object,
|
||||
organizations: Array,
|
||||
},
|
||||
remember: 'form',
|
||||
data() {
|
||||
return {
|
||||
sending: false,
|
||||
form: {
|
||||
form: this.$inertia.form({
|
||||
first_name: null,
|
||||
last_name: null,
|
||||
organization_id: null,
|
||||
|
@ -66,15 +64,12 @@ export default {
|
|||
region: null,
|
||||
country: null,
|
||||
postal_code: null,
|
||||
},
|
||||
}),
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
this.$inertia.post(this.route('contacts.store'), this.form, {
|
||||
onStart: () => this.sending = true,
|
||||
onFinish: () => this.sending = false,
|
||||
})
|
||||
store() {
|
||||
this.form.post(this.route('contacts.store'))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -8,30 +8,30 @@
|
|||
<trashed-message v-if="contact.deleted_at" class="mb-6" @restore="restore">
|
||||
This contact has been deleted.
|
||||
</trashed-message>
|
||||
<div class="bg-white rounded shadow overflow-hidden max-w-3xl">
|
||||
<form @submit.prevent="submit">
|
||||
<div class="bg-white rounded-md shadow overflow-hidden max-w-3xl">
|
||||
<form @submit.prevent="update">
|
||||
<div class="p-8 -mr-6 -mb-8 flex flex-wrap">
|
||||
<text-input v-model="form.first_name" :error="errors.first_name" class="pr-6 pb-8 w-full lg:w-1/2" label="First name" />
|
||||
<text-input v-model="form.last_name" :error="errors.last_name" class="pr-6 pb-8 w-full lg:w-1/2" label="Last name" />
|
||||
<select-input v-model="form.organization_id" :error="errors.organization_id" class="pr-6 pb-8 w-full lg:w-1/2" label="Organization">
|
||||
<text-input v-model="form.first_name" :error="form.errors.first_name" class="pr-6 pb-8 w-full lg:w-1/2" label="First name" />
|
||||
<text-input v-model="form.last_name" :error="form.errors.last_name" class="pr-6 pb-8 w-full lg:w-1/2" label="Last name" />
|
||||
<select-input v-model="form.organization_id" :error="form.errors.organization_id" class="pr-6 pb-8 w-full lg:w-1/2" label="Organization">
|
||||
<option :value="null" />
|
||||
<option v-for="organization in organizations" :key="organization.id" :value="organization.id">{{ organization.name }}</option>
|
||||
</select-input>
|
||||
<text-input v-model="form.email" :error="errors.email" class="pr-6 pb-8 w-full lg:w-1/2" label="Email" />
|
||||
<text-input v-model="form.phone" :error="errors.phone" class="pr-6 pb-8 w-full lg:w-1/2" label="Phone" />
|
||||
<text-input v-model="form.address" :error="errors.address" class="pr-6 pb-8 w-full lg:w-1/2" label="Address" />
|
||||
<text-input v-model="form.city" :error="errors.city" class="pr-6 pb-8 w-full lg:w-1/2" label="City" />
|
||||
<text-input v-model="form.region" :error="errors.region" class="pr-6 pb-8 w-full lg:w-1/2" label="Province/State" />
|
||||
<select-input v-model="form.country" :error="errors.country" class="pr-6 pb-8 w-full lg:w-1/2" label="Country">
|
||||
<text-input v-model="form.email" :error="form.errors.email" class="pr-6 pb-8 w-full lg:w-1/2" label="Email" />
|
||||
<text-input v-model="form.phone" :error="form.errors.phone" class="pr-6 pb-8 w-full lg:w-1/2" label="Phone" />
|
||||
<text-input v-model="form.address" :error="form.errors.address" class="pr-6 pb-8 w-full lg:w-1/2" label="Address" />
|
||||
<text-input v-model="form.city" :error="form.errors.city" class="pr-6 pb-8 w-full lg:w-1/2" label="City" />
|
||||
<text-input v-model="form.region" :error="form.errors.region" class="pr-6 pb-8 w-full lg:w-1/2" label="Province/State" />
|
||||
<select-input v-model="form.country" :error="form.errors.country" class="pr-6 pb-8 w-full lg:w-1/2" label="Country">
|
||||
<option :value="null" />
|
||||
<option value="CA">Canada</option>
|
||||
<option value="US">United States</option>
|
||||
</select-input>
|
||||
<text-input v-model="form.postal_code" :error="errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
||||
<text-input v-model="form.postal_code" :error="form.errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
||||
</div>
|
||||
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex items-center">
|
||||
<div class="px-8 py-4 bg-gray-50 border-t border-gray-100 flex items-center">
|
||||
<button v-if="!contact.deleted_at" class="text-red-600 hover:underline" tabindex="-1" type="button" @click="destroy">Delete Contact</button>
|
||||
<loading-button :loading="sending" class="btn-indigo ml-auto" type="submit">Update Contact</loading-button>
|
||||
<loading-button :loading="form.processing" class="btn-indigo ml-auto" type="submit">Update Contact</loading-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -40,9 +40,9 @@
|
|||
|
||||
<script>
|
||||
import Layout from '@/Shared/Layout'
|
||||
import LoadingButton from '@/Shared/LoadingButton'
|
||||
import SelectInput from '@/Shared/SelectInput'
|
||||
import TextInput from '@/Shared/TextInput'
|
||||
import SelectInput from '@/Shared/SelectInput'
|
||||
import LoadingButton from '@/Shared/LoadingButton'
|
||||
import TrashedMessage from '@/Shared/TrashedMessage'
|
||||
|
||||
export default {
|
||||
|
@ -51,13 +51,13 @@ export default {
|
|||
title: `${this.form.first_name} ${this.form.last_name}`,
|
||||
}
|
||||
},
|
||||
layout: Layout,
|
||||
components: {
|
||||
LoadingButton,
|
||||
SelectInput,
|
||||
TextInput,
|
||||
TrashedMessage,
|
||||
},
|
||||
layout: Layout,
|
||||
props: {
|
||||
errors: Object,
|
||||
contact: Object,
|
||||
|
@ -66,8 +66,7 @@ export default {
|
|||
remember: 'form',
|
||||
data() {
|
||||
return {
|
||||
sending: false,
|
||||
form: {
|
||||
form: this.$inertia.form({
|
||||
first_name: this.contact.first_name,
|
||||
last_name: this.contact.last_name,
|
||||
organization_id: this.contact.organization_id,
|
||||
|
@ -78,15 +77,12 @@ export default {
|
|||
region: this.contact.region,
|
||||
country: this.contact.country,
|
||||
postal_code: this.contact.postal_code,
|
||||
},
|
||||
}),
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
this.$inertia.put(this.route('contacts.update', this.contact.id), this.form, {
|
||||
onStart: () => this.sending = true,
|
||||
onFinish: () => this.sending = false,
|
||||
})
|
||||
update() {
|
||||
this.form.put(this.route('contacts.update', this.contact.id))
|
||||
},
|
||||
destroy() {
|
||||
if (confirm('Are you sure you want to delete this contact?')) {
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
<span class="hidden md:inline">Contact</span>
|
||||
</inertia-link>
|
||||
</div>
|
||||
<div class="bg-white rounded shadow overflow-x-auto">
|
||||
<table class="w-full whitespace-no-wrap">
|
||||
<div class="bg-white rounded-md shadow overflow-x-auto">
|
||||
<table class="w-full whitespace-nowrap">
|
||||
<tr class="text-left font-bold">
|
||||
<th class="px-6 pt-6 pb-4">Name</th>
|
||||
<th class="px-6 pt-6 pb-4">Organization</th>
|
||||
|
@ -58,27 +58,27 @@
|
|||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<pagination :links="contacts.links" />
|
||||
<pagination class="mt-6" :links="contacts.links" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Icon from '@/Shared/Icon'
|
||||
import pickBy from 'lodash/pickBy'
|
||||
import Layout from '@/Shared/Layout'
|
||||
import throttle from 'lodash/throttle'
|
||||
import mapValues from 'lodash/mapValues'
|
||||
import Pagination from '@/Shared/Pagination'
|
||||
import pickBy from 'lodash/pickBy'
|
||||
import SearchFilter from '@/Shared/SearchFilter'
|
||||
import throttle from 'lodash/throttle'
|
||||
|
||||
export default {
|
||||
metaInfo: { title: 'Contacts' },
|
||||
layout: Layout,
|
||||
components: {
|
||||
Icon,
|
||||
Pagination,
|
||||
SearchFilter,
|
||||
},
|
||||
layout: Layout,
|
||||
props: {
|
||||
contacts: Object,
|
||||
filters: Object,
|
||||
|
|
|
@ -4,24 +4,24 @@
|
|||
<inertia-link class="text-indigo-400 hover:text-indigo-600" :href="route('organizations')">Organizations</inertia-link>
|
||||
<span class="text-indigo-400 font-medium">/</span> Create
|
||||
</h1>
|
||||
<div class="bg-white rounded shadow overflow-hidden max-w-3xl">
|
||||
<form @submit.prevent="submit">
|
||||
<div class="bg-white rounded-md shadow overflow-hidden max-w-3xl">
|
||||
<form @submit.prevent="store">
|
||||
<div class="p-8 -mr-6 -mb-8 flex flex-wrap">
|
||||
<text-input v-model="form.name" :error="errors.name" class="pr-6 pb-8 w-full lg:w-1/2" label="Name" />
|
||||
<text-input v-model="form.email" :error="errors.email" class="pr-6 pb-8 w-full lg:w-1/2" label="Email" />
|
||||
<text-input v-model="form.phone" :error="errors.phone" class="pr-6 pb-8 w-full lg:w-1/2" label="Phone" />
|
||||
<text-input v-model="form.address" :error="errors.address" class="pr-6 pb-8 w-full lg:w-1/2" label="Address" />
|
||||
<text-input v-model="form.city" :error="errors.city" class="pr-6 pb-8 w-full lg:w-1/2" label="City" />
|
||||
<text-input v-model="form.region" :error="errors.region" class="pr-6 pb-8 w-full lg:w-1/2" label="Province/State" />
|
||||
<select-input v-model="form.country" :error="errors.country" class="pr-6 pb-8 w-full lg:w-1/2" label="Country">
|
||||
<text-input v-model="form.name" :error="form.errors.name" class="pr-6 pb-8 w-full lg:w-1/2" label="Name" />
|
||||
<text-input v-model="form.email" :error="form.errors.email" class="pr-6 pb-8 w-full lg:w-1/2" label="Email" />
|
||||
<text-input v-model="form.phone" :error="form.errors.phone" class="pr-6 pb-8 w-full lg:w-1/2" label="Phone" />
|
||||
<text-input v-model="form.address" :error="form.errors.address" class="pr-6 pb-8 w-full lg:w-1/2" label="Address" />
|
||||
<text-input v-model="form.city" :error="form.errors.city" class="pr-6 pb-8 w-full lg:w-1/2" label="City" />
|
||||
<text-input v-model="form.region" :error="form.errors.region" class="pr-6 pb-8 w-full lg:w-1/2" label="Province/State" />
|
||||
<select-input v-model="form.country" :error="form.errors.country" class="pr-6 pb-8 w-full lg:w-1/2" label="Country">
|
||||
<option :value="null" />
|
||||
<option value="CA">Canada</option>
|
||||
<option value="US">United States</option>
|
||||
</select-input>
|
||||
<text-input v-model="form.postal_code" :error="errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
||||
<text-input v-model="form.postal_code" :error="form.errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
||||
</div>
|
||||
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex justify-end items-center">
|
||||
<loading-button :loading="sending" class="btn-indigo" type="submit">Create Organization</loading-button>
|
||||
<div class="px-8 py-4 bg-gray-50 border-t border-gray-100 flex justify-end items-center">
|
||||
<loading-button :loading="form.processing" class="btn-indigo" type="submit">Create Organization</loading-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -30,26 +30,22 @@
|
|||
|
||||
<script>
|
||||
import Layout from '@/Shared/Layout'
|
||||
import LoadingButton from '@/Shared/LoadingButton'
|
||||
import SelectInput from '@/Shared/SelectInput'
|
||||
import TextInput from '@/Shared/TextInput'
|
||||
import SelectInput from '@/Shared/SelectInput'
|
||||
import LoadingButton from '@/Shared/LoadingButton'
|
||||
|
||||
export default {
|
||||
metaInfo: { title: 'Create Organization' },
|
||||
layout: Layout,
|
||||
components: {
|
||||
LoadingButton,
|
||||
SelectInput,
|
||||
TextInput,
|
||||
},
|
||||
props: {
|
||||
errors: Object,
|
||||
},
|
||||
layout: Layout,
|
||||
remember: 'form',
|
||||
data() {
|
||||
return {
|
||||
sending: false,
|
||||
form: {
|
||||
form: this.$inertia.form({
|
||||
name: null,
|
||||
email: null,
|
||||
phone: null,
|
||||
|
@ -58,15 +54,12 @@ export default {
|
|||
region: null,
|
||||
country: null,
|
||||
postal_code: null,
|
||||
},
|
||||
}),
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
this.$inertia.post(this.route('organizations.store'), this.form, {
|
||||
onStart: () => this.sending = true,
|
||||
onFinish: () => this.sending = false,
|
||||
})
|
||||
store() {
|
||||
this.form.post(this.route('organizations.store'))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -8,31 +8,31 @@
|
|||
<trashed-message v-if="organization.deleted_at" class="mb-6" @restore="restore">
|
||||
This organization has been deleted.
|
||||
</trashed-message>
|
||||
<div class="bg-white rounded shadow overflow-hidden max-w-3xl">
|
||||
<form @submit.prevent="submit">
|
||||
<div class="bg-white rounded-md shadow overflow-hidden max-w-3xl">
|
||||
<form @submit.prevent="update">
|
||||
<div class="p-8 -mr-6 -mb-8 flex flex-wrap">
|
||||
<text-input v-model="form.name" :error="errors.name" class="pr-6 pb-8 w-full lg:w-1/2" label="Name" />
|
||||
<text-input v-model="form.email" :error="errors.email" class="pr-6 pb-8 w-full lg:w-1/2" label="Email" />
|
||||
<text-input v-model="form.phone" :error="errors.phone" class="pr-6 pb-8 w-full lg:w-1/2" label="Phone" />
|
||||
<text-input v-model="form.address" :error="errors.address" class="pr-6 pb-8 w-full lg:w-1/2" label="Address" />
|
||||
<text-input v-model="form.city" :error="errors.city" class="pr-6 pb-8 w-full lg:w-1/2" label="City" />
|
||||
<text-input v-model="form.region" :error="errors.region" class="pr-6 pb-8 w-full lg:w-1/2" label="Province/State" />
|
||||
<select-input v-model="form.country" :error="errors.country" class="pr-6 pb-8 w-full lg:w-1/2" label="Country">
|
||||
<text-input v-model="form.name" :error="form.errors.name" class="pr-6 pb-8 w-full lg:w-1/2" label="Name" />
|
||||
<text-input v-model="form.email" :error="form.errors.email" class="pr-6 pb-8 w-full lg:w-1/2" label="Email" />
|
||||
<text-input v-model="form.phone" :error="form.errors.phone" class="pr-6 pb-8 w-full lg:w-1/2" label="Phone" />
|
||||
<text-input v-model="form.address" :error="form.errors.address" class="pr-6 pb-8 w-full lg:w-1/2" label="Address" />
|
||||
<text-input v-model="form.city" :error="form.errors.city" class="pr-6 pb-8 w-full lg:w-1/2" label="City" />
|
||||
<text-input v-model="form.region" :error="form.errors.region" class="pr-6 pb-8 w-full lg:w-1/2" label="Province/State" />
|
||||
<select-input v-model="form.country" :error="form.errors.country" class="pr-6 pb-8 w-full lg:w-1/2" label="Country">
|
||||
<option :value="null" />
|
||||
<option value="CA">Canada</option>
|
||||
<option value="US">United States</option>
|
||||
</select-input>
|
||||
<text-input v-model="form.postal_code" :error="errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
||||
<text-input v-model="form.postal_code" :error="form.errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
||||
</div>
|
||||
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex items-center">
|
||||
<div class="px-8 py-4 bg-gray-50 border-t border-gray-100 flex items-center">
|
||||
<button v-if="!organization.deleted_at" class="text-red-600 hover:underline" tabindex="-1" type="button" @click="destroy">Delete Organization</button>
|
||||
<loading-button :loading="sending" class="btn-indigo ml-auto" type="submit">Update Organization</loading-button>
|
||||
<loading-button :loading="form.processing" class="btn-indigo ml-auto" type="submit">Update Organization</loading-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<h2 class="mt-12 font-bold text-2xl">Contacts</h2>
|
||||
<div class="mt-6 bg-white rounded shadow overflow-x-auto">
|
||||
<table class="w-full whitespace-no-wrap">
|
||||
<table class="w-full whitespace-nowrap">
|
||||
<tr class="text-left font-bold">
|
||||
<th class="px-6 pt-6 pb-4">Name</th>
|
||||
<th class="px-6 pt-6 pb-4">City</th>
|
||||
|
@ -72,16 +72,15 @@
|
|||
<script>
|
||||
import Icon from '@/Shared/Icon'
|
||||
import Layout from '@/Shared/Layout'
|
||||
import LoadingButton from '@/Shared/LoadingButton'
|
||||
import SelectInput from '@/Shared/SelectInput'
|
||||
import TextInput from '@/Shared/TextInput'
|
||||
import SelectInput from '@/Shared/SelectInput'
|
||||
import LoadingButton from '@/Shared/LoadingButton'
|
||||
import TrashedMessage from '@/Shared/TrashedMessage'
|
||||
|
||||
export default {
|
||||
metaInfo() {
|
||||
return { title: this.form.name }
|
||||
},
|
||||
layout: Layout,
|
||||
components: {
|
||||
Icon,
|
||||
LoadingButton,
|
||||
|
@ -89,15 +88,14 @@ export default {
|
|||
TextInput,
|
||||
TrashedMessage,
|
||||
},
|
||||
layout: Layout,
|
||||
props: {
|
||||
errors: Object,
|
||||
organization: Object,
|
||||
},
|
||||
remember: 'form',
|
||||
data() {
|
||||
return {
|
||||
sending: false,
|
||||
form: {
|
||||
form: this.$inertia.form({
|
||||
name: this.organization.name,
|
||||
email: this.organization.email,
|
||||
phone: this.organization.phone,
|
||||
|
@ -106,15 +104,12 @@ export default {
|
|||
region: this.organization.region,
|
||||
country: this.organization.country,
|
||||
postal_code: this.organization.postal_code,
|
||||
},
|
||||
}),
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
this.$inertia.put(this.route('organizations.update', this.organization.id), this.form, {
|
||||
onStart: () => this.sending = true,
|
||||
onFinish: () => this.sending = false,
|
||||
})
|
||||
update() {
|
||||
this.form.put(this.route('organizations.update', this.organization.id))
|
||||
},
|
||||
destroy() {
|
||||
if (confirm('Are you sure you want to delete this organization?')) {
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
<span class="hidden md:inline">Organization</span>
|
||||
</inertia-link>
|
||||
</div>
|
||||
<div class="bg-white rounded shadow overflow-x-auto">
|
||||
<table class="w-full whitespace-no-wrap">
|
||||
<div class="bg-white rounded-md shadow overflow-x-auto">
|
||||
<table class="w-full whitespace-nowrap">
|
||||
<tr class="text-left font-bold">
|
||||
<th class="px-6 pt-6 pb-4">Name</th>
|
||||
<th class="px-6 pt-6 pb-4">City</th>
|
||||
|
@ -50,27 +50,27 @@
|
|||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<pagination :links="organizations.links" />
|
||||
<pagination class="mt-6" :links="organizations.links" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Icon from '@/Shared/Icon'
|
||||
import pickBy from 'lodash/pickBy'
|
||||
import Layout from '@/Shared/Layout'
|
||||
import throttle from 'lodash/throttle'
|
||||
import mapValues from 'lodash/mapValues'
|
||||
import Pagination from '@/Shared/Pagination'
|
||||
import pickBy from 'lodash/pickBy'
|
||||
import SearchFilter from '@/Shared/SearchFilter'
|
||||
import throttle from 'lodash/throttle'
|
||||
|
||||
export default {
|
||||
metaInfo: { title: 'Organizations' },
|
||||
layout: Layout,
|
||||
components: {
|
||||
Icon,
|
||||
Pagination,
|
||||
SearchFilter,
|
||||
},
|
||||
layout: Layout,
|
||||
props: {
|
||||
organizations: Object,
|
||||
filters: Object,
|
||||
|
|
|
@ -4,21 +4,21 @@
|
|||
<inertia-link class="text-indigo-400 hover:text-indigo-600" :href="route('users')">Users</inertia-link>
|
||||
<span class="text-indigo-400 font-medium">/</span> Create
|
||||
</h1>
|
||||
<div class="bg-white rounded shadow overflow-hidden max-w-3xl">
|
||||
<form @submit.prevent="submit">
|
||||
<div class="bg-white rounded-md shadow overflow-hidden max-w-3xl">
|
||||
<form @submit.prevent="store">
|
||||
<div class="p-8 -mr-6 -mb-8 flex flex-wrap">
|
||||
<text-input v-model="form.first_name" :error="errors.first_name" class="pr-6 pb-8 w-full lg:w-1/2" label="First name" />
|
||||
<text-input v-model="form.last_name" :error="errors.last_name" class="pr-6 pb-8 w-full lg:w-1/2" label="Last name" />
|
||||
<text-input v-model="form.email" :error="errors.email" class="pr-6 pb-8 w-full lg:w-1/2" label="Email" />
|
||||
<text-input v-model="form.password" :error="errors.password" class="pr-6 pb-8 w-full lg:w-1/2" type="password" autocomplete="new-password" label="Password" />
|
||||
<select-input v-model="form.owner" :error="errors.owner" class="pr-6 pb-8 w-full lg:w-1/2" label="Owner">
|
||||
<text-input v-model="form.first_name" :error="form.errors.first_name" class="pr-6 pb-8 w-full lg:w-1/2" label="First name" />
|
||||
<text-input v-model="form.last_name" :error="form.errors.last_name" class="pr-6 pb-8 w-full lg:w-1/2" label="Last name" />
|
||||
<text-input v-model="form.email" :error="form.errors.email" class="pr-6 pb-8 w-full lg:w-1/2" label="Email" />
|
||||
<text-input v-model="form.password" :error="form.errors.password" class="pr-6 pb-8 w-full lg:w-1/2" type="password" autocomplete="new-password" label="Password" />
|
||||
<select-input v-model="form.owner" :error="form.errors.owner" class="pr-6 pb-8 w-full lg:w-1/2" label="Owner">
|
||||
<option :value="true">Yes</option>
|
||||
<option :value="false">No</option>
|
||||
</select-input>
|
||||
<file-input v-model="form.photo" :error="errors.photo" class="pr-6 pb-8 w-full lg:w-1/2" type="file" accept="image/*" label="Photo" />
|
||||
<file-input v-model="form.photo" :error="form.errors.photo" class="pr-6 pb-8 w-full lg:w-1/2" type="file" accept="image/*" label="Photo" />
|
||||
</div>
|
||||
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex justify-end items-center">
|
||||
<loading-button :loading="sending" class="btn-indigo" type="submit">Create User</loading-button>
|
||||
<div class="px-8 py-4 bg-gray-50 border-t border-gray-100 flex justify-end items-center">
|
||||
<loading-button :loading="form.processing" class="btn-indigo" type="submit">Create User</loading-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -27,51 +27,36 @@
|
|||
|
||||
<script>
|
||||
import Layout from '@/Shared/Layout'
|
||||
import LoadingButton from '@/Shared/LoadingButton'
|
||||
import SelectInput from '@/Shared/SelectInput'
|
||||
import TextInput from '@/Shared/TextInput'
|
||||
import FileInput from '@/Shared/FileInput'
|
||||
import TextInput from '@/Shared/TextInput'
|
||||
import SelectInput from '@/Shared/SelectInput'
|
||||
import LoadingButton from '@/Shared/LoadingButton'
|
||||
|
||||
export default {
|
||||
metaInfo: { title: 'Create User' },
|
||||
layout: Layout,
|
||||
components: {
|
||||
FileInput,
|
||||
LoadingButton,
|
||||
SelectInput,
|
||||
TextInput,
|
||||
FileInput,
|
||||
},
|
||||
props: {
|
||||
errors: Object,
|
||||
},
|
||||
layout: Layout,
|
||||
remember: 'form',
|
||||
data() {
|
||||
return {
|
||||
sending: false,
|
||||
form: {
|
||||
form: this.$inertia.form({
|
||||
first_name: null,
|
||||
last_name: null,
|
||||
email: null,
|
||||
password: null,
|
||||
owner: false,
|
||||
photo: null,
|
||||
},
|
||||
}),
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
const data = new FormData()
|
||||
data.append('first_name', this.form.first_name || '')
|
||||
data.append('last_name', this.form.last_name || '')
|
||||
data.append('email', this.form.email || '')
|
||||
data.append('password', this.form.password || '')
|
||||
data.append('owner', this.form.owner ? '1' : '0')
|
||||
data.append('photo', this.form.photo || '')
|
||||
|
||||
this.$inertia.post(this.route('users.store'), data, {
|
||||
onStart: () => this.sending = true,
|
||||
onFinish: () => this.sending = false,
|
||||
})
|
||||
store() {
|
||||
this.form.post(this.route('users.store'))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -6,27 +6,27 @@
|
|||
<span class="text-indigo-400 font-medium">/</span>
|
||||
{{ form.first_name }} {{ form.last_name }}
|
||||
</h1>
|
||||
<img v-if="user.photo" class="block w-8 h-8 rounded-full ml-4" :src="user.photo">
|
||||
<img v-if="user.photo" class="block w-8 h-8 rounded-full ml-4" :src="user.photo" />
|
||||
</div>
|
||||
<trashed-message v-if="user.deleted_at" class="mb-6" @restore="restore">
|
||||
This user has been deleted.
|
||||
</trashed-message>
|
||||
<div class="bg-white rounded shadow overflow-hidden max-w-3xl">
|
||||
<form @submit.prevent="submit">
|
||||
<div class="bg-white rounded-md shadow overflow-hidden max-w-3xl">
|
||||
<form @submit.prevent="update">
|
||||
<div class="p-8 -mr-6 -mb-8 flex flex-wrap">
|
||||
<text-input v-model="form.first_name" :error="errors.first_name" class="pr-6 pb-8 w-full lg:w-1/2" label="First name" />
|
||||
<text-input v-model="form.last_name" :error="errors.last_name" class="pr-6 pb-8 w-full lg:w-1/2" label="Last name" />
|
||||
<text-input v-model="form.email" :error="errors.email" class="pr-6 pb-8 w-full lg:w-1/2" label="Email" />
|
||||
<text-input v-model="form.password" :error="errors.password" class="pr-6 pb-8 w-full lg:w-1/2" type="password" autocomplete="new-password" label="Password" />
|
||||
<select-input v-model="form.owner" :error="errors.owner" class="pr-6 pb-8 w-full lg:w-1/2" label="Owner">
|
||||
<text-input v-model="form.first_name" :error="form.errors.first_name" class="pr-6 pb-8 w-full lg:w-1/2" label="First name" />
|
||||
<text-input v-model="form.last_name" :error="form.errors.last_name" class="pr-6 pb-8 w-full lg:w-1/2" label="Last name" />
|
||||
<text-input v-model="form.email" :error="form.errors.email" class="pr-6 pb-8 w-full lg:w-1/2" label="Email" />
|
||||
<text-input v-model="form.password" :error="form.errors.password" class="pr-6 pb-8 w-full lg:w-1/2" type="password" autocomplete="new-password" label="Password" />
|
||||
<select-input v-model="form.owner" :error="form.errors.owner" class="pr-6 pb-8 w-full lg:w-1/2" label="Owner">
|
||||
<option :value="true">Yes</option>
|
||||
<option :value="false">No</option>
|
||||
</select-input>
|
||||
<file-input v-model="form.photo" :error="errors.photo" class="pr-6 pb-8 w-full lg:w-1/2" type="file" accept="image/*" label="Photo" />
|
||||
<file-input v-model="form.photo" :error="form.errors.photo" class="pr-6 pb-8 w-full lg:w-1/2" type="file" accept="image/*" label="Photo" />
|
||||
</div>
|
||||
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex items-center">
|
||||
<div class="px-8 py-4 bg-gray-50 border-t border-gray-100 flex items-center">
|
||||
<button v-if="!user.deleted_at" class="text-red-600 hover:underline" tabindex="-1" type="button" @click="destroy">Delete User</button>
|
||||
<loading-button :loading="sending" class="btn-indigo ml-auto" type="submit">Update User</loading-button>
|
||||
<loading-button :loading="form.processing" class="btn-indigo ml-auto" type="submit">Update User</loading-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -35,10 +35,10 @@
|
|||
|
||||
<script>
|
||||
import Layout from '@/Shared/Layout'
|
||||
import LoadingButton from '@/Shared/LoadingButton'
|
||||
import SelectInput from '@/Shared/SelectInput'
|
||||
import TextInput from '@/Shared/TextInput'
|
||||
import FileInput from '@/Shared/FileInput'
|
||||
import SelectInput from '@/Shared/SelectInput'
|
||||
import LoadingButton from '@/Shared/LoadingButton'
|
||||
import TrashedMessage from '@/Shared/TrashedMessage'
|
||||
|
||||
export default {
|
||||
|
@ -47,52 +47,35 @@ export default {
|
|||
title: `${this.form.first_name} ${this.form.last_name}`,
|
||||
}
|
||||
},
|
||||
layout: Layout,
|
||||
components: {
|
||||
FileInput,
|
||||
LoadingButton,
|
||||
SelectInput,
|
||||
TextInput,
|
||||
FileInput,
|
||||
TrashedMessage,
|
||||
},
|
||||
layout: Layout,
|
||||
props: {
|
||||
errors: Object,
|
||||
user: Object,
|
||||
},
|
||||
remember: 'form',
|
||||
data() {
|
||||
return {
|
||||
sending: false,
|
||||
form: {
|
||||
form: this.$inertia.form({
|
||||
_method: 'put',
|
||||
first_name: this.user.first_name,
|
||||
last_name: this.user.last_name,
|
||||
email: this.user.email,
|
||||
password: this.user.password,
|
||||
password: null,
|
||||
owner: this.user.owner,
|
||||
photo: null,
|
||||
},
|
||||
}),
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
var data = new FormData()
|
||||
data.append('first_name', this.form.first_name || '')
|
||||
data.append('last_name', this.form.last_name || '')
|
||||
data.append('email', this.form.email || '')
|
||||
data.append('password', this.form.password || '')
|
||||
data.append('owner', this.form.owner ? '1' : '0')
|
||||
data.append('photo', this.form.photo || '')
|
||||
data.append('_method', 'put')
|
||||
|
||||
this.$inertia.post(this.route('users.update', this.user.id), data, {
|
||||
onStart: () => this.sending = true,
|
||||
onFinish: () => this.sending = false,
|
||||
onSuccess: () => {
|
||||
if (Object.keys(this.$page.errors).length === 0) {
|
||||
this.form.photo = null
|
||||
this.form.password = null
|
||||
}
|
||||
},
|
||||
update() {
|
||||
this.form.post(this.route('users.update', this.user.id), {
|
||||
onSuccess: () => this.form.reset('password', 'photo'),
|
||||
})
|
||||
},
|
||||
destroy() {
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
<span class="hidden md:inline">User</span>
|
||||
</inertia-link>
|
||||
</div>
|
||||
<div class="bg-white rounded shadow overflow-x-auto">
|
||||
<table class="w-full whitespace-no-wrap">
|
||||
<div class="bg-white rounded-md shadow overflow-x-auto">
|
||||
<table class="w-full whitespace-nowrap">
|
||||
<tr class="text-left font-bold">
|
||||
<th class="px-6 pt-6 pb-4">Name</th>
|
||||
<th class="px-6 pt-6 pb-4">Email</th>
|
||||
|
@ -31,7 +31,7 @@
|
|||
<tr v-for="user in users" :key="user.id" class="hover:bg-gray-100 focus-within:bg-gray-100">
|
||||
<td class="border-t">
|
||||
<inertia-link class="px-6 py-4 flex items-center focus:text-indigo-500" :href="route('users.edit', user.id)">
|
||||
<img v-if="user.photo" class="block w-5 h-5 rounded-full mr-2 -my-2" :src="user.photo">
|
||||
<img v-if="user.photo" class="block w-5 h-5 rounded-full mr-2 -my-2" :src="user.photo" />
|
||||
{{ user.name }}
|
||||
<icon v-if="user.deleted_at" name="trash" class="flex-shrink-0 w-3 h-3 fill-gray-400 ml-2" />
|
||||
</inertia-link>
|
||||
|
@ -62,19 +62,19 @@
|
|||
|
||||
<script>
|
||||
import Icon from '@/Shared/Icon'
|
||||
import Layout from '@/Shared/Layout'
|
||||
import mapValues from 'lodash/mapValues'
|
||||
import pickBy from 'lodash/pickBy'
|
||||
import SearchFilter from '@/Shared/SearchFilter'
|
||||
import Layout from '@/Shared/Layout'
|
||||
import throttle from 'lodash/throttle'
|
||||
import mapValues from 'lodash/mapValues'
|
||||
import SearchFilter from '@/Shared/SearchFilter'
|
||||
|
||||
export default {
|
||||
metaInfo: { title: 'Users' },
|
||||
layout: Layout,
|
||||
components: {
|
||||
Icon,
|
||||
SearchFilter,
|
||||
},
|
||||
layout: Layout,
|
||||
props: {
|
||||
users: Array,
|
||||
filters: Object,
|
||||
|
|
|
@ -52,7 +52,7 @@ export default {
|
|||
},
|
||||
},
|
||||
mounted() {
|
||||
document.addEventListener('keydown', (e) => {
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.keyCode === 27) {
|
||||
this.show = false
|
||||
}
|
||||
|
|
|
@ -2,14 +2,16 @@
|
|||
<div>
|
||||
<label v-if="label" class="form-label">{{ label }}:</label>
|
||||
<div class="form-input p-0" :class="{ error: errors.length }">
|
||||
<input ref="file" type="file" :accept="accept" class="hidden" @change="change">
|
||||
<input ref="file" type="file" :accept="accept" class="hidden" @change="change" />
|
||||
<div v-if="!value" class="p-2">
|
||||
<button type="button" class="px-4 py-1 bg-gray-500 hover:bg-gray-700 rounded-sm text-xs font-medium text-white" @click="browse">
|
||||
Browse
|
||||
</button>
|
||||
</div>
|
||||
<div v-else class="flex items-center justify-between p-2">
|
||||
<div class="flex-1 pr-1">{{ value.name }} <span class="text-gray-500 text-xs">({{ filesize(value.size) }})</span></div>
|
||||
<div class="flex-1 pr-1">
|
||||
{{ value.name }} <span class="text-gray-500 text-xs">({{ filesize(value.size) }})</span>
|
||||
</div>
|
||||
<button type="button" class="px-4 py-1 bg-gray-500 hover:bg-gray-700 rounded-sm text-xs font-medium text-white" @click="remove">
|
||||
Remove
|
||||
</button>
|
||||
|
@ -40,7 +42,7 @@ export default {
|
|||
methods: {
|
||||
filesize(size) {
|
||||
var i = Math.floor(Math.log(size) / Math.log(1024))
|
||||
return (size / Math.pow(1024, i) ).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]
|
||||
return (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]
|
||||
},
|
||||
browse() {
|
||||
this.$refs.file.click()
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
<template>
|
||||
<div>
|
||||
<div v-if="$page.flash.success && show" class="mb-8 flex items-center justify-between bg-green-500 rounded max-w-3xl">
|
||||
<div v-if="$page.props.flash.success && show" class="mb-8 flex items-center justify-between bg-green-500 rounded max-w-3xl">
|
||||
<div class="flex items-center">
|
||||
<svg class="ml-4 mr-2 flex-shrink-0 w-4 h-4 fill-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><polygon points="0 11 2 9 7 14 18 3 20 5 7 18" /></svg>
|
||||
<div class="py-4 text-white text-sm font-medium">{{ $page.flash.success }}</div>
|
||||
<div class="py-4 text-white text-sm font-medium">{{ $page.props.flash.success }}</div>
|
||||
</div>
|
||||
<button type="button" class="group mr-2 p-2" @click="show = false">
|
||||
<svg class="block w-2 h-2 fill-green-800 group-hover:fill-white" xmlns="http://www.w3.org/2000/svg" width="235.908" height="235.908" viewBox="278.046 126.846 235.908 235.908"><path d="M506.784 134.017c-9.56-9.56-25.06-9.56-34.62 0L396 210.18l-76.164-76.164c-9.56-9.56-25.06-9.56-34.62 0-9.56 9.56-9.56 25.06 0 34.62L361.38 244.8l-76.164 76.165c-9.56 9.56-9.56 25.06 0 34.62 9.56 9.56 25.06 9.56 34.62 0L396 279.42l76.164 76.165c9.56 9.56 25.06 9.56 34.62 0 9.56-9.56 9.56-25.06 0-34.62L430.62 244.8l76.164-76.163c9.56-9.56 9.56-25.06 0-34.62z" /></svg>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="($page.flash.error || Object.keys($page.errors).length > 0) && show" class="mb-8 flex items-center justify-between bg-red-500 rounded max-w-3xl">
|
||||
<div v-if="($page.props.flash.error || Object.keys($page.props.errors).length > 0) && show" class="mb-8 flex items-center justify-between bg-red-400 rounded max-w-3xl">
|
||||
<div class="flex items-center">
|
||||
<svg class="ml-4 mr-2 flex-shrink-0 w-4 h-4 fill-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zm1.41-1.41A8 8 0 1 0 15.66 4.34 8 8 0 0 0 4.34 15.66zm9.9-8.49L11.41 10l2.83 2.83-1.41 1.41L10 11.41l-2.83 2.83-1.41-1.41L8.59 10 5.76 7.17l1.41-1.41L10 8.59l2.83-2.83 1.41 1.41z" /></svg>
|
||||
<div v-if="$page.flash.error" class="py-4 text-white text-sm font-medium">{{ $page.flash.error }}</div>
|
||||
<div v-if="$page.props.flash.error" class="py-4 text-white text-sm font-medium">{{ $page.props.flash.error }}</div>
|
||||
<div v-else class="py-4 text-white text-sm font-medium">
|
||||
<span v-if="Object.keys($page.errors).length === 1">There is one form error.</span>
|
||||
<span v-else>There are {{ Object.keys($page.errors).length }} form errors.</span>
|
||||
<span v-if="Object.keys($page.props.errors).length === 1">There is one form error.</span>
|
||||
<span v-else>There are {{ Object.keys($page.props.errors).length }} form errors.</span>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="group mr-2 p-2" @click="show = false">
|
||||
|
@ -33,7 +33,7 @@ export default {
|
|||
}
|
||||
},
|
||||
watch: {
|
||||
'$page.flash': {
|
||||
'$page.props.flash': {
|
||||
handler() {
|
||||
this.show = true
|
||||
},
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div>
|
||||
<portal-target name="dropdown" slim />
|
||||
<div class="md:flex md:flex-col">
|
||||
<div class="md:h-screen md:flex md:flex-col" @click="hideDropdownMenus">
|
||||
<div class="md:h-screen md:flex md:flex-col">
|
||||
<div class="md:flex md:flex-shrink-0">
|
||||
<div class="bg-indigo-900 md:flex-shrink-0 md:w-56 px-6 py-4 flex items-center justify-between md:justify-center">
|
||||
<inertia-link class="mt-1" href="/">
|
||||
|
@ -11,30 +11,30 @@
|
|||
<dropdown class="md:hidden" placement="bottom-end">
|
||||
<svg class="fill-white w-6 h-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z" /></svg>
|
||||
<div slot="dropdown" class="mt-2 px-8 py-4 shadow-lg bg-indigo-800 rounded">
|
||||
<main-menu :url="url()" />
|
||||
<main-menu />
|
||||
</div>
|
||||
</dropdown>
|
||||
</div>
|
||||
<div class="bg-white border-b w-full p-4 md:py-0 md:px-12 text-sm md:text-md flex justify-between items-center">
|
||||
<div class="mt-1 mr-4">{{ $page.auth.user.account.name }}</div>
|
||||
<div class="mt-1 mr-4">{{ $page.props.auth.user.account.name }}</div>
|
||||
<dropdown class="mt-1" placement="bottom-end">
|
||||
<div class="flex items-center cursor-pointer select-none group">
|
||||
<div class="text-gray-700 group-hover:text-indigo-600 focus:text-indigo-600 mr-1 whitespace-no-wrap">
|
||||
<span>{{ $page.auth.user.first_name }}</span>
|
||||
<span class="hidden md:inline">{{ $page.auth.user.last_name }}</span>
|
||||
<div class="text-gray-700 group-hover:text-indigo-600 focus:text-indigo-600 mr-1 whitespace-nowrap">
|
||||
<span>{{ $page.props.auth.user.first_name }}</span>
|
||||
<span class="hidden md:inline">{{ $page.props.auth.user.last_name }}</span>
|
||||
</div>
|
||||
<icon class="w-5 h-5 group-hover:fill-indigo-600 fill-gray-700 focus:fill-indigo-600" name="cheveron-down" />
|
||||
</div>
|
||||
<div slot="dropdown" class="mt-2 py-2 shadow-xl bg-white rounded text-sm">
|
||||
<inertia-link class="block px-6 py-2 hover:bg-indigo-500 hover:text-white" :href="route('users.edit', $page.auth.user.id)">My Profile</inertia-link>
|
||||
<inertia-link class="block px-6 py-2 hover:bg-indigo-500 hover:text-white" :href="route('users.edit', $page.props.auth.user.id)">My Profile</inertia-link>
|
||||
<inertia-link class="block px-6 py-2 hover:bg-indigo-500 hover:text-white" :href="route('users')">Manage Users</inertia-link>
|
||||
<inertia-link class="block px-6 py-2 hover:bg-indigo-500 hover:text-white" :href="route('logout')" method="post">Logout</inertia-link>
|
||||
<inertia-link class="block px-6 py-2 hover:bg-indigo-500 hover:text-white w-full text-left" :href="route('logout')" method="post" as="button">Logout</inertia-link>
|
||||
</div>
|
||||
</dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md:flex md:flex-grow md:overflow-hidden">
|
||||
<main-menu :url="url()" class="hidden md:block bg-indigo-800 flex-shrink-0 w-56 p-12 overflow-y-auto" />
|
||||
<main-menu class="hidden md:block bg-indigo-800 flex-shrink-0 w-56 p-12 overflow-y-auto" />
|
||||
<div class="md:flex-1 px-4 py-8 md:p-12 md:overflow-y-auto" scroll-region>
|
||||
<flash-messages />
|
||||
<slot />
|
||||
|
@ -46,11 +46,11 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Dropdown from '@/Shared/Dropdown'
|
||||
import FlashMessages from '@/Shared/FlashMessages'
|
||||
import Icon from '@/Shared/Icon'
|
||||
import Logo from '@/Shared/Logo'
|
||||
import Dropdown from '@/Shared/Dropdown'
|
||||
import MainMenu from '@/Shared/MainMenu'
|
||||
import FlashMessages from '@/Shared/FlashMessages'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -60,19 +60,5 @@ export default {
|
|||
Logo,
|
||||
MainMenu,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showUserMenu: false,
|
||||
accounts: null,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
url() {
|
||||
return location.pathname.substr(1)
|
||||
},
|
||||
hideDropdownMenus() {
|
||||
this.showUserMenu = false
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -34,16 +34,13 @@ export default {
|
|||
components: {
|
||||
Icon,
|
||||
},
|
||||
props: {
|
||||
url: String,
|
||||
},
|
||||
methods: {
|
||||
isUrl(...urls) {
|
||||
let currentUrl = this.$page.url.substr(1)
|
||||
if (urls[0] === '') {
|
||||
return this.url === ''
|
||||
return currentUrl === ''
|
||||
}
|
||||
|
||||
return urls.filter(url => this.url.startsWith(url)).length
|
||||
return urls.filter(url => currentUrl.startsWith(url)).length
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<template>
|
||||
<div class="mt-6 -mb-1 flex flex-wrap">
|
||||
<template v-for="(link, key) in links">
|
||||
<div v-if="link.url === null" :key="key" class="mr-1 mb-1 px-4 py-3 text-sm border rounded text-gray-400" :class="{ 'ml-auto': link.label === 'Next' }">{{ link.label }}</div>
|
||||
<inertia-link v-else :key="key" class="mr-1 mb-1 px-4 py-3 text-sm border rounded hover:bg-white focus:border-indigo-500 focus:text-indigo-500" :class="{ 'bg-white': link.active, 'ml-auto': link.label === 'Next' }" :href="link.url">{{ link.label }}</inertia-link>
|
||||
</template>
|
||||
<div v-if="links.length > 3">
|
||||
<div class="flex flex-wrap -mb-1">
|
||||
<template v-for="(link, key) in links">
|
||||
<div v-if="link.url === null" :key="key" class="mr-1 mb-1 px-4 py-3 text-sm leading-4 text-gray-400 border rounded" v-html="link.label" />
|
||||
<inertia-link v-else :key="key" class="mr-1 mb-1 px-4 py-3 text-sm leading-4 border rounded hover:bg-white focus:border-indigo-500 focus:text-indigo-500" :class="{ 'bg-white': link.active }" :href="link.url" v-html="link.label" />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="flex items-center">
|
||||
<div class="flex w-full bg-white shadow rounded">
|
||||
<dropdown :auto-close="false" class="px-4 md:px-6 rounded-l border-r hover:bg-gray-100 focus:border-white focus:shadow-outline focus:z-10" placement="bottom-start">
|
||||
<dropdown :auto-close="false" class="px-4 md:px-6 rounded-l border-r hover:bg-gray-100 focus:border-white focus:ring focus:z-10" placement="bottom-start">
|
||||
<div class="flex items-baseline">
|
||||
<span class="text-gray-700 hidden md:inline">Filter</span>
|
||||
<svg class="w-2 h-2 fill-gray-700 md:ml-2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 961.243 599.998">
|
||||
|
@ -12,7 +12,7 @@
|
|||
<slot />
|
||||
</div>
|
||||
</dropdown>
|
||||
<input class="relative w-full px-6 py-3 rounded-r focus:shadow-outline" autocomplete="off" type="text" name="search" placeholder="Search…" :value="value" @input="$emit('input', $event.target.value)">
|
||||
<input class="relative w-full px-6 py-3 rounded-r focus:ring" autocomplete="off" type="text" name="search" placeholder="Search…" :value="value" @input="$emit('input', $event.target.value)" />
|
||||
</div>
|
||||
<button class="ml-3 text-sm text-gray-500 hover:text-gray-700 focus:text-indigo-500" type="button" @click="$emit('reset')">Reset</button>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div>
|
||||
<label v-if="label" class="form-label" :for="id">{{ label }}:</label>
|
||||
<input :id="id" ref="input" v-bind="$attrs" class="form-input" :class="{ error: error }" :type="type" :value="value" @input="$emit('input', $event.target.value)">
|
||||
<input :id="id" ref="input" v-bind="$attrs" class="form-input" :class="{ error: error }" :type="type" :value="value" @input="$emit('input', $event.target.value)" />
|
||||
<div v-if="error" class="form-error">{{ error }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="p-4 bg-yellow-400 rounded flex items-center justify-between max-w-3xl">
|
||||
<div class="p-4 bg-yellow-300 rounded flex items-center justify-between max-w-3xl">
|
||||
<div class="flex items-center">
|
||||
<icon name="trash" class="flex-shrink-0 w-4 h-4 fill-yellow-800 mr-2" />
|
||||
<div class="text-sm font-medium text-yellow-800">
|
||||
|
|
|
@ -1,27 +1,28 @@
|
|||
import Vue from 'vue'
|
||||
import VueMeta from 'vue-meta'
|
||||
import PortalVue from 'portal-vue'
|
||||
import { InertiaApp } from '@inertiajs/inertia-vue'
|
||||
import { App, plugin } from '@inertiajs/inertia-vue'
|
||||
import { InertiaProgress } from '@inertiajs/progress/src'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
Vue.mixin({ methods: { route: window.route } })
|
||||
Vue.use(InertiaApp)
|
||||
Vue.use(plugin)
|
||||
Vue.use(PortalVue)
|
||||
Vue.use(VueMeta)
|
||||
|
||||
InertiaProgress.init()
|
||||
|
||||
let app = document.getElementById('app')
|
||||
const el = document.getElementById('app')
|
||||
|
||||
new Vue({
|
||||
metaInfo: {
|
||||
titleTemplate: (title) => title ? `${title} - Ping CRM` : 'Ping CRM'
|
||||
titleTemplate: title => (title ? `${title} - Ping CRM` : 'Ping CRM'),
|
||||
},
|
||||
render: h => h(InertiaApp, {
|
||||
props: {
|
||||
initialPage: JSON.parse(app.dataset.page),
|
||||
resolveComponent: name => import(`@/Pages/${name}`).then(module => module.default),
|
||||
},
|
||||
}),
|
||||
}).$mount(app)
|
||||
render: h =>
|
||||
h(App, {
|
||||
props: {
|
||||
initialPage: JSON.parse(el.dataset.page),
|
||||
resolveComponent: name => import(`@/Pages/${name}`).then(module => module.default),
|
||||
},
|
||||
}),
|
||||
}).$mount(el)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="h-full bg-gray-200">
|
||||
<html class="h-full bg-gray-100">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
|
||||
<link href="{{ mix('/css/app.css') }}" rel="stylesheet">
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
|
||||
|
||||
{{-- Inertia --}}
|
||||
<script src="https://polyfill.io/v3/polyfill.min.js?features=smoothscroll,NodeList.prototype.forEach,Promise,Object.values,Object.assign" defer></script>
|
||||
|
|
|
@ -1,22 +1,42 @@
|
|||
const colors = require('tailwindcss/colors')
|
||||
const defaultTheme = require('tailwindcss/defaultTheme')
|
||||
|
||||
module.exports = {
|
||||
purge: [
|
||||
// prettier-ignore
|
||||
'./resources/**/*.blade.php',
|
||||
'./resources/**/*.js',
|
||||
'./resources/**/*.vue',
|
||||
],
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
colors: {
|
||||
transparent: 'transparent',
|
||||
current: 'currentColor',
|
||||
black: colors.black,
|
||||
white: colors.white,
|
||||
red: colors.red,
|
||||
orange: colors.orange,
|
||||
yellow: colors.yellow,
|
||||
green: colors.green,
|
||||
gray: colors.blueGray,
|
||||
indigo: {
|
||||
100: '#e6e8ff',
|
||||
300: '#b2b7ff',
|
||||
400: '#7886d7',
|
||||
500: '#6574cd',
|
||||
600: '#5661b3',
|
||||
800: '#2f365f',
|
||||
900: '#191e38',
|
||||
},
|
||||
},
|
||||
extend: {
|
||||
borderColor: theme => ({
|
||||
DEFAULT: theme('colors.gray.200', 'currentColor'),
|
||||
}),
|
||||
fontFamily: {
|
||||
sans: ['Cerebri Sans', ...defaultTheme.fontFamily.sans],
|
||||
},
|
||||
colors: {
|
||||
indigo: {
|
||||
'900': '#191e38',
|
||||
'800': '#2f365f',
|
||||
'600': '#5661b3',
|
||||
'500': '#6574cd',
|
||||
'400': '#7886d7',
|
||||
'300': '#b2b7ff',
|
||||
'100': '#e6e8ff',
|
||||
},
|
||||
},
|
||||
boxShadow: theme => ({
|
||||
outline: '0 0 0 2px ' + theme('colors.indigo.500'),
|
||||
}),
|
||||
|
@ -24,9 +44,9 @@ module.exports = {
|
|||
},
|
||||
},
|
||||
variants: {
|
||||
fill: ['responsive', 'hover', 'focus', 'group-hover'],
|
||||
textColor: ['responsive', 'hover', 'focus', 'group-hover'],
|
||||
zIndex: ['responsive', 'focus'],
|
||||
extend: {
|
||||
fill: ['focus', 'group-hover'],
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
const path = require('path')
|
||||
const mix = require('laravel-mix')
|
||||
const cssImport = require('postcss-import')
|
||||
const cssNesting = require('postcss-nesting')
|
||||
const mix = require('laravel-mix')
|
||||
const path = require('path')
|
||||
const purgecss = require('@fullhuman/postcss-purgecss')
|
||||
const tailwindcss = require('tailwindcss')
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
@ -16,22 +14,15 @@ const tailwindcss = require('tailwindcss')
|
|||
|
|
||||
*/
|
||||
|
||||
mix.js('resources/js/app.js', 'public/js')
|
||||
.postCss('resources/css/app.css', 'public/css/app.css')
|
||||
.options({
|
||||
postCss: [
|
||||
cssImport(),
|
||||
cssNesting(),
|
||||
tailwindcss('tailwind.config.js'),
|
||||
...mix.inProduction() ? [
|
||||
purgecss({
|
||||
content: ['./resources/views/**/*.blade.php', './resources/js/**/*.vue'],
|
||||
defaultExtractor: content => content.match(/[\w-/:.]+(?<!:)/g) || [],
|
||||
whitelistPatternsChildren: [/nprogress/],
|
||||
}),
|
||||
] : [],
|
||||
],
|
||||
})
|
||||
mix
|
||||
.js('resources/js/app.js', 'public/js')
|
||||
.vue()
|
||||
.postCss('resources/css/app.css', 'public/css', [
|
||||
// prettier-ignore
|
||||
cssImport(),
|
||||
cssNesting(),
|
||||
require('tailwindcss'),
|
||||
])
|
||||
.webpackConfig({
|
||||
output: { chunkFilename: 'js/[name].js?id=[chunkhash]' },
|
||||
resolve: {
|
||||
|
|
Loading…
Reference in New Issue