Slickr
Short description and motivation.
Usage
How to use my plugin.
Installation
Add these lines to your application's Gemfile:
gem 'active_admin_slickr'
gem 'slickr'
And then execute:
bundle
Or install them yourself as:
gem install active_admin_slickr
gem install slickr
Migrations
After installing the gem run:
rake db:migrate
CMS
If you don't already have webpacker installed run:
Add this line to your application's Gemfile:
gem 'webpacker', '~> 3.0.2'
And then execute:
$ bundle
Or install it yourself as:
$ gem install webpacker
Then install webpacker:
bundle exec rails Webpacker:install
Finally, to use Webpacker with React:
bundle exec rails webpacker:install:react
Generators
rails g slickr:install
then
yarn install
Stylesheets
Firstly, please comment out the default Active Admin stylesheets.
// Active Admin's got SASS!
// @import "active_admin/mixins";
// @import "active_admin/base";
Then add the following in active_admin.scss
:
@import 'active_admin_slickr';
@import 'slickr/slickr_styles';
Javascript
- In the
active_admin.js
file, you require:
//= require active_admin/base
//= require active_admin_slickr
//= require slickr/slickr_javascript
Roles
You will have some basic default roles added to your AdminUser model which you can easily add to. Roles are managed by CanCanCan and can be altered in the Ability model
Admin User
The AdminUser model is already setup through this gem so you can remove your own
version. If however you need to extend it you can still create the admin_users.rb
file within the admin
folder but set it up like so:
ActiveAdmin.register AdminUser, as: "Users" do
end
Model Ordering
Slickr uses acts_as_list for ordering. In order to use it in you app you must first
add a position
column to the require table:
rails g migration AddPositionToAdminUser position:integer
rake db:migrate
Then add acts_as_list to your model (and also a default scope if you need it):
class AdminUser < ActiveRecord::Base
acts_as_list
default_scope { order(position: :asc) }
end
In your Active Admin model you then need to add the following:
ActiveAdmin.register AdminUser do
config.sort_order = 'position_asc'
config.paginate = false
reorderable
...
index as: :reorderable_table do
...
end
...
end
That's it, you now have reorderable tables.
Extending Megadraft
In text editing mode, Megadraft has a range of options such as bold, italic, bullet list, etc. With this editor there is also the ability to add icons to the toolbar that can display info from your models.
When you run the generator, you will see that a new folder has been added to
the app/javascript
folder called slickr_extensions
. Additionally,
a new model is added under app/models/slickr/page.rb
.
In app/models/slickr/page.rb
you can add to additional_page_edit_paths
to include new methods to get info from a model. There is currently an example
method admin_user_index_path
which requests the admin index path and has
params of type: 'megadraft_admins')
.
When the icon is clicked in the Megadraft toolbar, this path will be requested which requires the controller action to be added to Active Admin AdminUser. For example add:
controller do
def index
if params[:type] == 'megadraft_admins'
@admins = AdminUser.all
index! do |format|
format.html { render :json => @admins.to_json }
end
else
index!
end
end
end
making sure the params match.
Extending Redux store
In slickr_extensions/page_edit/containers/additional_prop_types.js
the
propTypes are extended with our default but you can add to this as needed.
Next we need to handle state change which is done through slickr_extensions/page_edit/reducers/additional_reducers.js
. Again this is
based on our admins example and simply references a function that responds
to LOAD_ADMINS
to get the payload from the admin controller we added above.
The action to trigger this state change is at slickr_extensions/page_edit/actions/additional_actions.js
.
Custom Entities
See Megadraft custom entities for more info.
Megadraft ships with a default entity "LINK" and an according action in the toolbar that allows a user to type in an url. We are adding to it with "ADMIN_LINK" with an action that allows a user to select
an admin email. We extend the entity inputs from slickr_extensions/page_edit/components/content/additional_entity_inputs.js
and
agin you can add more as needed.
In order to render the custom entities, we need to define decorators as seen
in slickr_extensions/page_edit/actions/additional_actions.js
. Upon
highlighting text in the Megadraft editor and then clicking the admin
icon in the Megadraft toolbar, componentWillMount() is fired which in
this case is used to signify a state change in Megadraft and passes editorState
as "load_admins" which is handled in slickr_extensions/page_edit/components/content/editor_state_change.js
.
The action we setup above to load the admins is now fired and the render method of entity input is called. This renders a drop down menu on the screen and an array of admins with a value as a fake link and label of their email populates the drop down.
The value of this.props.url
in
<Select
name="form-field-name"
value={this.props.url}
options={admins}
onChange={this.onAdminChange}
/>
at this point is undefined but when an admin email is clicked, the rendering in
the editor is handled by slickr_extensions/page_edit/decorators/admin_link_component.jsx
.
The text you highlighted earlier is now wrapped with a link with an href of
the link you declared in the value of the drop down. The value of this.props.url
is now the href value.
Megadraft to HTML
The content generated by Megadraft needs to be converted to HTML to be displayed
in preview mode or in the front end. If you have added any custom entities you will
need to add to "DRAFTJS_CONFIG" in app/models/slickr/page.rb
by adding
'ADMIN_LINK' => DraftjsExporter::Entities::Link.new(className: 'admin__link')
for our example in "entity_decorators".
Page Layouts
For each page you create, you will select a page layout. We have included some
defaults in app/models/slickr/page.rb
in the "LAYOUTS" constant but you
can remove or add as many as you like.
For each layout listed in "LAYOUTS" you will need a corresponding file
at app/views/slickr_page_templates
with the same name like contact.html.erb
or contact.slim
.
The instance variable is accessed as slickr_page
and the megadraft content
as raw content
. So as a simple example the page could look as follows:
<h1><%= page["title"] %></h1>
<p><%= page["page_intro"] %></p>
<%= raw content %>
Megadraft Text Area
Slickr enables the Megadraft editor to be used in text area inputs which normal Active Admin resources. Below is an example for how to have a mix of normal text area fields and megadraft text areas:
form do |f|
f.inputs do
f.input :title
f.input :body_normal,
as: :text
render 'admin/form/text_area_helper', f: f, field: :body_megadraft
f.input :body_megadraft,
as: :text
end
f.actions
end
View Helper
In order to use the DraftJS output from Megadraft there is a helper available to use in your views:
<%= draftjs_to_html(@slickr_page, :body_megadraft) %>
replacing the instance variable with that generated in your controller and the second argument with whatever field has the DraftJS content.
Developing
During development you can use a local copy of the engine in your app and there are 2 options for doing this. One thing you'll have to do first is you change the slickr.yml file in the config folder. Comment out:
slickr: dist
and uncomment
slickr: package/slickr/packs
Option 1
In the main app, package.json file, replace:
"slickr": "git+https://github.com/primate-inc/slickr#master"
with a local copy like
"slickr": "file:/Users/primate/Documents/Projects/slickr"
and use the local copy of the engine to load into the main apps node_modules. This works well if you need to make changes to the codebase that does not involve the webpacker code.
Option 2
To live reload your changes on the local engine rather than loading a compiled version into the main app you can run the following from the engine:
yarn install
to install any missing packages. Then
yarn link
Now in your main app type
yarn link slickr
The local engine now takes precedence over the version in the main app node_modules folder and when you run the dev server in the main app with
./bin/webpack-dev-server
any changes you make to your engine react code will be live reloaded.
When you're done you can type
yarn unlink slickr
from the main app but note that you'll have to yarn install
again as the
slickr node module will be removed.
Contributing
Contribution directions go here.
License
The gem is available as open source under the terms of the MIT License.