mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-05 04:34:37 +08:00
working version for steps first run
This commit is contained in:
parent
0757563d02
commit
550f563666
18 changed files with 381 additions and 72 deletions
1
Gemfile
1
Gemfile
|
@ -66,7 +66,6 @@ gem 'delayed_job_active_record'
|
|||
gem 'devise-async'
|
||||
gem 'ruby-graphviz', '~> 1.2' # Graphviz for rails
|
||||
gem 'tinymce-rails' # Rich text editor
|
||||
gem 'tinymce-rails-imageupload', '~> 4.0.0.beta'
|
||||
|
||||
gem 'base62' # Used for smart annotations
|
||||
gem 'newrelic_rpm'
|
||||
|
|
|
@ -311,9 +311,6 @@ GEM
|
|||
tilt (2.0.1)
|
||||
tinymce-rails (4.5.2)
|
||||
railties (>= 3.1.1)
|
||||
tinymce-rails-imageupload (4.0.17.beta.2)
|
||||
railties (>= 3.2, < 6)
|
||||
tinymce-rails (~> 4.0)
|
||||
turbolinks (2.5.3)
|
||||
coffee-rails
|
||||
tzinfo (1.2.2)
|
||||
|
@ -401,7 +398,6 @@ DEPENDENCIES
|
|||
spinjs-rails
|
||||
starscope
|
||||
tinymce-rails
|
||||
tinymce-rails-imageupload (~> 4.0.0.beta)
|
||||
turbolinks
|
||||
tzinfo-data
|
||||
uglifier (>= 1.3.0)
|
||||
|
|
|
@ -23,8 +23,8 @@ var TinyMCE = (function() {
|
|||
if (typeof tinyMCE != 'undefined') {
|
||||
tinyMCE.init({
|
||||
selector: 'textarea.tinymce',
|
||||
toolbar: ["undo redo | insert | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link | forecolor backcolor | uploadimage | codesample"],
|
||||
plugins: "uploadimage, link,advlist,codesample,autolink,lists,charmap,hr,anchor,searchreplace,wordcount,visualblocks,visualchars,insertdatetime,nonbreaking,save,contextmenu,directionality,paste,textcolor,colorpicker,textpattern,imagetools",
|
||||
toolbar: ["undo redo | insert | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link | forecolor backcolor | customimageuploader | codesample"],
|
||||
plugins: "customimageuploader,link,advlist,codesample,autolink,lists,charmap,hr,anchor,searchreplace,wordcount,visualblocks,visualchars,insertdatetime,nonbreaking,save,contextmenu,directionality,paste,textcolor,colorpicker,textpattern,imagetools",
|
||||
codesample_languages: [{"text":"R","value":"r"},{"text":"MATLAB","value":"matlab"},{"text":"Python","value":"python"},{"text":"JSON","value":"javascript"},{"text":"HTML/XML","value":"markup"},{"text":"JavaScript","value":"javascript"},{"text":"CSS","value":"css"},{"text":"PHP","value":"php"},{"text":"Ruby","value":"ruby"},{"text":"Java","value":"java"},{"text":"C","value":"c"},{"text":"C#","value":"csharp"},{"text":"C++","value":"cpp"}],
|
||||
removed_menuitems: 'newdocument',
|
||||
elementpath: false,
|
||||
|
@ -84,8 +84,7 @@ var TinyMCE = (function() {
|
|||
|
||||
});
|
||||
},
|
||||
codesample_content_css: '<%= asset_path('highlightjs-github-theme') %>',
|
||||
uploadimage_form_url: getTinyMceAssetsUploadPath()
|
||||
codesample_content_css: '<%= asset_path('highlightjs-github-theme') %>'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
|
@ -0,0 +1,235 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
tinymce.PluginManager.requireLangPack('customimageuploader');
|
||||
|
||||
tinymce.create('tinymce.plugins.CustomImageUploader', {
|
||||
CustomImageUploader: function(ed, url) {
|
||||
var form, iframe, win, throbber, editor = ed;
|
||||
function showDialog() {
|
||||
win = editor.windowManager.open({
|
||||
title: "<%= I18n.t 'tiny_mce.upload_window_title' %>",
|
||||
width: 520 + parseInt(editor.getLang(
|
||||
'customimageuploader.delta_width', 0
|
||||
), 10),
|
||||
height: 180 + parseInt(editor.getLang(
|
||||
'customimageuploader.delta_height', 0
|
||||
), 10),
|
||||
body: [
|
||||
{type: 'iframe', url: 'javascript:void(0)'},
|
||||
{type: 'textbox',
|
||||
name: 'file',
|
||||
label: "<%= I18n.t 'tiny_mce.upload_window_label' %>",
|
||||
subtype: 'file'},
|
||||
{type: 'container',
|
||||
classes: 'error',
|
||||
html: "<p style='color: #b94a48;'> </p>"},
|
||||
{type: 'container', classes: 'throbber'},
|
||||
],
|
||||
buttons: [
|
||||
{text: "<%= I18n.t 'tiny_mce.insert_btn' %>",
|
||||
onclick: insertImage,
|
||||
subtype: 'primary'},
|
||||
{text: "<%= I18n.t 'general.cancel' %>", onclick: ed.windowManager.close}
|
||||
],
|
||||
}, {
|
||||
plugin_url: url
|
||||
});
|
||||
|
||||
win.off('submit');
|
||||
win.on('submit', insertImage);
|
||||
|
||||
iframe = win.find('iframe')[0];
|
||||
form = createElement('form', {
|
||||
action: ed.getParam('customimageuploader_form_url',
|
||||
'/tinymce_assets'),
|
||||
target: iframe._id,
|
||||
method: 'POST',
|
||||
enctype: 'multipart/form-data',
|
||||
accept_charset: 'UTF-8',
|
||||
});
|
||||
|
||||
iframe.getEl().name = iframe._id;
|
||||
|
||||
// Create some needed hidden inputs
|
||||
form.appendChild(createElement('input',
|
||||
{type: 'hidden',
|
||||
name: 'utf8',
|
||||
value: '✓'}));
|
||||
form.appendChild(createElement('input',
|
||||
{type: 'hidden',
|
||||
name: 'authenticity_token',
|
||||
value: getMetaContents('csrf-token')}));
|
||||
form.appendChild(createElement('input',
|
||||
{type: 'hidden',
|
||||
name: 'object_type',
|
||||
value: $(ed.getElement())
|
||||
.data('object-type')}));
|
||||
form.appendChild(createElement('input',
|
||||
{type: 'hidden',
|
||||
name: 'object_id',
|
||||
value: $(ed.getElement())
|
||||
.data('object-id')}));
|
||||
form.appendChild(createElement('input',
|
||||
{type: 'hidden',
|
||||
name: 'hint',
|
||||
value: ed.getParam('uploadimage_hint', '')}));
|
||||
|
||||
var el = win.getEl();
|
||||
var body = document.getElementById(el.id + '-body');
|
||||
|
||||
// Copy everything TinyMCE made into our form
|
||||
var containers = body.getElementsByClassName('mce-container');
|
||||
for(var i = 0; i < containers.length; i++) {
|
||||
form.appendChild(containers[i]);
|
||||
}
|
||||
|
||||
var inputs = form.getElementsByTagName('input');
|
||||
for(var i = 0; i < inputs.length; i++) {
|
||||
var ctrl = inputs[i];
|
||||
|
||||
if(ctrl.tagName.toLowerCase() == 'input' && ctrl.type != 'hidden') {
|
||||
if(ctrl.type == 'file') {
|
||||
ctrl.name = 'file';
|
||||
|
||||
tinymce.DOM.setStyles(ctrl, {
|
||||
'border': 0,
|
||||
'boxShadow': 'none',
|
||||
'webkitBoxShadow': 'none',
|
||||
});
|
||||
} else {
|
||||
ctrl.name = 'alt';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body.appendChild(form);
|
||||
}
|
||||
|
||||
function insertImage() {
|
||||
if(getInputValue('file') == '') {
|
||||
return handleError("<%= I18n.t 'tiny_mce.error_message'");
|
||||
}
|
||||
|
||||
throbber = new top.tinymce.ui.Throbber(win.getEl());
|
||||
throbber.show();
|
||||
|
||||
clearErrors();
|
||||
|
||||
/* Add event listeners.
|
||||
* We remove the existing to avoid them being called twice in case
|
||||
* of errors and re-submitting afterwards.
|
||||
*/
|
||||
var target = iframe.getEl();
|
||||
if(target.attachEvent) {
|
||||
target.detachEvent('onload', uploadDone);
|
||||
target.attachEvent('onload', uploadDone);
|
||||
} else {
|
||||
target.removeEventListener('load', uploadDone);
|
||||
target.addEventListener('load', uploadDone, false);
|
||||
}
|
||||
|
||||
form.submit();
|
||||
}
|
||||
|
||||
function uploadDone() {
|
||||
if(throbber) {
|
||||
throbber.hide();
|
||||
}
|
||||
|
||||
var target = iframe.getEl();
|
||||
if(target.document || target.contentDocument) {
|
||||
var doc = target.contentDocument || target.contentWindow.document;
|
||||
handleResponse(doc.getElementsByTagName("body")[0].innerHTML);
|
||||
} else {
|
||||
handleError("Didn't get a response from the server");
|
||||
}
|
||||
}
|
||||
|
||||
function handleResponse(ret) {
|
||||
try {
|
||||
var json = tinymce.util.JSON.parse(ret);
|
||||
|
||||
if(json['error']) {
|
||||
handleError(json['error']['message']);
|
||||
} else {
|
||||
ed.execCommand('mceInsertContent', false, buildHTML(json));
|
||||
ed.windowManager.close();
|
||||
}
|
||||
} catch(e) {
|
||||
handleError('Got a bad response from the server');
|
||||
}
|
||||
}
|
||||
|
||||
function clearErrors() {
|
||||
var message = win.find('.error')[0].getEl();
|
||||
|
||||
if(message)
|
||||
message.getElementsByTagName('p')[0].innerHTML = ' ';
|
||||
}
|
||||
|
||||
function handleError(error) {
|
||||
var message = win.find('.error')[0].getEl();
|
||||
|
||||
if(message)
|
||||
message.getElementsByTagName('p')[0].innerHTML = ed.translate(error);
|
||||
}
|
||||
|
||||
function createElement(element, attributes) {
|
||||
var el = document.createElement(element);
|
||||
for(var property in attributes) {
|
||||
if (!(attributes[property] instanceof Function)) {
|
||||
el[property] = attributes[property];
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
function buildHTML(json) {
|
||||
var imgstr = "<img src='" + json['image']['url'] + "'";
|
||||
imgstr += " data-token='" + json['image']['token'] + "'"
|
||||
imgstr += " alt='description-" + json['image']['token'] + "'/>";
|
||||
return imgstr;
|
||||
}
|
||||
|
||||
function getInputValue(name) {
|
||||
var inputs = form.getElementsByTagName('input');
|
||||
|
||||
for(var i in inputs)
|
||||
if(inputs[i].name == name)
|
||||
return inputs[i].value;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
function getMetaContents(mn) {
|
||||
var m = document.getElementsByTagName('meta');
|
||||
|
||||
for(var i in m)
|
||||
if(m[i].name == mn)
|
||||
return m[i].content;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Add a button that opens a window
|
||||
editor.addButton('customimageuploader', {
|
||||
tooltip: ed.translate('Insert an image from your computer'),
|
||||
icon: 'image',
|
||||
onclick: showDialog
|
||||
});
|
||||
|
||||
// Adds a menu item to the tools menu
|
||||
editor.addMenuItem('customimageuploader', {
|
||||
text: ed.translate('Insert an image from your computer'),
|
||||
icon: 'image',
|
||||
context: 'insert',
|
||||
onclick: showDialog
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
tinymce.PluginManager.add('customimageuploader',
|
||||
tinymce.plugins.CustomImageUploader);
|
||||
})();
|
|
@ -1,6 +1,7 @@
|
|||
class StepsController < ApplicationController
|
||||
include ActionView::Helpers::TextHelper
|
||||
include ApplicationHelper
|
||||
include TinyMceHelper
|
||||
include StepsActions
|
||||
|
||||
before_action :load_vars, only: [:edit, :update, :destroy, :show]
|
||||
|
@ -28,7 +29,8 @@ class StepsController < ApplicationController
|
|||
|
||||
def create
|
||||
@step = Step.new(step_params)
|
||||
|
||||
# gerate a tag that replaces img tag in database
|
||||
@step.description = parse_tiny_mce_asset_to_token(@step.description)
|
||||
@step.completed = false
|
||||
@step.position = @protocol.number_of_steps
|
||||
@step.protocol = @protocol
|
||||
|
@ -52,6 +54,7 @@ class StepsController < ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
if @step.save
|
||||
|
||||
# Post process all assets
|
||||
@step.assets.each do |asset|
|
||||
asset.post_process_file(@protocol.team)
|
||||
|
@ -119,6 +122,7 @@ class StepsController < ApplicationController
|
|||
end
|
||||
|
||||
def edit
|
||||
@step.description = generate_image_tag_from_token(@step.description)
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: {
|
||||
|
@ -158,6 +162,10 @@ class StepsController < ApplicationController
|
|||
table.team = current_team
|
||||
end
|
||||
|
||||
# gerate a tag that replaces img tag in database
|
||||
@step.description = parse_tiny_mce_asset_to_token(@step.description,
|
||||
@step)
|
||||
|
||||
if @step.save
|
||||
@step.reload
|
||||
|
||||
|
|
|
@ -1,17 +1,27 @@
|
|||
class TinyMceAssetsController < ApplicationController
|
||||
before_action :find_object
|
||||
|
||||
def create
|
||||
step = Step.find_by_id(params[:step])
|
||||
image = Asset.create(file: params[:file],
|
||||
created_by: current_user,
|
||||
team: current_team)
|
||||
image.file.reprocess_without_delay!(:original)
|
||||
byebug
|
||||
render json: {
|
||||
image: {
|
||||
url: view_context.image_url(image.url(:original))
|
||||
}
|
||||
}, content_type: 'text/html'
|
||||
image = params.fetch(:file) { render_404 }
|
||||
tiny_img = TinyMceAsset.new(image: image, reference: @obj, editing: true)
|
||||
if tiny_img.save
|
||||
render json: {
|
||||
image: {
|
||||
url: view_context.image_url(tiny_img.url(:original)),
|
||||
token: Base62.encode(tiny_img.id)
|
||||
}
|
||||
}, content_type: 'text/html'
|
||||
else
|
||||
render_404
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_object
|
||||
obj_type = params.fetch(:object_type) { render_404 }
|
||||
obj_id = params.fetch(:object_id) { render_404 }
|
||||
render_404 unless ['step', 'result_text'].include? obj_type
|
||||
@obj = obj_type.classify.constantize.find_by_id(obj_id)
|
||||
end
|
||||
end
|
||||
|
|
27
app/helpers/tiny_mce_helper.rb
Normal file
27
app/helpers/tiny_mce_helper.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
require 'nokogiri'
|
||||
module TinyMceHelper
|
||||
def parse_tiny_mce_asset_to_token(text, ref = nil)
|
||||
html = Nokogiri::HTML(text)
|
||||
html.search('img').each do |img|
|
||||
next unless img['data-token']
|
||||
img_id = Base62.decode(img['data-token'])
|
||||
token = "[~tiny_mce_id:#{img_id}]"
|
||||
img.replace(token)
|
||||
byebug
|
||||
next unless ref
|
||||
tiny_img = TinyMceAsset.find_by_id(img_id)
|
||||
tiny_img.reference = ref unless tiny_img.step || tiny_img.result_text
|
||||
tiny_img.save
|
||||
end
|
||||
html
|
||||
end
|
||||
|
||||
def generate_image_tag_from_token(text, ref = nil)
|
||||
regex = /\[~tiny_mce_id:([0-9a-zA-Z]+)\]/
|
||||
new_text = text.gsub(regex) do |el|
|
||||
match = el.match(regex)
|
||||
img = TinyMceAsset.find_by_id(match[1])
|
||||
image_tag img.url, data: { token: Base62.encode(img.id) }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -4,6 +4,6 @@ class ResultText < ActiveRecord::Base
|
|||
presence: true,
|
||||
length: { maximum: Constants::RICH_TEXT_MAX_LENGTH }
|
||||
validates :result, presence: true
|
||||
|
||||
belongs_to :result, inverse_of: :result_text
|
||||
has_many :tiny_mce_assets, inverse_of: :result_text
|
||||
end
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
class StepTinyMceAsset < ActiveRecord::Base
|
||||
belongs_to :step
|
||||
belongs_to :asset
|
||||
end
|
51
app/models/tiny_mce_asset.rb
Normal file
51
app/models/tiny_mce_asset.rb
Normal file
|
@ -0,0 +1,51 @@
|
|||
class TinyMceAsset < ActiveRecord::Base
|
||||
attr_accessor :reference
|
||||
before_create :set_reference
|
||||
|
||||
belongs_to :step
|
||||
belongs_to :result_text
|
||||
has_attached_file :image,
|
||||
styles: { medium: [Constants::MEDIUM_PIC_FORMAT, :jpg] },
|
||||
convert_options: { medium: '-quality 70 -strip' }
|
||||
|
||||
validates_attachment_content_type :image,
|
||||
content_type: %r{^image/#{ Regexp.union(
|
||||
Constants::WHITELISTED_IMAGE_TYPES
|
||||
) }}
|
||||
# When using S3 file upload, we can limit file accessibility with url signing
|
||||
def presigned_url(style = :medium,
|
||||
download: false,
|
||||
timeout: Constants::URL_SHORT_EXPIRE_TIME)
|
||||
if stored_on_s3?
|
||||
if download
|
||||
download_arg = 'attachment; filename=' + URI.escape(image_file_name)
|
||||
else
|
||||
download_arg = nil
|
||||
end
|
||||
|
||||
signer = Aws::S3::Presigner.new(client: S3_BUCKET.client)
|
||||
signer.presigned_url(:get_object,
|
||||
bucket: S3_BUCKET.name,
|
||||
key: image.path(style)[1..-1],
|
||||
expires_in: timeout,
|
||||
response_content_disposition: download_arg)
|
||||
end
|
||||
end
|
||||
|
||||
def stored_on_s3?
|
||||
image.options[:storage].to_sym == :s3
|
||||
end
|
||||
|
||||
def url(style = :medium, timeout: Constants::URL_SHORT_EXPIRE_TIME)
|
||||
if image.is_stored_on_s3?
|
||||
presigned_url(style, timeout: timeout)
|
||||
else
|
||||
image.url(style)
|
||||
end
|
||||
end
|
||||
|
||||
def set_reference
|
||||
obj_type = "#{@reference.class.to_s.underscore}=".to_sym
|
||||
self.public_send(obj_type, @reference) if @reference
|
||||
end
|
||||
end
|
|
@ -27,7 +27,7 @@
|
|||
<div class="tab-pane active" role="tabpanel" id="new-step-main">
|
||||
<%= f.text_field :name, label: t("protocols.steps.new.name"), placeholder: t("protocols.steps.new.name_placeholder") %>
|
||||
<div class="form-group">
|
||||
<%= f.tiny_mce_editor(:description, tiny_mce_upload_path: tiny_mce_assets_path(step: @step) ) %>
|
||||
<%= f.tiny_mce_editor(:description, data: { object_type: 'step', object_id: @step.id }) %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" role="tabpanel" id="new-step-checklists">
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
<em><%= t('protocols.steps.no_description') %></em>
|
||||
<% else %>
|
||||
<div class="ql-editor">
|
||||
<%= custom_auto_link(step.description,
|
||||
<%= custom_auto_link(generate_image_tag_from_token(step.description),
|
||||
simple_format: false,
|
||||
tags: ['img']) %>
|
||||
</div>
|
||||
|
|
|
@ -1567,7 +1567,11 @@ en:
|
|||
expired_description: 'The downloadable file expires in 3 days after its creation.'
|
||||
# This section contains general words that can be used in any parts of
|
||||
# application.
|
||||
|
||||
tiny_mce:
|
||||
upload_window_title: 'Insert an image from your computer'
|
||||
upload_window_label: 'Choose an image'
|
||||
insert_btn: 'Insert'
|
||||
error_message: 'You must choose a file'
|
||||
general:
|
||||
save: "Save"
|
||||
update: "Update"
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
class CreateStepTinyMceAssets < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :step_tiny_mce_assets do |t|
|
||||
t.references :step, index: true, foreign_key: true
|
||||
t.references :asset, index: true, foreign_key: true
|
||||
t.boolean :edited, default: false
|
||||
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,11 @@
|
|||
class AddAttachmentImageToTinyMceAssets < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :tiny_mce_assets do |t|
|
||||
t.attachment :image
|
||||
t.boolean :editing, default: false
|
||||
t.references :step, index: true
|
||||
t.references :result_text, index: true
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
end
|
30
db/schema.rb
30
db/schema.rb
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20170419143608) do
|
||||
ActiveRecord::Schema.define(version: 20170420075905) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
@ -486,17 +486,6 @@ ActiveRecord::Schema.define(version: 20170419143608) do
|
|||
|
||||
add_index "step_tables", ["step_id", "table_id"], name: "index_step_tables_on_step_id_and_table_id", unique: true, using: :btree
|
||||
|
||||
create_table "step_tiny_mce_assets", force: :cascade do |t|
|
||||
t.integer "step_id"
|
||||
t.integer "asset_id"
|
||||
t.boolean "edited", default: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
add_index "step_tiny_mce_assets", ["asset_id"], name: "index_step_tiny_mce_assets_on_asset_id", using: :btree
|
||||
add_index "step_tiny_mce_assets", ["step_id"], name: "index_step_tiny_mce_assets_on_step_id", using: :btree
|
||||
|
||||
create_table "steps", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.string "description"
|
||||
|
@ -571,6 +560,21 @@ ActiveRecord::Schema.define(version: 20170419143608) do
|
|||
t.datetime "file_updated_at"
|
||||
end
|
||||
|
||||
create_table "tiny_mce_assets", force: :cascade do |t|
|
||||
t.string "image_file_name"
|
||||
t.string "image_content_type"
|
||||
t.integer "image_file_size"
|
||||
t.datetime "image_updated_at"
|
||||
t.boolean "editing", default: false
|
||||
t.integer "step_id"
|
||||
t.integer "result_text_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
add_index "tiny_mce_assets", ["result_text_id"], name: "index_tiny_mce_assets_on_result_text_id", using: :btree
|
||||
add_index "tiny_mce_assets", ["step_id"], name: "index_tiny_mce_assets_on_step_id", using: :btree
|
||||
|
||||
create_table "tokens", force: :cascade do |t|
|
||||
t.string "token", null: false
|
||||
t.integer "ttl", null: false
|
||||
|
@ -801,8 +805,6 @@ ActiveRecord::Schema.define(version: 20170419143608) do
|
|||
add_foreign_key "step_assets", "steps"
|
||||
add_foreign_key "step_tables", "steps"
|
||||
add_foreign_key "step_tables", "tables"
|
||||
add_foreign_key "step_tiny_mce_assets", "assets"
|
||||
add_foreign_key "step_tiny_mce_assets", "steps"
|
||||
add_foreign_key "steps", "protocols"
|
||||
add_foreign_key "steps", "users"
|
||||
add_foreign_key "steps", "users", column: "last_modified_by_id"
|
||||
|
|
11
test/fixtures/step_tiny_mce_assets.yml
vendored
11
test/fixtures/step_tiny_mce_assets.yml
vendored
|
@ -1,11 +0,0 @@
|
|||
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
|
||||
|
||||
one:
|
||||
step_id:
|
||||
asset_id:
|
||||
edited: false
|
||||
|
||||
two:
|
||||
step_id:
|
||||
asset_id:
|
||||
edited: false
|
|
@ -1,7 +0,0 @@
|
|||
require 'test_helper'
|
||||
|
||||
class StepTinyMceAssetTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
Loading…
Add table
Reference in a new issue