inline_editor 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 613a54ae2b2094b2b3f65bd09076ad440296cdc656ce4d9bce885f1da216a11d
4
+ data.tar.gz: bba7a5f528f10bda0a6bb0bfc9766c8bc62585931336a1916665ad97d3c79f9b
5
+ SHA512:
6
+ metadata.gz: d68aaf7a3982b5213fb9a142a84e3910efb0c5e28f00c1527b625c8804c09e024100aeaa68ad9c7153f545adc9544f9a9e135d14454c2ef9b310f65b14206980
7
+ data.tar.gz: 4ecf2664588d9e1443c1d4fb5b4ba4d7f13e48714317e74788cc2bdf285baf543587cddc1002042a7835c3074c86b560187ac2babca627cf559573f61f475784
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2019 ShevchukTania
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # InlineEditor
2
+ [![Build Status](https://travis-ci.com/ShevchukTania/inline_editor.svg?branch=master)](https://travis-ci.com/ShevchukTania/inline_editor)
3
+ [![Maintainability](https://api.codeclimate.com/v1/badges/8ad754e23e17a293dac2/maintainability)](https://codeclimate.com/github/ShevchukTania/inline_editor/maintainability)
4
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/8ad754e23e17a293dac2/test_coverage)](https://codeclimate.com/github/ShevchukTania/inline_editor/test_coverage)
5
+
6
+ Demo app https://inline-editor.herokuapp.com
7
+
8
+ ![](https://raw.githubusercontent.com/ShevchukTania/inline_editor/master/spec/dummy/app/assets/images/preview.gif)
9
+
10
+ ## Steps to install
11
+ 1. Add this line to your application's Gemfile:
12
+ ```ruby
13
+ gem 'inline_editor'
14
+ ```
15
+ 1. Import 'inline_editor' to your application.js
16
+
17
+ ```javascript
18
+ //= require inline_editor
19
+ ```
20
+ Also, you could add styles to your application.sccs for your inlne editor
21
+
22
+ ```scss
23
+ @import "inline_editor"
24
+ ```
25
+
26
+ 1. In your views you could use **inline_editor** helper which generate markup for clickable item and form
27
+
28
+ **Exampeles:**
29
+
30
+ ```ruby
31
+ <%= inline_editor as: :select, text: post.title, value: post.title, collection: Post::TITLE,
32
+ save_url: inline_update_post_path(post), include_blank: false, param: 'title'%>
33
+ ```
34
+
35
+ Also, insteed of plain text you could use any helper which generate HTML view
36
+
37
+ ```ruby
38
+ <%= inline_editor as: :select, text: your_helper(post.title), value: post.title, collection: Post::TITLE,
39
+ save_url: inline_update_post_path(post), include_blank: false, param: 'title'%>
40
+ ```
41
+ Option | Type | Example
42
+ ------------------ | -------------| -------------
43
+ as |symbol |as: :select. type of form tag you want to generate
44
+ text |string/HTML |text: post.title, text: your_text_helper(post.title), the value will
45
+ value |string |value: post.title
46
+ collection |array |collection: Post::TITLE
47
+ save_url |string |save_url: inline_update_post_path(post)
48
+ include_blank |boolean |include_blank: false
49
+ param |string |param: 'title', this is your model attribute you want to change
50
+
51
+ For now it is available two parameter for **as:**
52
+ * :select
53
+ * :grouped_select
54
+
55
+ 1. Create action responsible for inline update
56
+
57
+ It may look like this:
58
+
59
+ ```ruby
60
+ def inline_update
61
+ @post = Post.find(params[:id])
62
+ if @post.update(post_params)
63
+ render json: { html: helpers.inline_editor_text(value: post_params.values.first, option: post_params.keys.first)}
64
+ else
65
+ render json: { status: 'error', message: @post.errors.full_messages.to_sentence }
66
+ end
67
+ end
68
+ ```
69
+ 1. Also there are several custom JavaScript events you could use to achive extra behaviour
70
+
71
+ * **inlineEditError** - triggered if your responce contains { status: 'error' }
72
+ * **inlineEditSuccess** - triggered after controller respond without error status
73
+
74
+
75
+ ## Contributing
76
+ Contribution directions go here.
77
+
78
+ ## License
79
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'InlineEditor'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ require 'bundler/gem_tasks'
18
+
19
+ require 'rake/testtask'
20
+
21
+ Rake::TestTask.new(:test) do |t|
22
+ t.libs << 'test'
23
+ t.pattern = 'test/**/*_test.rb'
24
+ t.verbose = false
25
+ end
26
+
27
+ task default: :test
@@ -0,0 +1,84 @@
1
+ document.addEventListener('DOMContentLoaded', function(){
2
+ document.querySelectorAll('.form select').forEach(select => {
3
+ select.addEventListener("change", function(e){
4
+ let data = {};
5
+ let target = e.currentTarget;
6
+ const url = target.dataset.url;
7
+ data[target.dataset.param] = target.querySelector('option:checked').text;
8
+
9
+ fetch(url, {
10
+ method: 'PUT',
11
+ body: JSON.stringify(data),
12
+ headers: { 'Content-Type': 'application/json' }
13
+ })
14
+ .then(response => {
15
+ return response.json();
16
+ })
17
+ .then(resultJson => {
18
+ const form = target.parentNode;
19
+ const hint = form.querySelector('span.inline-form-hint');
20
+ if (hint) {
21
+ hint.remove();
22
+ };
23
+
24
+ if (resultJson.status === 'error') {
25
+ form.dispatchEvent(createEvent('inlineEditError', resultJson));
26
+
27
+ form.classList.add('invalid-value');
28
+ if (resultJson.message) {
29
+ form.insertAdjacentHTML('beforeend',
30
+ "<span class='inline-form-hint'>" + resultJson.message + "</span>"
31
+ );
32
+ }
33
+ } else {
34
+ const container = form.parentNode;
35
+ let clicableItem = container.querySelector('.clickable-item');
36
+
37
+ form.dispatchEvent(createEvent('inlineEditSuccess', resultJson))
38
+
39
+ form.classList.remove('invalid-value');
40
+ clicableItem.innerHTML = '';
41
+ clicableItem.insertAdjacentHTML('beforeend', resultJson.html);
42
+ toggleVisibility(container);
43
+ }
44
+ })
45
+ .catch(function(error) {
46
+ console.log('Request failed', error)
47
+ });
48
+ });
49
+ });
50
+
51
+ document.querySelectorAll('.clickable-item').forEach(item => {
52
+ item.addEventListener("click", function(e){
53
+ const container = e.target.closest('.inline-editor-container');
54
+ toggleVisibility(container);
55
+ })
56
+
57
+ document.querySelector('body').addEventListener('click', function(e){
58
+ const activeForm = document.querySelector('.form.active');
59
+ const container = e.target.closest('.inline-editor-container')
60
+
61
+ if (activeForm && !(e.target.closest('.inline-editor-container'))) {
62
+ activeForm.classList.remove('active');
63
+ activeForm.classList.add('display-none');
64
+ activeForm.previousElementSibling.classList.remove('display-none');
65
+ }
66
+ });
67
+ });
68
+
69
+ function toggleVisibility(container) {
70
+ container.querySelectorAll('.clickable-item, .form').forEach(item => {
71
+ item.classList.toggle('display-none');
72
+ })
73
+
74
+ container.querySelector('.form').classList.toggle('active');
75
+ }
76
+
77
+ function createEvent(name, params) {
78
+ return event = new CustomEvent(name, {
79
+ detail: params,
80
+ bubbles: true,
81
+ cancelable: true
82
+ });
83
+ }
84
+ });
@@ -0,0 +1,69 @@
1
+ .inline-editor-container .display-none {
2
+ display: none;
3
+ }
4
+
5
+
6
+ .inline-editor-container .clickable-item {
7
+ cursor: pointer;
8
+ position: relative;
9
+ padding: 5px;
10
+ border: 2px solid transparent;
11
+ }
12
+
13
+ .inline-editor-container .clickable-item:after {
14
+ content: '';
15
+ background: url('icon-edit.svg') no-repeat 97% center;
16
+ display: block;
17
+ position: absolute;
18
+ width: 100%;
19
+ height: 100%;
20
+ right: 2px;
21
+ top: -2px;
22
+ padding: 1px;
23
+ border: 1px dashed #ccc;
24
+ visibility: hidden;
25
+ }
26
+
27
+ .inline-editor-container .clickable-item:hover:after {
28
+ visibility: visible;
29
+ }
30
+
31
+ .inline-editor-container .form {
32
+ width: 100%;
33
+ }
34
+
35
+ .inline-editor-container .clickable-item .with-label .label{
36
+ background: #1c9c14;
37
+ padding: 1px 3px;
38
+ border-radius: 3px;
39
+ font-size: 10px;
40
+ margin-left: 5px;
41
+ color: #fff;
42
+ }
43
+
44
+ .inline-editor-container .form.active.invalid-value * {
45
+ border-color: #ff0000;
46
+ }
47
+
48
+ .inline-editor-container .form.active.invalid-value span.inline-form-hint {
49
+ color: #ff0000;
50
+ font-size: 12px;
51
+ }
52
+
53
+ .inline-editor-container .form select {
54
+ width: 100%;
55
+ border: solid 2px #000;
56
+ padding: 5px 25px 5px 3px;
57
+ font-size: 16px;
58
+ font-family: "Times New Roman", Times, serif;
59
+ position: relative;
60
+ color: #000;
61
+ -webkit-appearance: none;
62
+ -moz-appearance: none;
63
+ -ms-appearance: none;
64
+ -o-appearance: none;
65
+ appearance: none;
66
+ box-shadow: none;
67
+ background: url('dropdown-arrow.svg') right no-repeat;
68
+ background-position: calc(100% - 5px) 50%;
69
+ }
@@ -0,0 +1,19 @@
1
+ <div class="inline-editor-container">
2
+ <div class='clickable-item'>
3
+ <%= raw text %>
4
+ </div>
5
+ <div class='form display-none'>
6
+
7
+ <%- if local_assigns[:as] == :select %>
8
+ <%= select_tag '', options_for_select(collection, value),
9
+ class: 'form-control select', include_blank: include_blank, data: { url: save_url, param: param }
10
+ %>
11
+ <% end %>
12
+
13
+ <%- if local_assigns[:as] == :grouped_select %>
14
+ <%= select_tag '', grouped_options_for_select(collection, value),
15
+ class: 'form-control select', include_blank: include_blank, data: { url: save_url, param: param }
16
+ %>
17
+ <% end %>
18
+ </div>
19
+ </div>
@@ -0,0 +1,21 @@
1
+ module InlineEditor
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ isolate_namespace InlineEditor
5
+
6
+ initializer 'inline_editor.assets_precompile', group: :all do |app|
7
+ app.config.assets.precompile += ['inline_editor/inline_editor.js', 'inline_editor/inline_editor.css']
8
+ end
9
+
10
+ initializer 'inline_editor.helpers' do
11
+ ActiveSupport.on_load :action_view do
12
+ ActionView::Base.send :include, InlineEditor::ApplicationHelper
13
+ end
14
+ end
15
+
16
+ config.generators do |g|
17
+ g.test_framework :rspec
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,4 @@
1
+ module InlineEditor
2
+ class Railtie < ::Rails::Railtie
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module InlineEditor
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,12 @@
1
+ require "inline_editor/engine"
2
+
3
+ module InlineEditor
4
+ module ApplicationHelper
5
+ def inline_editor(as: '', text: '', collection: '', value: '', include_blank: '', save_url: '', param: '', &block)
6
+ text = capture(&block) if block_given?
7
+
8
+ render 'inline_editor/inline_editor', as: as, text: text, collection: collection, value: value,
9
+ include_blank: include_blank, save_url: save_url, param: param
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :inline_editor do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inline_editor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - ShevchukTania
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-02-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mini_racer
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 1.3.6
51
+ type: :development
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '1.3'
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 1.3.6
61
+ description: Simple inline editor for Rails applications
62
+ email:
63
+ - taniabeley@ukr.net
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files: []
67
+ files:
68
+ - MIT-LICENSE
69
+ - README.md
70
+ - Rakefile
71
+ - app/assets/javascripts/inline_editor.js
72
+ - app/assets/stylesheets/inline_editor.css
73
+ - app/views/inline_editor/_inline_editor.erb
74
+ - lib/inline_editor.rb
75
+ - lib/inline_editor/engine.rb
76
+ - lib/inline_editor/railtie.rb
77
+ - lib/inline_editor/version.rb
78
+ - lib/tasks/inline_editor_tasks.rake
79
+ homepage: https://github.com/ShevchukTania/inline_editor
80
+ licenses:
81
+ - MIT
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubygems_version: 3.0.6
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: Inline editor for Rails applications
102
+ test_files: []