Skip to content

Commit

Permalink
add text and textarea transformer field
Browse files Browse the repository at this point in the history
  • Loading branch information
bocanhcam committed Dec 18, 2024
0 parents commit 260a629
Show file tree
Hide file tree
Showing 21 changed files with 408 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 @@
/.idea
/vendor
/node_modules
auth.json
package-lock.json
composer.phar
composer.lock
phpunit.xml
.phpunit.result.cache
.DS_Store
Thumbs.db
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## Overview

A custom Laravel Nova field to transforming text to Hiragana or Katakana.

![Transforming Romaji](/screenshots/transform.gif)

## Installation

Install the package via Composer:
```shell
composer require bocanhcam/nova-japanese-transformer
```

## Usage

### Usage
Add the field to your Nova resource:

```php
use Bocanhcam\NovaJapaneseTransformer\JapaneseTransformerText;
use Bocanhcam\NovaJapaneseTransformer\JapaneseTransformerTextarea;

// Text
JapaneseTransformerText::make('Name'), // Convert Romaji to Kana. outputs Hiragana by default; uppercase text outputs Katakana.
JapaneseTransformerText::make('Hiragana')->toHiragana(), // Convert Katakana or Romaji to Hiragana.
JapaneseTransformerText::make('Katakana')->toKatakana(), // Convert Hiragana or Romaji to Katakana.
// Textarea
JapaneseTransformerTextarea::make('Description'), // Have the same function like Text field
```

### Powered by `wanakana`
For more details on wanakana, check out their [documentation](https://github.com/WaniKani/WanaKana).

## License
This package is open-sourced software licensed under the [MIT license](https://opensource.org/license/MIT).
37 changes: 37 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "bocanhcam/nova-japanese-transformer",
"description": "A Laravel Nova field.",
"keywords": [
"laravel",
"nova"
],
"license": "MIT",
"require": {
"php": "^8.1",
"illuminate/support": "^10.0|^11.0"
},
"require-dev": {
"laravel/nova": "^5.0",
"laravel/nova-devtool": "^1.1"
},
"repositories": [
{ "type": "composer", "url": "https://nova.laravel.com" }
],
"autoload": {
"psr-4": {
"Bocanhcam\\NovaJapaneseTransformer\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"Bocanhcam\\NovaJapaneseTransformer\\FieldServiceProvider"
]
}
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev",
"prefer-stable": true
}
1 change: 1 addition & 0 deletions dist/css/field.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

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"
}
18 changes: 18 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"private": true,
"scripts": {
"dev": "npm run development",
"development": "mix",
"watch": "mix watch",
"watch-poll": "mix watch -- --watch-options-poll=1000",
"prod": "npm run production",
"production": "mix --production"
},
"devDependencies": {
"laravel-nova-devtool": "file:vendor/laravel/nova-devtool",
"lodash": "^4.17.21"
},
"dependencies": {
"wanakana": "^5.3.1"
}
}
1 change: 1 addition & 0 deletions postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = {}
1 change: 1 addition & 0 deletions resources/css/field.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* Nova Field CSS */
9 changes: 9 additions & 0 deletions resources/js/components/Text/DetailField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<template>
<PanelItem :index="index" :field="field" />
</template>

<script>
export default {
props: ['index', 'resource', 'resourceName', 'resourceId', 'field'],
}
</script>
71 changes: 71 additions & 0 deletions resources/js/components/Text/FormField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<template>
<DefaultField
:field="currentField"
:errors="errors"
:show-help-text="showHelpText"
:full-width-content="fullWidthContent"
>
<template #field>
<input
:id="currentField.uniqueKey"
type="text"
class="w-full form-control form-input form-control-bordered"
:class="errorClasses"
:placeholder="currentField.placeholder"
@change="handleChange"
/>
</template>
</DefaultField>
</template>

<script>
import {DependentFormField, HandlesValidationErrors} from 'laravel-nova'
import * as wanakana from 'wanakana';
export default {
mixins: [DependentFormField, HandlesValidationErrors],
props: ['resourceName', 'resourceId', 'field'],
mounted() {
this.setInitialValue()
wanakana.bind(this.getInputElement(), {
IMEMode: this.currentField.IMEMode || true,
...this.currentField.options,
})
},
unmounted() {
wanakana.unbind(this.getInputElement())
},
methods: {
getInputElement() {
return document.getElementById(this.currentField.uniqueKey)
},
handleChange() {
this.emitFieldValueChange(this.fieldAttribute, this.getInputElement().value)
this.$emit('field-changed')
},
/*
* Set the initial, internal value for the field.
*/
setInitialValue() {
const input = this.getInputElement()
if (input) {
input.value = this.currentField.value || ''
}
},
/**
* Fill the given FormData object with the field's internal value.
*/
fill(formData) {
formData.append(this.fieldAttribute, this.getInputElement().value || '')
},
},
}
</script>
15 changes: 15 additions & 0 deletions resources/js/components/Text/IndexField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<template>
<span>{{ fieldValue }}</span>
</template>

<script>
export default {
props: ['resourceName', 'field'],
computed: {
fieldValue() {
return this.field.displayedAs || this.field.value
},
}
}
</script>
17 changes: 17 additions & 0 deletions resources/js/components/Textarea/DetailField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<template>
<PanelItem :index="index" :field="field">
<template #value>
<Excerpt
:content="field.value"
:plain-text="true"
:should-show="field.shouldShow"
/>
</template>
</PanelItem>
</template>

<script>
export default {
props: ['index', 'resource', 'resourceName', 'resourceId', 'field'],
}
</script>
72 changes: 72 additions & 0 deletions resources/js/components/Textarea/FormField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<template>
<DefaultField
:field="currentField"
:errors="errors"
:show-help-text="showHelpText"
:full-width-content="fullWidthContent"
>
<template #field>
<textarea
:id="currentField.uniqueKey"
type="text"
class="block w-full form-control form-input form-control-bordered py-3 h-auto"
:class="errorClasses"
:placeholder="currentField.placeholder"
:rows="currentField.rows"
@change="handleChange"
/>
</template>
</DefaultField>
</template>

<script>
import {DependentFormField, HandlesValidationErrors} from 'laravel-nova'
import * as wanakana from "wanakana";
export default {
mixins: [DependentFormField, HandlesValidationErrors],
props: ['resourceName', 'resourceId', 'field'],
mounted() {
this.setInitialValue()
wanakana.bind(this.getInputElement(), {
IMEMode: this.currentField.IMEMode || true,
...this.currentField.options,
})
},
unmounted() {
wanakana.unbind(this.getInputElement())
},
methods: {
getInputElement() {
return document.getElementById(this.currentField.uniqueKey)
},
handleChange() {
this.emitFieldValueChange(this.fieldAttribute, this.getInputElement().value)
this.$emit('field-changed')
},
/*
* Set the initial, internal value for the field.
*/
setInitialValue() {
const input = this.getInputElement()
if (input) {
input.value = this.currentField.value || ''
}
},
/**
* Fill the given FormData object with the field's internal value.
*/
fill(formData) {
formData.append(this.fieldAttribute, this.getInputElement().value || '')
},
},
}
</script>
15 changes: 15 additions & 0 deletions resources/js/field.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import IndexField from './components/Text/IndexField.vue'
import DetailField from './components/Text/DetailField.vue'
import FormField from './components/Text/FormField.vue'

import DetailTextareaField from './components/Textarea/DetailField.vue'
import FormTextareaField from './components/Textarea/FormField.vue'

Nova.booting((app, store) => {
app.component('index-japanese-transformer-text', IndexField)
app.component('detail-japanese-transformer-text', DetailField)
app.component('form-japanese-transformer-text', FormField)

app.component('detail-japanese-transformer-textarea', DetailTextareaField)
app.component('form-japanese-transformer-textarea', FormTextareaField)
})
Binary file added screenshots/transform.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions src/FieldServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Bocanhcam\NovaJapaneseTransformer;

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

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

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

namespace Bocanhcam\NovaJapaneseTransformer;

use Laravel\Nova\Fields\SupportsDependentFields;

trait HasTextTransform
{
use SupportsDependentFields;

public function toKatakana()
{
return $this->withMeta(['IMEMode' => 'toKatakana']);
}

public function toHiragana()
{
return $this->withMeta(['IMEMode' => 'toHiragana']);
}

public function options($options = [])
{
return $this->withMeta(['options' => $options]);
}
}
17 changes: 17 additions & 0 deletions src/JapaneseTransformerText.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Bocanhcam\NovaJapaneseTransformer;

use Laravel\Nova\Fields\Text;

class JapaneseTransformerText extends Text
{
use HasTextTransform;

/**
* The field's component.
*
* @var string
*/
public $component = 'japanese-transformer-text';
}
Loading

0 comments on commit 260a629

Please sign in to comment.