Skip to content

Commit

Permalink
feature: Trix field (#107)
Browse files Browse the repository at this point in the history
Co-authored-by: Adrian Marin <[email protected]>
  • Loading branch information
mihaimdm22 and adrianthedev authored Sep 23, 2020
1 parent 8761ee9 commit 622b95d
Show file tree
Hide file tree
Showing 12 changed files with 267 additions and 33 deletions.
43 changes: 43 additions & 0 deletions app/frontend/js/components/Edit/TrixField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<template>
<edit-field-wrapper :field="field" :errors="errors" :index="index" :value-slot-full-width="true">
<VueTrix v-model="editorContent"
:placeholder="field.placeholder"
class="w-full prose prose-sm"
inputId="trixEditor"
/>
</edit-field-wrapper>
</template>

<script>
import FormField from '@/js/mixins/form-field'
import VueTrix from 'vue-trix'
export default {
mixins: [FormField],
components: {
VueTrix,
},
data() {
return {
editorContent: this.field.value,
}
},
methods: {
setInitialValue() {
this.editorContent = this.field.value
},
getValue() {
return this.editorContent
},
focus() {
if (this.$refs['field-input']) this.$refs['field-input'].$emit('focus')
},
},
}
</script>

<style>
.trix-content pre {
background-color: #2D3648 !important;
}
</style>
46 changes: 46 additions & 0 deletions app/frontend/js/components/Show/TrixField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<template>
<show-field-wrapper :field="field" :index="index" :value-slot-full-width="true">
<div v-if="field.value">
<div v-if="showTrix" v-html="field.value" class="prose prose-sm"/>
<a href="javascript:void(0);"
v-if="!field.always_show"
:class="buttonStyle"
@click="toggleTrix"
v-text="linkLabel"
/>
</div>
<empty-dash v-else />
</show-field-wrapper>
</template>

<script>
export default {
props: ['field', 'index'],
data() {
return {
showTrix: this.field.always_show,
}
},
computed: {
buttonStyle() {
if (this.showTrix) return 'font-bold inline-block mt-6'
return 'font-bold'
},
linkLabel() {
return this.showTrix ? 'Hide Content' : 'Show Content'
},
},
methods: {
toggleTrix() {
this.showTrix = !this.showTrix
},
},
}
</script>

<style>
.prose {
max-width: none !important;
}
</style>
2 changes: 2 additions & 0 deletions app/frontend/js/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Vue.component('show-country-field', require('@/js/components/Sh
Vue.component('show-badge-field', require('@/js/components/Show/BadgeField.vue').default)
Vue.component('show-heading-field', require('@/js/components/Show/HeadingField.vue').default)
Vue.component('show-code-field', require('@/js/components/Show/CodeField.vue').default)
Vue.component('show-trix-field', require('@/js/components/Show/TrixField.vue').default)

Vue.component('edit-field-wrapper', require('@/js/components/Edit/FieldWrapper.vue').default)
Vue.component('edit-id-field', require('@/js/components/Edit/IdField.vue').default)
Expand All @@ -70,6 +71,7 @@ Vue.component('edit-country-field', require('@/js/components/Ed
Vue.component('edit-heading-field', require('@/js/components/Show/HeadingField.vue').default)
Vue.component('edit-code-field', require('@/js/components/Edit/CodeField.vue').default)
Vue.component('edit-hidden-field', require('@/js/components/Edit/HiddenField.vue').default)
Vue.component('edit-trix-field', require('@/js/components/Edit/TrixField.vue').default)

// Form Fields
Vue.component('input-component', require('@/js/components/InputComponent.vue').default)
Expand Down
25 changes: 25 additions & 0 deletions lib/avo/app/fields/trix_field.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require_relative 'field'

module Avo
module Fields
class TrixField < Field
def initialize(name, **args, &block)
@defaults = {
component: 'trix-field',
}

super(name, **args, &block)

hide_on :index

@always_show = args[:always_show].present? ? args[:always_show] : false
end

def hydrate_field(fields, model, resource, view)
{
always_show: @always_show
}
end
end
end
end
4 changes: 4 additions & 0 deletions lib/avo/app/resource_fields.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ def get_fields
def add_field(resource, field)
@@fields[resource].push field
end

def trix(name, **args, &block)
@@fields[self].push Avo::Fields::TrixField::new(name, **args, &block)
end
end
end
end
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"dependencies": {
"@rails/activestorage": "^6.0.2-1",
"@rails/webpacker": "^4.2.2",
"@tailwindcss/typography": "^0.2.0",
"autoprefixer": "^9.7.4",
"axios": "^0.19.2",
"css-loader": "^3.5.3",
Expand Down Expand Up @@ -58,6 +59,7 @@
"vue-svg-loader": "^0.16.0",
"vue-template-compiler": "^2.6.11",
"vue-toasted": "^1.1.28",
"vue-trix": "^1.1.11",
"vue-turbolinks": "^2.1.0",
"vuejs-paginate": "^2.1.0",
"vuex": "^3.5.1",
Expand Down
3 changes: 2 additions & 1 deletion spec/dummy/app/avo/resources/post.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ def initialize
fields do
id
text :name, required: true
textarea :body, nullable: true, null_values: ['0', '', 'null', 'nil'], format_using: -> (value) { value.to_s.truncate 100 }
trix :body, placeholder: 'Enter text', always_show: false
file :cover_photo, is_image: true
boolean :is_featured
boolean :is_published do |model|
model.published_at.present?
end


belongs_to :user, searchable: false, placeholder: '—'
end

Expand Down
2 changes: 1 addition & 1 deletion spec/dummy/app/avo/resources/team.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def initialize
fields do
id
text :name
textarea :description, rows: 5, readonly: false, hide_on: :index, format_using: -> (value) { value.to_s.truncate 30 }, required: true, default: 'This team is wonderful!'
textarea :description, rows: 5, readonly: false, hide_on: :index, format_using: -> (value) { value.to_s.truncate 30 }, default: 'This team is wonderful!', nullable: true, null_values: ['0', '', 'null', 'nil']

number :members_count do |model|
model.members.count
Expand Down
62 changes: 31 additions & 31 deletions spec/system/avo/nullable_field_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,76 +2,76 @@

RSpec.describe 'NullableField', type: :system do
describe 'without input (specifying null_values: ["", "0", "null", "nil"])' do
let!(:post) { create :post, body: nil }
let!(:team) { create :team, description: nil }

context 'show' do
it 'displays the posts empty body (dash)' do
visit "/avo/resources/post/#{post.id}"
it 'displays the teams empty description (dash)' do
visit "/avo/resources/teams/#{team.id}"

expect(find_field_value_element('body')).to have_text empty_dash
expect(find_field_value_element('description')).to have_text empty_dash
end
end

context 'edit' do
it 'has the posts body empty' do
visit "/avo/resources/posts/#{post.id}/edit"
it 'has the teams description empty' do
visit "/avo/resources/teams/#{team.id}/edit"

expect(find_field('body').value).to eq ''
expect(find_field('description').value).to eq ''
end
end
end

describe 'with regular input (specifying null_values: ["", "0", "null", "nil"])' do
let!(:post) { create :post, body: 'descr' }
let!(:team) { create :team, description: 'descr' }

context 'edit' do
it 'has the posts body prefilled' do
visit "/avo/resources/posts/#{post.id}/edit"
it 'has the teams description prefilled' do
visit "/avo/resources/teams/#{team.id}/edit"

expect(find_field('body').value).to eq 'descr'
expect(find_field('description').value).to eq 'descr'
end
it 'changes the posts body to null ("" - empty string)' do
visit "/avo/resources/posts/#{post.id}/edit"
it 'changes the teams description to null ("" - empty string)' do
visit "/avo/resources/teams/#{team.id}/edit"

fill_in 'body', with: ''
fill_in 'description', with: ''
click_on 'Save'
wait_for_loaded

expect(current_path).to eql "/avo/resources/posts/#{post.id}"
expect(find_field_value_element('body')).to have_text empty_dash
expect(current_path).to eql "/avo/resources/teams/#{team.id}"
expect(find_field_value_element('description')).to have_text empty_dash
end

it 'changes the posts body to null ("0")' do
visit "/avo/resources/posts/#{post.id}/edit"
it 'changes the teams description to null ("0")' do
visit "/avo/resources/teams/#{team.id}/edit"

fill_in 'body', with: '0'
fill_in 'description', with: '0'
click_on 'Save'
wait_for_loaded

expect(current_path).to eql "/avo/resources/posts/#{post.id}"
expect(find_field_value_element('body')).to have_text empty_dash
expect(current_path).to eql "/avo/resources/teams/#{team.id}"
expect(find_field_value_element('description')).to have_text empty_dash
end

it 'changes the posts body to null ("nil")' do
visit "/avo/resources/posts/#{post.id}/edit"
it 'changes the teams description to null ("nil")' do
visit "/avo/resources/teams/#{team.id}/edit"

fill_in 'body', with: 'nil'
fill_in 'description', with: 'nil'
click_on 'Save'
wait_for_loaded

expect(current_path).to eql "/avo/resources/posts/#{post.id}"
expect(find_field_value_element('body')).to have_text empty_dash
expect(current_path).to eql "/avo/resources/teams/#{team.id}"
expect(find_field_value_element('description')).to have_text empty_dash
end

it 'changes the postss body to null ("null")' do
visit "/avo/resources/posts/#{post.id}/edit"
it 'changes the teams description to null ("null")' do
visit "/avo/resources/teams/#{team.id}/edit"

fill_in 'body', with: 'null'
fill_in 'description', with: 'null'
click_on 'Save'
wait_for_loaded

expect(current_path).to eql "/avo/resources/posts/#{post.id}"
expect(find_field_value_element('body')).to have_text empty_dash
expect(current_path).to eql "/avo/resources/teams/#{team.id}"
expect(find_field_value_element('description')).to have_text empty_dash
end
end
end
Expand Down
93 changes: 93 additions & 0 deletions spec/system/avo/trix_field_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
require 'rails_helper'

RSpec.describe 'TrixField', type: :system do
describe 'without value' do
let!(:post) { create :post , body: '' }

context 'show' do
it 'displays the posts empty body (dash)' do
visit "/avo/resources/posts/#{post.id}"

expect(find_field_element('body')).to have_text empty_dash
end
end

context 'edit' do
it 'has the posts body label and empty trix editor and placeholder' do
visit "/avo/resources/posts/#{post.id}/edit"

body_element = find_field_element('body')

expect(body_element).to have_text 'Body'

expect(find(:xpath, "//trix-editor[@input='trixEditor']")[:placeholder]).to have_text('Enter text')
expect(find_trix_editor('trixEditor')).to have_text('')
end

it 'change the posts body text' do
visit "/avo/resources/posts/#{post.id}/edit"

fill_in_trix_editor 'trixEditor', with: 'Works for us!!!'

click_on 'Save'
wait_for_loaded

click_on 'Show Content'

expect(find_field_value_element('body')).to have_text 'Works for us!!!'
end
end
end

describe 'with regular value' do
let!(:body) { 'Example trix text.' }
let!(:post) { create :post , body: body }

context 'show' do
it 'displays the posts body' do
visit "/avo/resources/posts/#{post.id}"

click_on 'Show Content'

expect(find_field_value_element('body')).to have_text body
end
end

context 'edit' do
it 'has the posts body label' do
visit "/avo/resources/posts/#{post.id}/edit"

body_element = find_field_element('body')

expect(body_element).to have_text 'Body'
end

it 'has filled simple text in trix editor' do
visit "/avo/resources/posts/#{post.id}/edit"

expect(find_trix_editor('trixEditor').value).to eq('<div>' + body + '</div>')
end

it 'change the posts body trix to another simple text value' do
visit "/avo/resources/posts/#{post.id}/edit"

fill_in_trix_editor 'trixEditor', with: 'New example!'

click_on 'Save'
wait_for_loaded

click_on 'Show Content'

expect(find_field_value_element('body')).to have_text 'New example!'
end
end
end

def fill_in_trix_editor(id, with:)
find(:xpath, "//trix-editor[@input='#{id}']").click.set(with)
end

def find_trix_editor(id)
find(:xpath, "//*[@id='#{id}']", visible: false)
end
end
1 change: 1 addition & 0 deletions tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ module.exports = {
cursor: ['responsive', 'disabled'],
},
plugins: [
require('@tailwindcss/typography'),
// buttons
plugin(({ addComponents, theme }) => {
const styles = {
Expand Down
Loading

0 comments on commit 622b95d

Please sign in to comment.