Revision 5e2b847d
Added by Amos Benari over 10 years ago
app/assets/javascripts/config_template.js | ||
---|---|---|
var $editor
|
||
|
||
$(function() {
|
||
var template_text = $(".template_text");
|
||
if ($.browser && $.browser.msie && $.browser.version.slice(0,1) < 10) {
|
||
$('.subnav').hide();
|
||
if ($('.diffMode').size() >0) {
|
||
IE_diff_mode(template_text);
|
||
}
|
||
}else{
|
||
if (template_text.size() >0 ) { create_editor(template_text) };
|
||
if ($('.diffMode').size() >0) {
|
||
set_diff_mode(template_text);
|
||
} else {
|
||
set_edit_mode(template_text);
|
||
}
|
||
$('#config_template_submit').on('click', function(){
|
||
if($('.diffMode').size() >0){ set_edit_mode( $(".template_text")); }
|
||
})
|
||
}
|
||
$(document).on('ContentLoad', function(){onEditorLoad()});
|
||
|
||
$(".template_file").on("change", function(evt){
|
||
if ($(".template_file").val() == "") return;
|
||
|
||
if(window.File && window.FileList && window.FileReader)
|
||
{
|
||
var answer = confirm(_("You are about to override the editor content, are you sure?"))
|
||
if (!answer) { $('.template_file').val(""); return;}
|
||
|
||
var files = evt.target.files; // files is a FileList object
|
||
for (var i = 0, f; f = files[i]; i++) {
|
||
var reader = new FileReader();
|
||
// Closure to capture the file information.
|
||
reader.onloadend = function(evt) {
|
||
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
|
||
$('#new').text(( evt.target.result));
|
||
set_edit_mode($('.template_text'));
|
||
}
|
||
};
|
||
// Read in the file as text.
|
||
reader.readAsText(f);
|
||
$('.template_file').val("");
|
||
}
|
||
}else{
|
||
//Set editor in read only mode
|
||
$editor.setTheme("ace/theme/clouds");
|
||
$editor.setReadOnly(true);
|
||
}
|
||
$(document).on('click','#config_template_submit', function(){
|
||
if($('.diffMode').exists()){
|
||
set_edit_mode( $(".template_text"));
|
||
}
|
||
})
|
||
|
||
})
|
||
$(document).on('change', '.template_file', function(e){
|
||
if ($('.template_file').val() != '') upload_file(e);
|
||
})
|
||
|
||
$("#keybinding").on("change", function() {
|
||
var vim = require("ace/keyboard/vim").handler;
|
||
var emacs = require("ace/keyboard/emacs").handler;
|
||
var keybindings = [
|
||
null, // Null = use "default" keymapping
|
||
vim,
|
||
emacs];
|
||
$(document).on('change','#keybinding', function(){
|
||
set_keybinding()
|
||
})
|
||
|
||
$editor.setKeyboardHandler(keybindings[$("#keybinding")[0].selectedIndex]);
|
||
})
|
||
$(document).keyup(function(e) {
|
||
if (e.keyCode == 27) { // esc
|
||
exit_fullscreen();
|
||
}
|
||
});
|
||
|
||
function onEditorLoad(){
|
||
var template_text = $(".template_text");
|
||
if ($.browser && $.browser.msie && $.browser.version.slice(0,1) < 10) {
|
||
$('.subnav').hide();
|
||
if ($('.diffMode').exists()) {
|
||
IE_diff_mode(template_text);
|
||
}
|
||
}else{
|
||
if (template_text.exists()){
|
||
create_editor(template_text)
|
||
}
|
||
|
||
if ($('.diffMode').exists()) {
|
||
set_diff_mode(template_text);
|
||
} else {
|
||
set_edit_mode(template_text);
|
||
}
|
||
}
|
||
}
|
||
|
||
function set_keybinding(){
|
||
var vim = require("ace/keyboard/vim").handler;
|
||
var emacs = require("ace/keyboard/emacs").handler;
|
||
var keybindings = [
|
||
null, // Null = use "default" keymapping
|
||
vim,
|
||
emacs];
|
||
|
||
$editor.setKeyboardHandler(keybindings[$("#keybinding")[0].selectedIndex]);
|
||
}
|
||
|
||
function upload_file(evt){
|
||
if(window.File && window.FileList && window.FileReader)
|
||
{
|
||
if (!confirm(_("You are about to override the editor content, are you sure?"))) {
|
||
$('.template_file').val('');
|
||
return;
|
||
}
|
||
|
||
var files = evt.target.files; // files is a FileList object
|
||
for (var i = 0, f; f = files[i]; i++) {
|
||
var reader = new FileReader();
|
||
// Closure to capture the file information.
|
||
reader.onloadend = function(evt) {
|
||
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
|
||
$('#new').text(( evt.target.result));
|
||
set_edit_mode($('.template_text'));
|
||
}
|
||
};
|
||
// Read in the file as text.
|
||
reader.readAsText(f);
|
||
$('.template_file').val("");
|
||
}
|
||
}else{
|
||
// Browser can't read the file content,
|
||
// the file will be uploaded to the server on form submit.
|
||
// Set editor to read only mode
|
||
$editor.setTheme("ace/theme/clouds");
|
||
$editor.setReadOnly(true);
|
||
}
|
||
}
|
||
|
||
function snippet_changed(item){
|
||
var checked = !!$(item).attr('checked');
|
||
$('#kind_selector').toggle(!checked);
|
||
$('#snippet_message').toggle(checked);
|
||
$('#association').toggle(!checked);
|
||
}
|
||
function create_editor(item) {
|
||
|
||
function create_editor(item) {
|
||
item.parent().prepend("<div id='editor1'></div>");
|
||
|
||
$("#editor1")
|
||
.css("position","relative")
|
||
.height(item.height() || '360')
|
||
.width(item.width()+10);
|
||
.width(item.width()+10)
|
||
.css('top', '-20px');
|
||
item.hide();
|
||
|
||
$editor = ace.edit("editor1");
|
||
... | ... | |
$editor.renderer.setShowGutter(false);
|
||
}
|
||
|
||
function set_fullscreen(){
|
||
$('#main').append($("#editor1"));
|
||
$("#editor1")
|
||
.height($(window).height()-80)
|
||
.width($('#content').width())
|
||
.addClass('container');
|
||
$('#content').hide();
|
||
$('.navbar').addClass('hidden');
|
||
$('.logo-bar').addClass('hidden');
|
||
$editor.resize();
|
||
$('#main').append($('.exit-fullscreen'));
|
||
$('.exit-fullscreen').show();
|
||
$(window).scrollTop(0);
|
||
}
|
||
|
||
function exit_fullscreen(){
|
||
$(".template_text").show();
|
||
$('#content').show();
|
||
$('.navbar').removeClass('hidden');
|
||
$('.logo-bar').removeClass('hidden');
|
||
$(".template_text").parent().prepend($("#editor1"))
|
||
$("#editor1")
|
||
.height($(".template_text").height() || '360')
|
||
.width($(".template_text").width()+10)
|
||
$(".template_text").hide();
|
||
$editor.resize();
|
||
$('.exit-fullscreen').hide()
|
||
}
|
||
|
||
function set_preview(){
|
||
if($('.template_text').hasClass('diffMode')) return;
|
||
... | ... | |
}
|
||
|
||
function set_edit_mode(item){
|
||
if( $editor == undefined) return;
|
||
$editor.setTheme("ace/theme/twilight");
|
||
$editor.setReadOnly(false);
|
||
var session = $editor.getSession();
|
||
... | ... | |
});
|
||
}
|
||
|
||
|
||
function set_diff_mode(item){
|
||
$editor.setTheme("ace/theme/clouds");
|
||
$editor.setReadOnly(true);
|
||
... | ... | |
var patch = JsDiff.createPatch(item.attr('data-file-name'), $('#old').text(), $('#new').text());
|
||
patch = patch.replace(/^(.*\n){0,4}/,'');
|
||
if (patch.length == 0)
|
||
patch = "No changes"
|
||
patch = _("No changes")
|
||
|
||
$(session).off('change');
|
||
session.setValue(patch);
|
||
... | ... | |
}
|
||
|
||
function revert_template(item){
|
||
var answer = confirm(_("You are about to override the editor content with a previous version, are you sure?"))
|
||
if (!answer) return;
|
||
if (!confirm(_("You are about to override the editor content with a previous version, are you sure?"))) return;
|
||
|
||
var version = $(item).attr('data-version');
|
||
var url = $(item).attr('data-url');
|
app/assets/stylesheets/application.scss | ||
---|---|---|
text-indent: 20px;
|
||
margin: 20% 30% 0 40%;
|
||
}
|
||
|
||
.exit-fullscreen{
|
||
position: absolute;
|
||
top: 60px;
|
||
right: 30px;
|
||
}
|
app/helpers/config_templates_helper.rb | ||
---|---|---|
str.join(" / ")
|
||
end.to_sentence
|
||
end
|
||
|
||
def include_javascript
|
||
javascript 'config_template', 'ace/ace',
|
||
'ace/theme-twilight', 'ace/theme-dawn', 'ace/theme-clouds', 'ace/theme-textmate',
|
||
'ace/mode-diff', 'diff', 'ace/mode-ruby', 'ace/keybinding-vim', 'ace/keybinding-emacs'
|
||
end
|
||
end
|
app/views/config_templates/_form.html.erb | ||
---|---|---|
<%= javascript 'config_template', 'ace/ace',
|
||
'ace/theme-twilight', 'ace/theme-dawn', 'ace/theme-clouds', 'ace/theme-textmate',
|
||
'ace/mode-diff', 'diff', 'ace/mode-ruby', 'ace/keybinding-vim', 'ace/keybinding-emacs' %>
|
||
<%= include_javascript %>
|
||
<%= form_for @config_template, :html => { :multipart => true, :onsubmit => 'submit_code();' } do |f| %>
|
||
<%= base_errors_for @config_template %>
|
||
<ul class="nav nav-tabs" data-tabs="tabs">
|
||
<li class="active"><a id="primary_tab" href="#primary" data-toggle="tab"><%= _("Provisioning Template") %></a></li>
|
||
<li><a href="#template_type" data-toggle="tab"><%= _("Type") %></a></li>
|
||
<li><a href="#template_associations" data-toggle="tab"><%= _("Association") %></a></li>
|
||
<li><a id='history_tab' href="#history" data-toggle="tab"><%= _("History") %></a></li>
|
||
</ul>
|
||
... | ... | |
<div class="tab-content">
|
||
<div class="tab-pane active" id="primary">
|
||
<%= text_f f, :name %>
|
||
<%= checkbox_f f, :snippet, :onchange => "snippet_changed(this)" %>
|
||
|
||
<div id="kind_selector" <%= display? @config_template.snippet %>>
|
||
<%= select_f f, :template_kind_id, TemplateKind.all, :id, :name, {:include_blank => true}, {:label => _("Type")} %>
|
||
</div>
|
||
|
||
<%= alert :class => 'controls alert-success', :header => '',
|
||
:text => icon_text("info-sign", (_('Note: %s ') % link_to(_('Useful template functions and macros'),
|
||
'http://theforeman.org/projects/foreman/wiki/TemplateWriting#Functions-and-macros', :rel => 'external')).html_safe) %>
|
||
<div class='controls'>
|
||
<div class="navbar-inner">
|
||
<div class="btn-group" data-toggle="buttons-radio" >
|
||
<button type="button" style="margin-top: 8px;" class="btn btn-small active" onclick="set_code()"><%= _("Code") %></button>
|
||
<button type="button" style="margin-top: 8px;" class="btn btn-small" onclick="set_preview()"><%= _("Preview") %></button>
|
||
</div>
|
||
<div class="fr">
|
||
<%= select_tag('keybinding', content_tag(:optgroup, options_for_select([_('Default'), 'Vim', 'Emacs']), :label => _('Key Binding')), :class => 'input-small', :style=>"margin-top: 8px;height: 26px;") %>
|
||
</div>
|
||
<div class='control-group'>
|
||
<label class="control-label" for="template"><%= _("Template editor") %></label>
|
||
<div class='controls'>
|
||
<div class="navbar-inner">
|
||
<div class="btn-group" data-toggle="buttons-radio" >
|
||
<button type="button" style="margin-top: 8px;" class="btn btn-small active" onclick="set_code()"><%= _("Code") %></button>
|
||
<button type="button" style="margin-top: 8px;" class="btn btn-small" onclick="set_preview()"><%= _("Preview") %></button>
|
||
</div>
|
||
<button type='button' style='margin-top: 8px;' class='btn btn-small' onclick='set_fullscreen()' title="<%= _("Full screen") %>"><i class="icon-resize-full"></i></button>
|
||
<div class="fr">
|
||
<%= select_tag('keybinding', content_tag(:optgroup, options_for_select([_('Default'), 'Vim', 'Emacs']), :label => _('Key Binding')), :class => 'input-small', :style=>"margin-top: 8px;height: 26px;") %>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<%= textarea_f f, :template, :class => "span12 template_text", :fluid=>true, :label => _("Template editor"), :'data-file-name' => @config_template.name %>
|
||
<%= textarea_f f, :template, :class => "span12 template_text", :fluid=>true, :label =>'', :'data-file-name' => @config_template.name %>
|
||
|
||
|
||
<%= file_field_f f, :template, :class => "template_file span4",
|
||
... | ... | |
<%= textarea_f f, :audit_comment, :class => "span12", :fluid=>true, :rows => 3, :label => _("Audit Comment"),
|
||
:help_block => _("The Audit Comment field is saved with the template auditing to document the template changes") %>
|
||
</div>
|
||
<div class="tab-pane" id="template_type">
|
||
<%= checkbox_f f, :snippet, :onchange => "snippet_changed(this)", :label=>'', :help_inline=>_('Snippet') %>
|
||
|
||
<div id="kind_selector" <%= display? @config_template.snippet %>>
|
||
<%= select_f f, :template_kind_id, TemplateKind.all, :id, :name, {:include_blank => true}, {:label => _("Type")} %>
|
||
</div>
|
||
</div>
|
||
<div class="tab-pane" id="history">
|
||
<div class='controls'>
|
||
<% if @history.try(:any?) %>
|
||
... | ... | |
</div>
|
||
<div class='span2 ra'><h6><%= audit_time audit %></h6></div>
|
||
<div class='span8 audit-content'>
|
||
<%= link_to_function icon_text("retweet", _("Revert")), "revert_template(this)", :'data-url' => revision_config_templates_url, :'data-version' => audit.id %>
|
||
<%= link_to icon_text("eye-open", _("Show Diff")), audit_path(audit) %>
|
||
<%= link_to_function icon_text("retweet", _("Revert")), "revert_template(this)", :data => {:url => revision_config_templates_url, :version => audit.id } %>
|
||
<%= link_to icon_text("eye-open", _("Show Diff")), audit_path(audit), :rel => 'external' %>
|
||
</div>
|
||
</div>
|
||
<% end %>
|
||
... | ... | |
<%= render "combinations", :f => f %>
|
||
</div>
|
||
</div>
|
||
<%= submit_or_cancel f %>
|
||
</div>
|
||
<%= submit_or_cancel f %>
|
||
<% end %>
|
||
<div class='hide' id="old"><%= @config_template.template %></div>
|
||
<div class='hide' id="new"><%= @config_template.template %></div>
|
||
<div class='exit-fullscreen hide'>
|
||
<%= link_to_function icon_text('resize-small'), 'exit_fullscreen()', :class => 'btn btn-large', :title => _('Exit Full Screen') %>
|
||
</div>
|
||
<div class='hide' id="old"><%= @config_template.template %></div>
|
||
<div class='hide' id="new"><%= @config_template.template %></div>
|
||
<% end %>
|
app/views/config_templates/index.html.erb | ||
---|---|---|
<%= include_javascript %>
|
||
<% title _("Provisioning Templates") %>
|
||
|
||
<% title_actions display_link_if_authorized(_("New Template"), hash_for_new_config_template_path),
|
||
... | ... | |
:class => "btn btn-info"})
|
||
%>
|
||
|
||
<table class="table table-bordered table-striped">
|
||
<table class="table table-bordered table-striped table-two-pane">
|
||
<tr>
|
||
<tr>
|
||
<th><%= sort :name, :as => s_("ConfigTemplate|Name") %></th>
|
Also available in: Unified diff
fixes #3274 moved config template to the new two-pane and add full screen editing