Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ZakariaTlilani committed Jan 11, 2024
1 parent 0faf613 commit 496dbf8
Show file tree
Hide file tree
Showing 13 changed files with 290 additions and 22 deletions.
24 changes: 2 additions & 22 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
/vendor/
node_modules/
npm-debug.log
yarn-error.log

# Laravel 4 specific
bootstrap/compiled.php
app/storage/

# Laravel 5 & Lumen specific
public/storage
public/hot

# Laravel 5 & Lumen specific with changed public path
public_html/storage
public_html/hot

storage/*.key
.env
Homestead.yaml
Homestead.json
/.vagrant
.phpunit.result.cache
/node_modules/
composer.json
Empty file added dist/css/field.css
Empty file.
1 change: 1 addition & 0 deletions dist/js/field.js

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions dist/mix-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"/js/field.js": "/js/field.js",
"/css/field.css": "/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"
}
}
9 changes: 9 additions & 0 deletions resources/js/components/DetailField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<template>
<panel-item :field="field" />
</template>

<script>
export default {
props: ['resource', 'resourceName', 'resourceId', 'field'],
}
</script>
137 changes: 137 additions & 0 deletions resources/js/components/FormField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<template>
<default-field :field="field" :errors="errors" :show-help-text="showHelpText" :full-width-content="true">
<template slot="field">
<div v-for="locale in locales" :style="[locale == 'ar' ? {'border-bottom': '2px solid #7c858e', direction: 'rtl'} : {}]">
<input v-if="template == null"
type="text" class="my-2 w-full form-control form-input form-input-bordered" :class="errorClasses"
:placeholder="field.name" v-model="withoutTemplateValue[locale]" />
<div v-else v-for="(item, index) in template" class="my-2 inline-block">
<div v-if="item.word[locale].split('')[0] == '+'">
<input type="text" class="form-control form-input form-input-bordered inline-block w-auto mx-1 mb-1" :class="errorClasses"
:placeholder="item.word[locale].substr(1)" required
v-model="tempName[locale][index]" />
</div>
<div v-else-if="item.word[locale].split('')[0] == '-'">
<select v-model="tempName[locale][index]" required class="form-control form-input form-input-bordered inline-block w-auto mx-1 mb-1" :class="errorClasses">
<option value="null" disabled>{{item.word[locale].substr(1).split('-')[0]}}</option>
<option v-for="optionItem in item.word[locale].substr(1).split('-').slice(1)" :value="optionItem">{{optionItem}}</option>
</select>
</div>
<div v-else-if="item.word[locale].split('')[0] != null">
<input type="text" readonly required :size="item.word[locale].length"
class="form-control form-input form-input-bordered inline-block w-auto mx-1 mb-1"
v-model="tempName[locale][index] = item.word[locale]" />
</div>
</div>
</div>
</template>
</default-field>
</template>

<script>
import { FormField, HandlesValidationErrors } from 'laravel-nova'
export default {
mixins: [FormField, HandlesValidationErrors],
props: ['resourceName', 'resourceId', 'field'],
data() {
return {
fields: [],
locales: ['ar', 'en'],
template: null,
tempName: null,
withoutTemplateValue: null,
category: null
}
},
mounted() {
this.watchedComponents.forEach(component => {
let attribute = 'value'
// nova-nested-tree-attach-many
if(component.field.component === 'belongs-to-field') {
attribute = 'selectedResource';
}
component.$watch(attribute, (value) => {
this.category = (value && attribute === 'selectedResource') ? value.value : value;
this.updateResults();
}, { immediate: true });
});
},
computed: {
watchedComponents() {
return this.$parent.$children.filter(component => {
return this.isWatchingComponent(component);
})
},
endpoint() {
return this.field.endpoint
.replace('{'+ this.field.category +'}', this.category ? this.category : '')
.replace('{product}', this.resourceId ? this.resourceId : null)
},
},
methods: {
isWatchingComponent(component) {
return component.field !== undefined && component.field.attribute === this.field.category;
},
updateResults() {
if(this.notWatching() || (this.category != null && this.category !== '')) {
Nova.request().get(this.endpoint)
.then(response => {
if (response.data.template != null && response.data.template != '') {
this.template = response.data.template;
if (response.data.temp_name) {
this.tempName = {
'ar': response.data.temp_name.ar.split('(^)'),
'en': response.data.temp_name.en.split('(^)')
}
} else {
this.tempName = {
'ar': new Array(this.template.length).fill(null),
'en': new Array(this.template.length).fill(null)
}
}
} else {
this.template = null;
if(response.data.name) {
this.withoutTemplateValue = {
'ar': response.data.name.ar,
'en': response.data.name.en
}
} else {
this.withoutTemplateValue = {
'ar': null,
'en': null
}
}
}
})
}
},
notWatching() {
return this.field.category === undefined;
},
/*
* 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) {
if(this.tempName)
formData.append(this.field.attribute, JSON.stringify(this.tempName) || '')
else
formData.append('withoutTemplate', JSON.stringify(this.withoutTemplateValue) || '')
},
}
}
</script>
9 changes: 9 additions & 0 deletions resources/js/components/IndexField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<template>
<span>{{ field.value }}</span>
</template>

<script>
export default {
props: ['resourceName', 'field'],
}
</script>
5 changes: 5 additions & 0 deletions resources/js/field.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Nova.booting((Vue, router, store) => {
Vue.component('index-title-template', require('./components/IndexField'))
Vue.component('detail-title-template', require('./components/DetailField'))
Vue.component('form-title-template', 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
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 ZakariaTlilani\TextTemplate;

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

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

/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
}
63 changes: 63 additions & 0 deletions src/TitleTemplate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

namespace ZakariaTlilani\TextTemplate;

use Laravel\Nova\Fields\Field;

class Template extends Field
{
/**
* The field's component.
*
* @var string
*/
public $component = 'title-template';

/**
* @param $category
* @return TitleTemplate
*/
public function category($category)
{
return $this->withMeta([
'category' => $category
]);
}

/**
* @param $endpoint
* @return TitleTemplate
*/
public function endpoint($endpoint)
{
return $this->withMeta([
'endpoint' => $endpoint
]);
}

/**
* 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($request, $requestAttribute, $model, $attribute)
{
if ($request->exists($requestAttribute)) {
foreach (json_decode($request->name) as $key => $item) {
$name[$key] = implode(' ', $item);
$tempName[$key] = implode('(^)', $item);
}
$model->name = $name;
$model->temp_name = $tempName;
} elseif(isset($request->withoutTemplate)) {
foreach(json_decode($request->withoutTemplate) as $key => $item) {
$withoutTemplate[$key] = $item;
}
$model->name = $withoutTemplate;
}
}
}
6 changes: 6 additions & 0 deletions webpack.mix.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
let mix = require('laravel-mix')

mix
.setPublicPath('dist')
.js('resources/js/field.js', 'js')
.sass('resources/sass/field.scss', 'css')

0 comments on commit 496dbf8

Please sign in to comment.