Skip to content

Commit

Permalink
Init blud
Browse files Browse the repository at this point in the history
  • Loading branch information
m2de committed Sep 1, 2018
0 parents commit 1b980fa
Show file tree
Hide file tree
Showing 12 changed files with 307 additions and 0 deletions.
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/dist
/.idea
/vendor
/node_modules
package-lock.json
composer.phar
composer.lock
phpunit.xml
.phpunit.result.cache
.DS_Store
Thumbs.db
35 changes: 35 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "silvanite/nova-field-checkboxes",
"description": "A Laravel Nova field to display a number of multi-select options using checkboxes.",
"keywords": [
"laravel",
"nova",
"input",
"field",
"checkbox",
"checkboxes",
"multiselect",
"multiple choice"
],
"license": "MIT",
"require": {
"php": ">=7.1.0"
},
"autoload": {
"psr-4": {
"Silvanite\\NovaFieldCheckboxes\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"Silvanite\\NovaFieldCheckboxes\\FieldServiceProvider"
]
}
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev",
"prefer-stable": true
}
4 changes: 4 additions & 0 deletions mix-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"/dist/js/field.js": "/dist/js/field.js",
"/dist/css/field.css": "/dist/css/field.css"
}
20 changes: 20 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"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",
"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 --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"cross-env": "^5.0.0",
"laravel-mix": "^1.0",
"laravel-nova": "^1.0"
},
"dependencies": {
"vue": "^2.5.0"
}
}
25 changes: 25 additions & 0 deletions resources/js/components/DetailField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<template>
<panel-item :field="field">
<p slot="value" class="text-90">
<span class="flex flex-wrap w-full">
<div
v-for="(label, option) in field.options"
:key="option"
class="w-1/3"
>
<span
class="inline-block rounded-full w-2 h-2 mr-1"
:class="{'bg-success': field.value.includes(option), 'bg-danger': !field.value.includes(option)}"
/>
<span>{{ label }}</span>
</div>
</span>
</p>
</panel-item>
</template>

<script>
export default {
props: ['resource', 'resourceName', 'resourceId', 'field'],
}
</script>
75 changes: 75 additions & 0 deletions resources/js/components/FormField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<template>
<default-field :field="field">
<template slot="field">
<div class="flex flex-wrap w-full">
<div
v-for="(label, option) in field.options"
:key="option"
class="flex w-1/2 lg:w-1/3 mb-2"
>
<checkbox
:value="option"
:checked="isChecked(option)"
@input="toggleOption(option)"
class="pr-2"
/>
<label
:for="field.name"
v-text="label"
@click="toggleOption(option)"
></label>
</div>
</div>
<p v-if="hasError" class="my-2 text-danger">
{{ firstError }}
</p>
</template>
</default-field>
</template>

<script>
import { FormField, HandlesValidationErrors } from 'laravel-nova'
export default {
mixins: [FormField, HandlesValidationErrors],
props: ['resourceName', 'resourceId', 'field'],
methods: {
isChecked(option) {
return this.value.includes(option)
},
toggleOption(option) {
if (this.isChecked(option)) {
this.$set(this, 'value', this.value.filter(item => item != option))
return
}
this.value.push(option)
},
/*
* Set the initial, internal value for the field.
*/
setInitialValue() {
this.value = this.field.value || []
},
/**
* Fill the given FormData object with the field's internal value.
*/
fill(formData) {
formData.append(this.field.attribute, this.value || [])
},
/**
* Update the field's internal value.
*/
handleChange(value) {
this.value = value
}
}
}
</script>
33 changes: 33 additions & 0 deletions resources/js/components/IndexField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<template>
<span class="w-full">
<span
v-for="(value, option) in availableOptions"
:key="option"
:class="optionClass(option)"
:title="value"
class="inline-block rounded-full w-2 h-2 mr-1"
/>
</span>
</template>

<script>
export default {
props: ['resourceName', 'field'],
computed: {
availableOptions() {
return this.field.options
},
},
methods: {
optionClass(option) {
return {
'bg-success': this.field.value.includes(option),
'bg-danger': !this.field.value.includes(option),
}
},
},
}
</script>
9 changes: 9 additions & 0 deletions resources/js/field.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Vue from 'vue'

Vue.config.devtools = true

Nova.booting((Vue, router) => {
Vue.component('index-nova-field-checkboxes', require('./components/IndexField'));
Vue.component('detail-nova-field-checkboxes', require('./components/DetailField'));
Vue.component('form-nova-field-checkboxes', require('./components/FormField'));
})
1 change: 1 addition & 0 deletions resources/sass/field.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// Nova Tool CSS
52 changes: 52 additions & 0 deletions src/Checkboxes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Silvanite\NovaFieldCheckboxes;

use Laravel\Nova\Fields\Field;
use Laravel\Nova\Http\Requests\NovaRequest;

class Checkboxes extends Field
{
/**
* The field's component.
*
* @var string
*/
public $component = 'nova-field-checkboxes';

/**
* Specify the available options
*
* @param array $options
* @return void
*/
public function options(array $options)
{
return $this->withMeta(['options' => $options]);
}

/**
* Hydrate the given attribute on the model based on the incoming request.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @param string $requestAttribute
* @param object $model
* @param string $attribute
* @return void
*/
protected function fillAttributeFromRequest(NovaRequest $request, $requestAttribute, $model, $attribute)
{
if ($request->exists($requestAttribute)) {
/**
* When editing entries, they are returned as comma seperated string (unsure why).
* As a result we need to include this check and explode the values if required.
*/
clock($request[$requestAttribute]);
if (!is_array($choices = $request[$requestAttribute])) {
$choices = explode(',', $choices);
}

$model->{$attribute} = $choices;
}
}
}
33 changes: 33 additions & 0 deletions src/FieldServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Silvanite\NovaFieldCheckboxes;

use Laravel\Nova\Nova;
use Laravel\Nova\Events\ServingNova;
use Illuminate\Support\ServiceProvider;

class FieldServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Nova::serving(function (ServingNova $event) {
Nova::script('nova-field-checkboxes', __DIR__.'/../dist/js/field.js');
Nova::style('nova-field-checkboxes', __DIR__.'/../dist/css/field.css');
});
}

/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
}
9 changes: 9 additions & 0 deletions webpack.mix.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
let mix = require('laravel-mix')

mix.js('resources/js/field.js', 'dist/js')
.sass('resources/sass/field.scss', 'dist/css')
.webpackConfig({
resolve: {
symlinks: false
}
})

0 comments on commit 1b980fa

Please sign in to comment.