Merge pull request #228 from okkez/install-webpacker-vue

Install Vue.js via webpacker and use it
This commit is contained in:
okkez 2018-05-21 16:34:11 +09:00 committed by GitHub
commit 0ebb5fe7ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
188 changed files with 7465 additions and 71132 deletions

18
.babelrc Normal file
View File

@ -0,0 +1,18 @@
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": "> 1%",
"uglify": true
},
"useBuiltIns": true
}]
],
"plugins": [
"syntax-dynamic-import",
"transform-object-rest-spread",
["transform-class-properties", { "spec": true }]
]
}

View File

@ -1,3 +0,0 @@
{
"directory": "vendor/assets/javascripts/bower"
}

11
.editorconfig Normal file
View File

@ -0,0 +1,11 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 120

6
.gitignore vendored
View File

@ -29,3 +29,9 @@
/db/*-user.txt
/db/*-fluentd.json
/public/packs
/public/packs-test
/public/assets
/node_modules
yarn-debug.log*
.yarn-integrity

3
.postcssrc.yml Normal file
View File

@ -0,0 +1,3 @@
plugins:
postcss-import: {}
postcss-cssnext: {}

View File

@ -22,4 +22,4 @@ install:
- bundle -v
- gem i bundler
- sudo sh -c 'curl -L https://toolbelt.treasuredata.com/sh/install-ubuntu-trusty-td-agent2.sh | sh'
- bundle install --jobs=4 --retry=4
- bin/setup

View File

@ -22,6 +22,7 @@ PATH
settingslogic
sucker_punch (~> 2.0.4)
thor
webpacker
GEM
remote: https://rubygems.org/
@ -194,6 +195,8 @@ GEM
public_suffix (3.0.2)
puma (3.11.4)
rack (2.0.4)
rack-proxy (0.6.4)
rack
rack-test (1.0.0)
rack (>= 1.0, < 3)
rails (5.2.0)
@ -299,6 +302,10 @@ GEM
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
webpacker (3.5.3)
activesupport (>= 4.2)
rack-proxy (>= 0.6.1)
railties (>= 4.2)
websocket-driver (0.7.0)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3)

View File

@ -10,15 +10,4 @@
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require sb-admin-v2/bootstrap
//= require sb-admin-v2/plugins/dataTables/jquery.dataTables
//= require sb-admin-v2/plugins/dataTables/dataTables.bootstrap
//= require bower/vue/dist/vue
//= require bower/es6-promise/promise
//= require bower/lodash/dist/lodash.compat
//= require bower/codemirror/lib/codemirror
//= require codemirror_fluentd
//= require vue_common
//= require_tree .
//= require rails-ujs

View File

@ -1,29 +0,0 @@
function codemirrorify(el) {
return CodeMirror.fromTextArea(el, {
theme: "neo",
lineNumbers: true,
viewportMargin: Infinity,
mode: "fluentd"
});
}
$(function(){
$('.js-fluentd-config-editor').each(function(_, el){
codemirrorify(el);
});
});
Vue.directive('config-editor', {
bind: function(){
var $parent = this.vm;
// NOTE: needed delay for waiting CodeMirror setup
_.delay(function(textarea){
var cm = codemirrorify(textarea);
// textarea.codemirror = cm; // for test, but doesn't work for now (working on Chrome, but Poltergeist not)
cm.on('change', function(code_mirror){
// bridge Vue - CodeMirror world
$parent.editContent = code_mirror.getValue();
});
}, 0, this.el);
}
});

View File

@ -1,3 +0,0 @@
$(function(){
$('[data-toggle="tooltip"]').tooltip();
});

View File

@ -1,41 +0,0 @@
(function(){
"use strict";
$(function(){
var $firstSetting = $('.js-nested-column.js-multiple:first');
if($firstSetting.length === 0) return;
var counter = 0;
$('.js-append', $firstSetting).on('click', function(ev){
ev.preventDefault();
var $new = $firstSetting.clone(true);
counter++;
var fields = $('input,select,textarea', $new);
_.each(fields, function(elm){
elm.name = elm.name.replace("0", counter);
});
$('label', $new).each(function(_, label){
var $label = $(label);
$label.attr('for', $label.attr('for').replace("0", counter));
});
$('.js-remove', $new).show();
$('.js-append', $new).hide();
$new.appendTo($firstSetting.parent());
});
$('.js-remove').on('click', function(ev){
ev.preventDefault();
$(this).closest('.js-nested-column').remove();
});
var $allSettings = $('.js-nested-column.js-multiple');
$('.js-append', $allSettings).hide();
$('.js-remove', $allSettings).show();
$('.js-append', $firstSetting).show();
$('.js-remove', $firstSetting).hide();
});
})();

View File

@ -1,64 +0,0 @@
(function(){
"use strict";
$(function(){
if($('#fluent-log').length === 0) return;
new Vue({
el: "#fluent-log",
paramAttributes: ["logUrl", "initialAutoReload"],
data: {
"autoFetch": false,
"logs": [],
"limit": 30,
"processing": false
},
compiled: function(){
this.fetchLogs();
var self = this;
var timer;
this.$watch("autoFetch", function(newValue){
if(newValue === true) {
timer = setInterval(function(){
self.fetchLogs();
var $log = $(".log", self.$el);
$log.scrollTop($log.innerHeight());
}, 1000);
} else {
clearInterval(timer);
}
});
if(this.initialAutoReload) {
this.autoFetch = true;
}
},
computed: {
isPresentedLogs: function(){
return this.logs.length > 0;
}
},
methods: {
fetchLogs: function() {
if(this.processing) return;
this.processing = true;
var self = this;
new Promise(function(resolve, reject) {
$.getJSON(self.logUrl + "?limit=" + self.limit, resolve).fail(reject);
}).then(function(logs){
self.logs = logs;
setTimeout(function(){
self.processing = false;
}, 256); // delay to reduce flicking loading icon
})["catch"](function(error){
self.processing = false;
});
}
}
});
});
})();

View File

@ -1,177 +0,0 @@
(function(){
"use strict";
var maxFormatCount = 20;
$(function(){
if($('#in_tail_format').length === 0) return;
var FormatBundle = Vue.component('format-bundle', {
inherit: true,
template: "#format-bundle",
computed: {
options: {
get: function(){
return this.formatOptions[this.format];
},
},
selectableFormats: {
get: function() {
return Object.keys(this.formatOptions);
}
}
}
});
new Vue({
el: "#in_tail_format",
paramAttributes: ["formatOptionsJson", "initialSelected", "targetFile", "paramsJson"],
data: {
previewProcessing: false,
format: "",
highlightedLines: null,
},
computed: {
useTextArea: function() {
return this.format === "multiline";
}
},
compiled: function(){
this.$watch('params.setting.formats', function(formats){
_.range(1, maxFormatCount + 1).forEach(function(i) {params.setting["format" + String(i)] = "";});
_.compact(formats.split("\n")).forEach(function(formatLine, index) {
params.setting["format" + String(index + 1)] = formatLine;
});
}),
this.$watch('params.setting.regexp', function(){
this.preview();
});
this.$watch('format', function(){
this.preview();
});
this.$set("formatOptions", JSON.parse(this.formatOptionsJson));
this.format = this.initialSelected;
// initialize params
// NOTE: if `params.setting.foo` is undefined, Vue can't binding with v-model="params.setting.foo"
var params = JSON.parse(this.paramsJson);
if(!params.setting) {
params.setting = {};
}
var formats = _.chain(_.range(1, maxFormatCount + 1)).map(function(i) {return params.setting["format" + String(i)];}).compact().value();
params.setting.formats = formats.join("\n");
_.each(this.formatOptions, function(options){
_.each(options, function(key){
if(!params.setting.hasOwnProperty(key)){
params.setting[key] = "";
}
});
});
this.$set('params', params);
this.$emit("data-loaded");
},
methods: {
onKeyup: function(ev){
var el = ev.target;
if(el.name.match(/\[format/)){
this.preview();
}
},
updateHighlightedLines: function() {
if(!this.regexpMatches) {
this.highlightedLines = null;
return;
}
var $container = jQuery('<div>');
_.each(this.regexpMatches, function(match){
var colors = [
"#ff9", "#cff", "#fcf", "#dfd"
];
var whole = match.whole;
var html = "";
var matches = [];
var lastPos = 0;
_.each(match.matches, function(match) {
var matched = match.matched;
if(!matched) return;
if(matched.length === 0) return; // Ignore empty matched with "foobar".match(/foo(.*?)bar/)[1] #=> ""
// rotated highlight color
var currentColor = colors.shift();
colors.push(currentColor);
// create highlighted range HTML
var $highlighted = jQuery('<span>').text(matched);
$highlighted.attr({
"class": "regexp-preview",
"data-toggle": "tooltip",
"data-placement": "top",
"title": match.key,
'style': 'background-color:' + currentColor
});
var highlightedHtml = $highlighted.wrap('<div>').parent().html();
var pos = {
"start": match.pos[0],
"end": match.pos[1]
};
if(pos.start > 0) {
html += _.escape(whole.substring(lastPos, pos.start));
}
html += highlightedHtml;
lastPos = pos.end;
});
html += whole.substring(lastPos);
$container.append(html);
$container.append("<br />");
});
this.highlightedLines = $container.html();
setTimeout(function(){
$('#in_tail_format').tooltip({
selector: "[data-toggle=tooltip]",
container: "body"
})
},0);
},
preview: function(){
if(this.previewAjax) {
this.previewAjax.abort();
}
var self = this;
new Promise(function(resolve, reject) {
self.previewAjax = $.ajax({
method: "POST",
url: "/api/regexp_preview",
data: {
regexp: self.params.setting.regexp,
time_format: self.params.setting.time_format,
format: _.isEmpty(self.format) ? "regexp" : self.format,
params: self.params.setting,
file: self.targetFile
}
}).done(resolve).fail(reject);
}).then(function(result){
self.params = _.merge(self.params, result.params);
self.regexpMatches = result.matches;
self.updateHighlightedLines();
})["catch"](function(error){
if(error.stack) {
console.error(error.stack);
}
});
},
}
});
});
})();

View File

@ -1,65 +0,0 @@
(function(){
"use strict";
var POLLING_INTERVAL = 3 * 1000;
var POLLING_URL = "/polling/alerts";
$(function(){
if($('#vue-notification').length === 0) return;
var alert = new Vue({
el: "#vue-notification",
data: {
"alerts": []
},
created: function(){
var timer;
var self = this;
var currentInterval = POLLING_INTERVAL;
var fetch = function(){
self.fetchAlertsData().then(function(alerts){
if(self.alerts.toString() == alerts.toString()) {
currentInterval *= 1.1;
} else {
currentInterval = POLLING_INTERVAL;
}
self.alerts = alerts;
timer = setTimeout(fetch, currentInterval);
})["catch"](function(xhr){
if(xhr.status === 401) {
// signed out
}
if(xhr.status === 0) {
// server unreachable (maybe down)
}
});
};
window.addEventListener('focus', function(ev){
currentInterval = POLLING_INTERVAL;
timer = setTimeout(fetch, currentInterval);
}, false);
window.addEventListener('blur', function(ev){
clearTimeout(timer);
}, false);
fetch();
},
computed: {
alertsCount: {
get: function(){ return this.alerts.length; }
},
hasAlerts: {
get: function(){ return this.alertsCount > 0; }
}
},
methods: {
fetchAlertsData: function() {
return new Promise(function(resolve, reject) {
$.getJSON(POLLING_URL, resolve).fail(reject);
});
}
}
});
});
})();

View File

@ -1,121 +0,0 @@
;(function(){
"use strict";
$(function(){
var el = document.querySelector("#vue-setting");
if(!el) return;
new Vue({
el: el,
data: function(){
return {
loaded: false,
loading: false,
sections: {
sources: [],
matches: []
}
};
},
ready: function() {
this.update();
},
components: {
section: {
inherit: true,
template: "#vue-setting-section",
data: function(){
return {
mode: "default",
processing: false,
editContent: null
};
},
created: function(){
this.initialState();
},
computed: {
endpoint: function(){
return "/api/settings/" + this.id;
}
},
methods: {
onCancel: function(ev) {
this.initialState();
},
onEdit: function(ev) {
this.mode = "edit";
},
onDelete: function(ev) {
if(!confirm("really?")) return;
this.destroy();
},
onSubmit: function(ev) {
this.processing = true;
var self = this;
$.ajax({
url: this.endpoint,
method: "POST",
data: {
_method: "PATCH",
id: this.id,
content: this.editContent
}
}).then(function(data){
// NOTE: self.$data = data doesn't work as well, so using _.each
// whole $data swapping breaks mode switching..
_.each(data, function(v,k){
self[k] = v;
});
self.initialState();
}).always(function(){
self.processing = false;
});
},
initialState: function(){
this.$set('processing', false);
this.$set('mode', 'default');
this.$set('editContent', this.content);
},
destroy: function(){
var self = this;
$.ajax({
url: this.endpoint,
method: "POST",
data: {
_method: "DELETE",
id: this.id
}
}).then(function(){
self.$parent.update();
});
}
}
}
},
methods: {
update: function() {
this.loading = true;
var self = this;
$.getJSON("/api/settings", function(data){
var sources = [];
var matches = [];
data.forEach(function(v){
if(v.name === "source"){
sources.push(v);
}else{
matches.push(v);
}
});
self.sections.sources = sources;
self.sections.matches = matches;
self.loaded = true;
setTimeout(function(){
self.loading = false;
}, 500);
});
}
}
});
});
})();

View File

@ -1,97 +0,0 @@
(function(){
"use strict";
$(function(){
if($('#treeview').length === 0) return;
new Vue({
el: "#treeview",
paramAttributes: ["initialPath"],
data: {
preview: "",
path: "",
paths: []
},
compiled: function(){
this.path = this.initialPath;
this.fetchTree();
this.$watch("path", this.fetchTree);
this.$watch("path", this.fetchPreview);
},
computed: {
selected: function(){
var self = this;
return _.find(this.paths, function(path){
return self.path == path.path;
});
},
selectedIsDir: function() {
if(!this.selected) return true;
return this.selected.is_dir;
},
currentDirs: function() {
if(this.path === "/") {
return ["/"];
}
var path = this.path;
if(this.selected && !this.selected.is_dir) {
path = path.replace(/\/[^/]+$/, "");
}
var root = "/";
var dirs = [];
path.split("/").forEach(function(dir) {
dirs.push(root + dir);
if(dir) {
root = root + dir + "/";
}
});
return dirs;
}
},
methods: {
isAncestor: function(target) {
return this.path.indexOf(target) === 0;
},
basename: function(path) {
if (path === "/") return "/";
return path.match(/[^/]+$/)[0];
},
fetchTree: function() {
var self = this;
return new Promise(function(resolve, reject) {
$.getJSON("/api/tree?path=" + self.path, resolve).fail(reject);
}).then(function(paths){
self.paths = paths;
});
},
fetchPreview: function(){
if(!this.selected) return ;
var self = this;
this.preview = "";
new Promise(function(resolve, reject) {
$.getJSON("/api/file_preview?file=" + self.selected.path, resolve).fail(reject);
}).catch(function(e){
console.error(e);
}).then(function(lines){
self.preview = lines.join("\n");
});
},
selectPath: function(path){
this.path = path;
},
isSuffixRequired: function(data){
return data.is_dir && data.path != "/";
},
isSelected: function(path){
return this.path == path;
}
}
});
});
})();

View File

@ -1,4 +0,0 @@
Vue.filter('to_json', function (value) {
return JSON.stringify(value);
})

View File

@ -10,11 +10,12 @@
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
* file per style scope.
*
*= require sb-admin-v2/bootstrap.css
*= require sb-admin-v2/sb-admin
*= require "sb-admin-v2/font-awesome/scss/font-awesome.scss"
*= require bower/codemirror/lib/codemirror
*= require bower/codemirror/theme/neo
*= require font-awesome
*= require bootstrap/dist/css/bootstrap
*= require startbootstrap-sb-admin/css/sb-admin.css
*= require datatables.net-bs4/css/dataTables.bootstrap4.css
*= require codemirror/lib/codemirror
*= require codemirror/theme/neo
*= require_tree .
*= require_self
*/

View File

@ -37,12 +37,12 @@ module ApplicationHelper
raw html
end
def link_to_other(text, path)
def link_to_other(text, path, **options)
if current_page?(path)
# NOTE: sb-admin set style for element name instead of class name, such as ".nav a". So use "a" element even if it isn't a link.
content_tag(:a, text, class: "current")
else
link_to text, path
link_to text, path, class: "nav-link"
end
end
@ -62,4 +62,10 @@ module ApplicationHelper
head.html_safe + block.try(:call).to_s
end
end
def add_javascript_pack_tag(name, **options)
content_for(:additional_javascript_pack_tag) do
javascript_pack_tag(name, **options)
end
end
end

View File

@ -54,8 +54,8 @@ module SettingsHelper
end
def append_and_remove_links
%Q!<a class="btn btn-xs btn-default js-append">#{icon('fa-plus')}</a> ! +
%Q!<a class="btn btn-xs btn-default js-remove" style="display:none">#{icon('fa-minus')}</a> !
%Q!<a class="btn btn-sm btn-outline-secondary js-append">#{icon('fa-plus')}</a> ! +
%Q!<a class="btn btn-sm btn-outline-secondary js-remove" style="display:none">#{icon('fa-minus')}</a> !
end
def child_data(form, key)

22
app/javascript/app.vue Normal file
View File

@ -0,0 +1,22 @@
<template>
<div id="app">
<p>{{ message }}</p>
</div>
</template>
<script>
export default {
data: function () {
return {
message: "Hello Vue!"
}
}
}
</script>
<style scoped>
p {
font-size: 2em;
text-align: center;
}
</style>

View File

@ -0,0 +1,31 @@
/* eslint no-console:0 */
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
//
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb
console.log('Hello World from Webpacker')
import jQuery from 'jquery/dist/jquery'
window.$ = jQuery
window.jQuery = jQuery
import 'popper.js/dist/popper'
import 'bootstrap/dist/js/bootstrap'
import 'datatables.net/js/jquery.dataTables'
import 'startbootstrap-sb-admin/js/sb-admin'
import 'startbootstrap-sb-admin/js/sb-admin-datatables'
import Vue from 'vue/dist/vue.esm'
Vue.filter('to_json', function (value) {
return JSON.stringify(value);
})
window.Vue = Vue
import '../stylesheets/application.scss'

View File

@ -1,7 +1,9 @@
import CodeMirror from 'codemirror/lib/codemirror'
import 'lodash/lodash'
// See: http://codemirror.net/doc/manual.html#modeapi
// and sample mode files: https://github.com/codemirror/CodeMirror/tree/master/mode
CodeMirror.defineMode('fluentd', function(){
return {
startState: function(aa){
@ -57,3 +59,32 @@ CodeMirror.defineMode('fluentd', function(){
}
};
});
function codemirrorify(el) {
return CodeMirror.fromTextArea(el, {
theme: "neo",
lineNumbers: true,
viewportMargin: Infinity,
mode: "fluentd"
});
}
$(function(){
$('.js-fluentd-config-editor').each(function(_, el){
codemirrorify(el);
});
});
Vue.directive('config-editor', {
bind: function(el, binding, vnode, oldVnode){
// NOTE: needed delay for waiting CodeMirror setup
_.delay(function(textarea){
let cm = codemirrorify(textarea);
// textarea.codemirror = cm; // for test, but doesn't work for now (working on Chrome, but Poltergeist not)
cm.on('change', function(code_mirror){
// bridge Vue - CodeMirror world
el.dataset.content = code_mirror.getValue();
});
}, 0, el);
}
});

View File

@ -0,0 +1,63 @@
'use strict';
$(document).ready(()=> {
new Vue({
el: "#fluent-log",
props: ["logUrl", "initialAutoReload"],
data: {
"autoFetch": false,
"logs": [],
"limit": 30,
"processing": false
},
beforeMount: function() {
this.logUrl = this.$el.attributes.logUrl.nodeValue;
this.initialAutoReload = this.$el.attributes.initialAutoReload.nodeValue;
},
mounted: function(){
this.fetchLogs();
var self = this;
var timer;
this.$watch("autoFetch", function(newValue){
if(newValue === true) {
timer = setInterval(function(){
self.fetchLogs();
var $log = $(".log", self.$el);
$log.scrollTop($log.innerHeight());
}, 1000);
} else {
clearInterval(timer);
}
});
if(this.initialAutoReload) {
this.autoFetch = true;
}
},
computed: {
isPresentedLogs: function(){
return this.logs.length > 0;
}
},
methods: {
fetchLogs: function() {
if(this.processing) return;
this.processing = true;
var self = this;
new Promise(function(resolve, reject) {
$.getJSON(self.logUrl + "?limit=" + self.limit, resolve).fail(reject);
}).then(function(logs){
self.logs = logs;
setTimeout(function(){
self.processing = false;
}, 256); // delay to reduce flicking loading icon
})["catch"](function(error){
self.processing = false;
});
}
}
});
});

View File

@ -0,0 +1,71 @@
/* eslint no-console: 0 */
// Run this example by adding <%= javascript_pack_tag 'hello_vue' %> (and
// <%= stylesheet_pack_tag 'hello_vue' %> if you have styles in your component)
// to the head of your layout file,
// like app/views/layouts/application.html.erb.
// All it does is render <div>Hello Vue</div> at the bottom of the page.
import Vue from 'vue'
import App from '../app.vue'
document.addEventListener('DOMContentLoaded', () => {
const el = document.body.appendChild(document.createElement('hello'))
const app = new Vue({
el,
render: h => h(App)
})
console.log(app)
})
// The above code uses Vue without the compiler, which means you cannot
// use Vue to target elements in your existing html templates. You would
// need to always use single file components.
// To be able to target elements in your existing html/erb templates,
// comment out the above code and uncomment the below
// Add <%= javascript_pack_tag 'hello_vue' %> to your layout
// Then add this markup to your html template:
//
// <div id='hello'>
// {{message}}
// <app></app>
// </div>
// import Vue from 'vue/dist/vue.esm'
// import App from '../app.vue'
//
// document.addEventListener('DOMContentLoaded', () => {
// const app = new Vue({
// el: '#hello',
// data: {
// message: "Can you say hello?"
// },
// components: { App }
// })
// })
//
//
//
// If the using turbolinks, install 'vue-turbolinks':
//
// yarn add 'vue-turbolinks'
//
// Then uncomment the code block below:
//
// import TurbolinksAdapter from 'vue-turbolinks';
// import Vue from 'vue/dist/vue.esm'
// import App from '../app.vue'
//
// Vue.use(TurbolinksAdapter)
//
// document.addEventListener('turbolinks:load', () => {
// const app = new Vue({
// el: '#hello',
// data: {
// message: "Can you say hello?"
// },
// components: { App }
// })
// })

View File

@ -0,0 +1,174 @@
'use strict'
import 'lodash/lodash'
window.addEventListener('load', () => {
const maxFormatCount = 20;
new Vue({
el: "#in_tail_format",
props: ["formatOptionsJson", "initialSelected", "targetFile", "paramsJson"],
data: {
previewProcessing: false,
format: "",
highlightedLines: null,
},
computed: {
options: {
get: function(){
return this.formatOptions[this.format];
},
},
selectableFormats: {
get: function() {
return Object.keys(this.formatOptions);
}
},
useTextArea: function() {
return this.format === "multiline";
}
},
beforeMount: function() {
this.formatOptions = JSON.parse(this.$el.attributes.formatOptionsJson.nodeValue);
this.format = this.$el.attributes.initialSelected.nodeValue;
// initialize params
// NOTE: if `params.setting.foo` is undefined, Vue can't binding with v-model="params.setting.foo"
var params = JSON.parse(this.$el.attributes.paramsJson.nodeValue);
if(!params.setting) {
params.setting = {};
}
var formats = _.chain(_.range(1, maxFormatCount + 1)).map(function(i) {return params.setting["format" + String(i)];}).compact().value();
params.setting.formats = formats.join("\n");
_.each(this.formatOptions, function(options){
_.each(options, function(key){
if(!params.setting.hasOwnProperty(key)){
params.setting[key] = "";
}
});
});
this.params = params;
this.targetFile = this.$el.attributes.targetFile.nodeValue;
},
mounted: function(){
this.$emit("data-loaded");
},
watch: {
'params.setting.formats': function(formats) {
_.range(1, maxFormatCount + 1).forEach(()=> {params.setting["format" + String(i)] = "";});
_.compact(formats.split("\n")).forEach((formatLine, index)=> {
params.setting["format" + String(index + 1)] = formatLine;
})
},
'params.setting.regexp': function() {
this.preview();
},
'format': function() {
this.preview();
},
},
methods: {
onKeyup: function(ev){
var el = ev.target;
if(el.name.match(/\[format/)){
this.preview();
}
},
updateHighlightedLines: function() {
if(!this.regexpMatches) {
this.highlightedLines = null;
return;
}
var $container = jQuery('<div>');
_.each(this.regexpMatches, function(match){
var colors = [
"#ff9", "#cff", "#fcf", "#dfd"
];
var whole = match.whole;
var html = "";
var matches = [];
var lastPos = 0;
_.each(match.matches, function(match) {
var matched = match.matched;
if(!matched) return;
if(matched.length === 0) return; // Ignore empty matched with "foobar".match(/foo(.*?)bar/)[1] #=> ""
// rotated highlight color
var currentColor = colors.shift();
colors.push(currentColor);
// create highlighted range HTML
var $highlighted = jQuery('<span>').text(matched);
$highlighted.attr({
"class": "regexp-preview",
"data-toggle": "tooltip",
"data-placement": "top",
"title": match.key,
'style': 'background-color:' + currentColor
});
var highlightedHtml = $highlighted.wrap('<div>').parent().html();
var pos = {
"start": match.pos[0],
"end": match.pos[1]
};
if(pos.start > 0) {
html += _.escape(whole.substring(lastPos, pos.start));
}
html += highlightedHtml;
lastPos = pos.end;
});
html += whole.substring(lastPos);
$container.append(html);
$container.append("<br />");
});
this.highlightedLines = $container.html();
},
preview: function(){
if(this.previewAjax) {
this.previewAjax.abort();
}
const token = document.getElementsByName("csrf-token")[0].getAttribute('content')
var self = this;
new Promise(function(resolve, reject) {
self.previewAjax = $.ajax({
method: "POST",
url: "/api/regexp_preview",
headers: {
'X-CSRF-Token': token
},
data: {
regexp: self.params.setting.regexp,
time_format: self.params.setting.time_format,
format: _.isEmpty(self.format) ? "regexp" : self.format,
params: self.params.setting,
file: self.targetFile
}
}).done(resolve).fail(reject);
}).then(function(result){
self.params = _.merge(self.params, result.params);
self.regexpMatches = result.matches;
self.updateHighlightedLines();
})["catch"](function(error){
if(error.stack) {
console.error(error.stack);
}
});
},
}
});
});

View File

@ -0,0 +1,40 @@
'use strict';
import 'lodash/lodash';
$(document).ready(()=> {
var $firstSetting = $('.js-nested-column.js-multiple:first');
if ($firstSetting.length === 0) {
return;
}
var counter = 0;
$('.js-append', $firstSetting).on('click', function(ev){
ev.preventDefault();
var $new = $firstSetting.clone(true);
counter++;
var fields = $('input,select,textarea', $new);
_.each(fields, function(elm){
elm.name = elm.name.replace("0", counter);
});
$('label', $new).each(function(_, label){
var $label = $(label);
$label.attr('for', $label.attr('for').replace("0", counter));
});
$('.js-remove', $new).show();
$('.js-append', $new).hide();
$new.appendTo($firstSetting.parent());
});
$('.js-remove').on('click', function(ev){
ev.preventDefault();
$(this).closest('.js-nested-column').remove();
});
var $allSettings = $('.js-nested-column.js-multiple');
$('.js-append', $allSettings).hide();
$('.js-remove', $allSettings).show();
$('.js-append', $firstSetting).show();
$('.js-remove', $firstSetting).hide();
});

View File

@ -0,0 +1,60 @@
const POLLING_INTERVAL = 3 * 1000
const POLLING_URL = "/polling/alerts"
$(document).ready(()=> {
let alert = new Vue({
el: "#vue-notification",
data: {
"alerts": []
},
created: function(){
let timer;
let self = this;
let currentInterval = POLLING_INTERVAL;
let fetch = function(){
self.fetchAlertsData().then(function(alerts){
if(self.alerts.toString() == alerts.toString()) {
currentInterval *= 1.1;
} else {
currentInterval = POLLING_INTERVAL;
}
self.alerts = alerts;
timer = setTimeout(fetch, currentInterval);
})["catch"](function(xhr){
if(xhr.status === 401) {
// signed out
}
if(xhr.status === 0) {
// server unreachable (maybe down)
}
});
};
window.addEventListener('focus', function(ev){
currentInterval = POLLING_INTERVAL;
timer = setTimeout(fetch, currentInterval);
}, false);
window.addEventListener('blur', function(ev){
clearTimeout(timer);
}, false);
fetch();
},
computed: {
alertsCount: {
get: function(){ return this.alerts.length; }
},
hasAlerts: {
get: function(){ return this.alertsCount > 0; }
}
},
methods: {
fetchAlertsData: function() {
return new Promise(function(resolve, reject) {
$.getJSON(POLLING_URL, resolve).fail(reject);
});
}
}
});
});

View File

@ -0,0 +1,122 @@
$(document).ready(() => {
const SettingSection = {
template: '#vue-setting-section',
props: ['id', 'content', 'type', 'name', 'arg'],
data: function() {
return {
mode: 'default',
processing: false
};
},
created: function() {
this.initialState();
},
computed: {
endpoint: function() {
return '/api/settings/' + this.id;
}
},
methods: {
onCancel: function(event) {
this.initialState();
},
onEdit: function(ev) {
this.mode = "edit";
},
onDelete: function(ev) {
if (!confirm("really?")) {
return;
}
this.destroy();
},
onSubmit: function(ev) {
const token = document.getElementsByName("csrf-token")[0].getAttribute('content');
this.processing = true;
this.content = $(`#${this.id} textarea.form-control`)[0].dataset.content;
$.ajax({
url: this.endpoint,
method: "POST",
data: {
_method: "PATCH",
id: this.id,
content: this.content
},
headers: {
'X-CSRF-Token': token
}
}).then((data)=> {
_.each(data, function(v,k){
this[k] = v;
});
this.initialState();
}).always(()=> {
this.processing = false;
});
},
initialState: function(){
this.processing = false;
this.mode = 'default';
},
destroy: function(){
const token = document.getElementsByName("csrf-token")[0].getAttribute('content');
$.ajax({
url: this.endpoint,
method: "POST",
data: {
_method: "DELETE",
id: this.id
},
headers: {
'X-CSRF-Token': token
}
}).then(()=> {
this.$parent.update();
});
}
}
};
new Vue({
el: "#vue-setting",
data: function(){
return {
loaded: false,
loading: false,
sections: {
sources: [],
matches: []
}
};
},
mounted: function() {
this.$nextTick(() => {
this.update();
})
},
components: {
'setting-section': SettingSection
},
methods: {
update: function() {
this.loading = true;
$.getJSON("/api/settings", (data)=> {
var sources = [];
var matches = [];
data.forEach((v)=> {
if(v.name === "source"){
sources.push(v);
}else{
matches.push(v);
}
});
this.sections.sources = sources;
this.sections.matches = matches;
this.loaded = true;
setTimeout(()=> {
this.loading = false;
}, 500);
});
}
}
});
})

View File

@ -0,0 +1,99 @@
'use strict';
import 'lodash/lodash';
$(document).ready(() => {
new Vue({
el: "#treeview",
props: {
initialPath: {
default: "/var/log",
type: String
}
},
data: {
preview: "",
path: "",
paths: []
},
mounted: function(){
console.log(this.initialPath);
this.path = this.initialPath;
this.fetchTree();
this.$watch("path", this.fetchTree);
this.$watch("path", this.fetchPreview);
},
computed: {
selected: function(){
var self = this;
return _.find(this.paths, function(path){
return self.path == path.path;
});
},
selectedIsDir: function() {
if(!this.selected) return true;
return this.selected.is_dir;
},
currentDirs: function() {
if(this.path === "/") {
return ["/"];
}
var path = this.path;
if(this.selected && !this.selected.is_dir) {
path = path.replace(/\/[^/]+$/, "");
}
var root = "/";
var dirs = [];
path.split("/").forEach(function(dir) {
dirs.push(root + dir);
if(dir) {
root = root + dir + "/";
}
});
return dirs;
}
},
methods: {
isAncestor: function(target) {
return this.path.indexOf(target) === 0;
},
basename: function(path) {
if (path === "/") return "/";
return path.match(/[^/]+$/)[0];
},
fetchTree: function() {
var self = this;
return new Promise(function(resolve, reject) {
$.getJSON("/api/tree?path=" + self.path, resolve).fail(reject);
}).then(function(paths){
console.log(paths);
self.paths = paths;
});
},
fetchPreview: function(){
if(!this.selected) return ;
var self = this;
this.preview = "";
new Promise(function(resolve, reject) {
$.getJSON("/api/file_preview?file=" + self.selected.path, resolve).fail(reject);
}).catch(function(e){
console.error(e);
}).then(function(lines){
self.preview = lines.join("\n");
});
},
selectPath: function(path){
this.path = path;
},
isSuffixRequired: function(data){
return data.is_dir && data.path != "/";
},
isSelected: function(path){
return this.path == path;
}
}
});
});

View File

@ -1,4 +1,4 @@
.col-xs-6
.col-xl-6
- @fluentd.errors.full_messages.each do |e|
.alert.alert-danger= e

View File

@ -1,19 +1,18 @@
- page_title t('fluentd.common.recent_errors', days: @error_duration_days) do
- link_to raw_log_daemon_path(@fluentd), class: "btn btn-primary pull-right" do
- link_to raw_log_daemon_path(@fluentd), class: "btn btn-primary float-right mt-3" do
= icon('fa-download')
= t('fluentd.common.raw_log_link')
.row
.col-xs-12
.col-xl-12.col-sm-12
- @errors.each do |error|
.panel.panel-default
.panel-heading
.card.card-primary
.card-heading
%h4= error[:subject]
- if error[:notes].present?
.panel-body
.card-body
%ul
- error[:notes].each do |stack|
%li= stack
- if @errors.empty?
%p= t('.error_is_empty')

View File

@ -1,9 +1,8 @@
- page_title t('.page_title', label: @fluentd.label) do
- link_to raw_log_daemon_path(@fluentd), class: "btn btn-primary pull-right" do
- link_to raw_log_daemon_path(@fluentd), class: "btn btn-primary float-right mt-3" do
= icon('fa-download')
= t('fluentd.common.raw_log_link')
.row
.col-xs-12
.row.ml-3
= preserve do # partial containing <pre>, so shouldn't break indent
= render partial: "shared/vue/fluent_log", locals: { fluentd: @fluentd }

View File

@ -1,8 +1,9 @@
- page_title t('.page_title', label: @fluentd.label)
- add_javascript_pack_tag("codemirror")
= form_tag(daemon_setting_path(@fluentd), method: :patch) do
.form-group
= text_area_tag "config", @config, class: "form-control js-fluentd-config-editor", rows: 40
%p.text.text-danger= t('terms.notice_restart_for_config_edit', brand: fluentd_ui_brand)
= submit_tag t("terms.update"), class: "btn btn-primary"
= submit_tag t("terms.configtest"), class: "btn btn-default", name: "dryrun"
= submit_tag t("terms.configtest"), class: "btn btn-secondary", name: "dryrun"

View File

@ -14,4 +14,4 @@
.form-group.input-group
= f.text_field :content, value: file.note.content, class: "note-content form-control", id: nil
%span.input-group-btn
= submit_tag t('terms.save'), class: 'btn btn-default'
= submit_tag t('terms.save'), class: 'btn btn-info'

View File

@ -1,7 +1,7 @@
- page_title t('.page_title', label: @fluentd.label)
%p.pull-right
= link_to configtest_daemon_setting_history_path(id: @backup_file.file_id), method: "post", class: "btn btn-default" do
%p.float-right
= link_to configtest_daemon_setting_history_path(id: @backup_file.file_id), method: "post", class: "btn btn-secondary" do
= icon('fa-legal')
= t("terms.configtest")
= link_to reuse_daemon_setting_history_path(id: @backup_file.file_id), method: 'post', class: "btn btn-primary" do
@ -10,22 +10,22 @@
- if @backup_file.note.content.present?
.row
.col-xs-12
.col-xl-12
%p= @backup_file.note.content
.row
.col-xs-12
.col-xl-12
%h2
="#{t('.target_config')}(#{params[:id]})"
%pre
= preserve do
= @backup_file.content
.col-xs-12.diff
.col-xl-12.diff
%h2
Diff:
%div
= t(".diff_description", file_name: params[:id] )
.pull-right
.float-right
= link_to t(".show_current"), daemon_setting_path(@fluentd)
= preserve render "/shared/settings/diff"

View File

@ -12,8 +12,9 @@
= f.text_field :path, class: "form-control", disabled: true
= render partial: "shared/vue/in_tail_format", locals: { file: f.object.path, formats: @setting.known_formats, initialSelected: f.object.format || @setting.guess_format }
%pre= file_tail(@setting.path, Settings.in_tail_preview_line_count).join("\n")
.card
%pre.card-body= file_tail(@setting.path, Settings.in_tail_preview_line_count).join("\n")
%p
= f.submit t('terms.next'), class: "btn btn-lg btn-primary pull-right"
= link_to t('terms.prev'), daemon_setting_in_tail_path(@fluentd), class: "btn btn-lg btn-default"
= f.submit t('terms.next'), class: "btn btn-lg btn-primary float-right"
= link_to t('terms.prev'), daemon_setting_in_tail_path(@fluentd), class: "btn btn-lg btn-secondary"

View File

@ -6,5 +6,5 @@
= render partial: "form", locals: { f: f }
%p
= f.submit t('terms.next'), class: "btn btn-lg btn-primary pull-right"
= f.submit t('terms.prev'), class: "btn btn-lg btn-default", name: "back"
= f.submit t('terms.next'), class: "btn btn-lg btn-primary float-right"
= f.submit t('terms.prev'), class: "btn btn-lg btn-secondary", name: "back"

View File

@ -8,6 +8,6 @@
%pre= @setting.to_conf
%p
= f.submit t('fluentd.common.finish') , class: "btn btn-lg btn-primary pull-right"
= f.submit t('terms.prev'), class: "btn btn-lg btn-default", name: "back"
.clearfix.pull-right= t('terms.notice_restart_for_config_edit', brand: fluentd_ui_brand)
= f.submit t('fluentd.common.finish') , class: "btn btn-lg btn-primary float-right"
= f.submit t('terms.prev'), class: "btn btn-lg btn-secondary", name: "back"
.clearfix.float-right= t('terms.notice_restart_for_config_edit', brand: fluentd_ui_brand)

View File

@ -1,8 +1,8 @@
- page_title t('.page_title', label: @fluentd.label)
- if @backup_file.content
%p.pull-right
= link_to configtest_daemon_setting_running_backup_path, method: 'post', class: "btn btn-default" do
%p.float-right
= link_to configtest_daemon_setting_running_backup_path, method: 'post', class: "btn btn-secondary" do
= icon('fa-legal')
= t("terms.configtest")
= link_to reuse_daemon_setting_running_backup_path, method: 'post', class: "btn btn-primary" do
@ -10,7 +10,7 @@
= t("terms.reuse")
.row
.col-xs-12
.col-xl-12
- if @backup_file.content
%h2
= t('.page_title')
@ -21,11 +21,11 @@
%p
=t('fluentd.common.never_started_yet', brand: fluentd_ui_brand)
- if @backup_file.content
.col-xs-12.diff
.col-xl-12.diff
%h2
Diff:
%div
= t(".diff_description")
.pull-right
.float-right
= link_to t(".show_current"), daemon_setting_path(@fluentd)
= preserve render "/shared/settings/diff"

View File

@ -1,23 +1,23 @@
- page_title t('.page_title') do
- link_to edit_daemon_setting_path(@fluentd), class: "btn btn-primary pull-right" do
- link_to edit_daemon_setting_path(@fluentd), class: "btn btn-primary float-right mt-3" do
= icon('fa-pencil')
= t("terms.edit")
.row
.col-xs-12
%pre
.row.mb-3
.card.col-xl-12.bg-light.ml-3
%pre.card-body
= preserve do
= @config
.row
.col-xs-12
.row.mb-3
.col-xl-12
%h3= link_to(t('fluentd.settings.running_backup.title'), daemon_setting_running_backup_path)
%p
%label= t('terms.backup_time')
= @running_backedup_file.ctime.try(:strftime, I18n.t('time.formats.default')) || t('fluentd.common.never_started_yet', brand: fluentd_ui_brand)
.row
.col-xs-12
.col-xl-12
%h3= t('fluentd.settings.history')
= render '/fluentd/settings/histories/list'
.link= link_to t('.link_to_histories'), daemon_setting_histories_path

View File

@ -1,27 +1,28 @@
- add_javascript_pack_tag("settings")
- page_title t('.page_title')
.row.fluentd-setting-inout
.col-xs-4
.panel.panel-default
.panel-heading
.col-xl-4
.card.card-primary
.card-header
%h4= t('.in')
.panel-body
.card-body
- %w|tail syslog monitor_agent http forward|.each do |type|
%p
= link_to(send("daemon_setting_in_#{type}_path", @fluentd)) do
= icon('fa-file-text-o fa-lg')
= t("fluentd.common.setup_in_#{type}")
.col-xs-1.arrow-right
.col-xl-1.arrow-right
= icon "fa-arrow-circle-right"
.col-xs-2
.col-xl-2
= image_tag "/fluentd-logo.png", style: "max-width: 100%"
.col-xs-1.arrow-right
.col-xl-1.arrow-right
= icon "fa-arrow-circle-right"
.col-xs-4
.panel.panel-default
.panel-heading
.col-xl-4
.card.card-primary
.card-header
%h4= t('.out')
.panel-body
.card-body
- %w|stdout td s3 mongo elasticsearch forward|.each do |type|
%p
= link_to(send("daemon_setting_out_#{type}_path", @fluentd)) do
@ -33,17 +34,29 @@
#vue-setting.current-settings
%h2
= t('.current')
.pull-right
%button.btn.btn-default.btn-sm{"v-on" => "click: update", "v-if" => "!loading"}= icon('fa-refresh')
%button.btn.btn-default.btn-sm{"v-if" => "loading"}= icon('fa-spin fa-refresh')
.float-right
%button.btn.btn-outline-dark.btn-sm{"v-on:click" => "update", "v-if" => "!loading"}= icon('fa-refresh')
%button.btn.btn-outline-dark.btn-sm{"v-if" => "loading"}= icon('fa-spin fa-refresh')
.row
.col-xs-6.input
.col-xl-6.input
%h3= t('.in')
%div{"v-if" => "loaded && sections.sources.length == 0"}
%p.empty= t('.setting_empty')
%div{"v-repeat" => "sections.sources", "v-component" => "section"}
.col-xs-6.output
%setting-section{"v-if" => "loaded && sections.sources.length > 0",
"v-for" => "source in sections.sources",
"v-bind:id" => "source.id",
"v-bind:content" => "source.content",
"v-bind:type" => "source.type",
"v-bind:name" => "source.name",
"v-bind:arg" => "source.arg"}
.col-xl-6.output
%h3= t('.out')
%div{"v-if" => "loaded && sections.matches.length == 0"}
%p.empty= t('.setting_empty')
%div{"v-repeat" => "sections.matches", "v-component" => "section"}
%setting-section{"v-if" => "loaded && sections.matches.length > 0",
"v-for" => "match in sections.matches",
"v-bind:id" => "match.id",
"v-bind:content" => "match.content",
"v-bind:type" => "match.type",
"v-bind:name" => "match.name",
"v-bind:arg" => "match.arg"}

View File

@ -1,9 +1,9 @@
- if @fluentd.present?
- page_title t('.page_title')
.row
.col-xs-6
%div{class: "panel panel-#{@fluentd.agent.running? ? "success":"default"}"}
.panel-heading
.col-xl-6.col-sm-6
%div{class: "card card-#{@fluentd.agent.running? ? "primary":"secondary"}"}
.card-header
%h4
- if @fluentd.agent.running?
= icon("fa-play")
@ -11,17 +11,17 @@
- else
= icon("fa-pause")
= t("fluentd.common.stopped")
.panel-body
.card-body
- if flash[:error]
.alert.alert-danger= flash[:error]
= link_to icon("fa-play") << t("fluentd.common.start"), start_daemon_agent_path(@fluentd), method: :put, class: "btn #{@fluentd.agent.running? ? "disabled btn-default" : "btn-primary"}"
= link_to icon("fa-pause") << t("fluentd.common.stop"), stop_daemon_agent_path(@fluentd), method: :put, class: "btn #{@fluentd.agent.running? ? "btn-danger" : "disabled btn-default"}"
= link_to icon("fa-refresh") << t("fluentd.common.restart"), restart_daemon_agent_path(@fluentd), method: :put, class: "btn #{@fluentd.agent.running? ? "btn-warning" : "disabled btn-default"}"
.col-xs-6
.panel.panel-default
.panel-heading
.pull-right
= link_to t('terms.edit'), edit_daemon_path, class: "btn btn-default"
= link_to icon("fa-play") << t("fluentd.common.start"), start_daemon_agent_path(@fluentd), method: :put, class: "btn #{@fluentd.agent.running? ? "disabled btn-outline-dark" : "btn-primary"}"
= link_to icon("fa-pause") << t("fluentd.common.stop"), stop_daemon_agent_path(@fluentd), method: :put, class: "btn #{@fluentd.agent.running? ? "btn-danger" : "disabled btn-outline-dark"}"
= link_to icon("fa-refresh") << t("fluentd.common.restart"), restart_daemon_agent_path(@fluentd), method: :put, class: "btn #{@fluentd.agent.running? ? "btn-warning" : "disabled btn-outline-dark"}"
.col-xl-6.col-sm-6
.card.card-default
.card-header
.float-right
= link_to t('terms.edit'), edit_daemon_path, class: "btn btn-info"
= link_to t('terms.destroy'), "#", class: "btn btn-danger", data: { toggle: "modal", target: "#setting-destroy-modal" }
%h4= t('fluentd.common.fluentd_info')
.modal.fade{id: "setting-destroy-modal"}
@ -36,11 +36,11 @@
= raw t('fluentd.common.destroy_fluentd_setting_warning', brand: fluentd_ui_brand)
.modal-footer
= form_tag(daemon_path(@fluentd), method: :delete) do
%button.btn.btn-default{"data-dismiss" => "modal"}
%button.btn.btn-secondary{"data-dismiss" => "modal"}
Close
= submit_tag t('terms.destroy'), class: "btn btn-danger"
%table.table.table-hover
%table.table.table-hover.mb-0
%tbody
%tr
%th= @fluentd.class.human_attribute_name(:pid_file)
@ -52,7 +52,7 @@
%th= @fluentd.class.human_attribute_name(:config_file)
%td= @fluentd.agent.config_file
.row
.col-xs-12
.col-xl-12
= preserve do # partial containing <pre>, so shouldn't break indent
= render partial: "shared/vue/fluent_log", locals: { fluentd: @fluentd }

View File

@ -11,70 +11,55 @@
<%= fluentd_ui_title %>
</title>
<%= stylesheet_link_tag 'application', media: 'all'%>
<%= javascript_include_tag 'application' %>
<%= stylesheet_pack_tag 'application', media: 'all'%>
<%= javascript_pack_tag 'application' %>
<%= javascript_pack_tag 'notification' %>
<%= content_for(:additional_javascript_pack_tag) %>
<%= csrf_meta_tags %>
</head>
<body>
<div id="wrapper">
<nav class="navbar navbar-default navbar-fixed-top" role="navigation" style="margin-bottom: 0">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".sidebar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<body class="fixed-nav bg-light">
<nav class="navbar navbar-expand-lg navbar-light bg-light fixed-top" id="mainNav">
<%= link_to fluentd_ui_logo, root_path, class: "navbar-brand fluentd-ui-logo" %>
</div>
<!-- /.navbar-header -->
<ul class="nav navbar-top-links navbar-right">
<% if @fluentd %>
<li class="fluentd-status">
<a href="<%= daemon_path %>" data-toggle="tooltip" data-placement="bottom" title="fluentd <%= fluentd_status_message %>">
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<%= render partial: "shared/global_nav" %>
<ul class="navbar-nav ml-auto">
<%- if @fluentd %>
<li class="nav-item fluentd-status">
<a class="nav-link" href="<%= daemon_path %>" data-toggle="tooltip" data-placement="bottom" title="fluentd <%= fluentd_status_message %>">
<%= fluentd_status_icon %>
</a>
</li>
<% end %>
<%- end %>
<%= render partial: "shared/vue/notification" %>
<li class="dropdown">
<%= link_to(t("terms.sign_out"), sessions_path, method: :delete) %>
<li class="nav-item">
<%= link_to(icon("fa-fw fa-sign-out") + t("terms.sign_out"), sessions_path, method: :delete, class: "nav-link") %>
</li>
</ul>
<!-- /.navbar-top-links -->
<div class="navbar-default navbar-static-side" role="navigation">
<div class="sidebar-collapse">
<%= render partial: "shared/global_nav" %>
<!-- /#side-menu -->
</div>
<!-- /.sidebar-collapse -->
</div>
<!-- /.navbar-static-side -->
</nav>
<div id="page-wrapper">
<div class="content-wrapper">
<div class="container-fluid">
<%= render partial: "shared/flash" %>
<% if content_for?(:page_head) %>
<div class="row">
<div class="col-xs-12">
<h1 class="page-header"><%= content_for(:page_head) %></h1>
<div class="col-xl-12 col-sm-12">
<h1 class="display-4 border-bottom mb-3"><%= content_for(:page_head) %></h1>
</div>
<!-- /.col-xs-12 -->
</div>
<!-- /.row -->
<% end %>
<div class="row">
<div class="col-xs-12">
<div class="col-xl-12 col-sm-12">
<%= yield %>
</div>
</div>
<!-- /.row -->
</div>
<!-- /#page-wrapper -->
</div>
</div>
<!-- /#wrapper -->
</body>
</html>

View File

@ -8,21 +8,14 @@
<title>Fluentd-UI</title>
<%= stylesheet_link_tag 'application', media: 'all'%>
<%= javascript_include_tag 'application' %>
<%= javascript_pack_tag 'application' %>
<%= csrf_meta_tags %>
</head>
<body>
<body class="bg-light">
<div class="container">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<%= yield %>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,23 +1,23 @@
- page_title t('.page_title') do
- link_to misc_download_info_path, class: "btn btn-primary pull-right" do
- link_to misc_download_info_path, class: "btn btn-primary float-right" do
= icon('fa-download')
= t('.download_system_information')
- if FluentdUI.update_available? && !FluentdUI.td_agent_ui?
- # NOTE: td-agent-ui shouldn't have auto update feature
.row
.col-xs-12
.col-xl-12
%p
= link_to misc_update_fluentd_ui_path, class: "btn btn-primary btn-lg", method: :post do
= t('.update_fluentd_ui', version: FluentdUI.latest_version, title: fluentd_ui_title)
= t('.update_fluentd_ui_caution', brand: fluentd_ui_brand)
.row
.col-xs-6
.panel.panel-default
.panel-heading
.col-xl-6.col-sm-6.mb-3
.card.card-default
.card-header
%h4= t("terms.version")
.panel-body
.card-body
%dl{class: "dl-horizontal"}
%dt ruby
%dd= RUBY_DESCRIPTION
@ -27,11 +27,11 @@
%dt fluentd-ui
%dd= FluentdUI::VERSION
.col-xs-6
.panel.panel-default
.panel-heading
.col-xl-6.col-sm-6.mb-3
.card.card-default
.card-header
%h4= t('terms.installed_plugins')
.panel-body
.card-body
- if @plugins.present?
%table{class: "table table-hover", id: "plugins-table"}
%thead
@ -47,9 +47,9 @@
= t "plugins.common.no_installed"
.row
.col-xs-12
.panel.panel-default
.panel-heading
.col-xl-12.col-sm-12
.card.card-default
.card-header
%h4{"data-toggle" => "collapse", "href" => "#env-table"}
= icon('fa-caret-down')
= t('.env')

View File

@ -1,7 +1,7 @@
.panel.panel-default
.panel-heading
.card
.card-header
= t('.update_title', title: fluentd_ui_title)
.panel-body
.card-body
#processing
= icon('fa-lg fa-gear fa-spin')
= t('.updating')

View File

@ -3,13 +3,13 @@
%table{class: "table table-striped table-hover", id: "plugins-table"}
%thead
%tr
%th.col-xs-1
%th.col-xs-1= t('plugins.common.name')
%th{width: 160}= t('plugins.common.authors')
%th{width: 320}= t('plugins.common.summary')
%th.col-xs-1= t('plugins.common.installed_version')
%th.col-xs-1= t('plugins.common.latest_version')
%th.col-xs-1
%th{scope: "col"}
%th{scope: "col"}= t('plugins.common.name')
%th{scope: "col"}= t('plugins.common.authors')
%th{scope: "col"}= t('plugins.common.summary')
%th{scope: "col"}= t('plugins.common.installed_version')
%th{scope: "col"}= t('plugins.common.latest_version')
%th{scope: "col"}
%tbody
- @plugins.each do |plugin|
%tr
@ -28,7 +28,7 @@
= t('terms.confirm_body', action: t('terms.uninstall'))
.modal-footer
= form_tag(uninstall_plugins_path, method: :patch) do
%button.btn.btn-default{"data-dismiss" => "modal"}
%button.btn.btn-secondary{"data-dismiss" => "modal"}
Close
= hidden_field_tag("plugins[]", plugin.gem_name)
= submit_tag t('terms.uninstall'), class: "btn btn-danger"

View File

@ -3,11 +3,11 @@
%table{class: "table table-striped table-hover", id: "plugins-table"}
%thead
%tr
%th{width: "24"}
%th= t('plugins.common.name')
%th= t('plugins.common.category')
%th= t('plugins.common.status')
%th
%th{scope: "col", width: "24"}
%th{scope: "col"}= t('plugins.common.name')
%th{scope: "col"}= t('plugins.common.category')
%th{scope: "col"}= t('plugins.common.status')
%th{scope: "col"}
%tbody
- @plugins.each do |plugin|
%tr

View File

@ -7,11 +7,11 @@
%table{class: "table table-striped table-hover"}
%thead
%tr
%th.col-xs-2= t('plugins.common.name')
%th.col-xs-2= t('plugins.common.authors')
%th.col-xs-6= t('plugins.common.summary')
%th.col-xs-1= t('plugins.common.installed_version')
%th.col-xs-1= t('plugins.common.latest_version')
%th.col-xl-2= t('plugins.common.name')
%th.col-xl-2= t('plugins.common.authors')
%th.col-xl-6= t('plugins.common.summary')
%th.col-xl-1= t('plugins.common.installed_version')
%th.col-xl-1= t('plugins.common.latest_version')
%tbody
- @plugins.each do |plugin|
%tr

View File

@ -1,8 +1,7 @@
.login-panel.panel.panel-default
.panel-heading
%h3.panel-title
.card.card-login.mx-auto.mt-5
.card-header
= t('messages.please_sign_in')
.panel-body
.card-body
= render partial: "shared/error"
= form_for(:session, url: sessions_path) do |f|
.form-group
@ -10,4 +9,4 @@
.form-group
= f.password_field :password, placeholder: t('terms.password'), class: "form-control"
= submit_tag t("terms.sign_in"), class: "btn btn-success"
= submit_tag t("terms.sign_in"), class: "btn btn-primary btn-block"

View File

@ -1,9 +1,9 @@
<ul class="nav" id="side-menu">
<li>
<ul class="navbar-nav navbar-sidenav" id="side-menu">
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="Fluentd">
<a class="section">
<%= icon("fa-puzzle-piece fa-fw") << "fluentd" %>
</a>
<ul class="nav nav-second-level">
<ul class="sidenav-second-level">
<% if fluentd_exists? %>
<li>
<%= link_to_other t('fluentd.show.page_title'), daemon_path %>
@ -29,11 +29,11 @@
</li>
<% if fluentd_exists? %>
<li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="Plugins">
<a class="section">
<%= icon("fa-cogs fa-fw") << t('terms.plugins') %>
</a>
<ul class="nav nav-second-level">
<ul class="sidenav-second-level">
<li>
<%= link_to_other t("plugins.installed.page_title"), installed_plugins_path %>
</li>
@ -47,11 +47,11 @@
</li>
<% end %>
<li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="Misc">
<a class="section">
<%= icon('fa-coffee fa-fw') << t('terms.misc') %>
</a>
<ul class="nav nav-second-level">
<ul class="sidenav-second-level">
<li>
<%= link_to_other t("misc.information.page_title"), misc_information_path %>
</li>
@ -67,11 +67,11 @@
</ul>
</li>
<li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="Language">
<a class="section">
<%= icon('fa-font') << t('terms.languages') %>
</a>
<ul class="nav nav-second-level">
<ul class="sidenav-second-level">
<li>
<%= language_menu %>
</li>

View File

@ -1,13 +1,13 @@
- page_title "fluentd"
.row
.col-xs-6
.col-xl-6.col-sm-6
.well
%span= link_to icon("fa-cog") << t("terms.setup", target: "fluentd"), new_daemon_path(variant: "fluentd_gem"), class: "btn btn-primary btn-lg"
.col-xs-6
.col-xl-6.col-sm-6
.well
%span
= link_to icon("fa-cog") << t("terms.setup", target: "td-agent"), new_daemon_path(variant: "td-agent"), class: "btn btn-lg #{has_td_agent_system? ? "btn-primary" : "btn-default disabled"}"
= link_to icon("fa-cog") << t("terms.setup", target: "td-agent"), new_daemon_path(variant: "td-agent"), class: "btn btn-lg #{has_td_agent_system? ? "btn-primary" : "btn-secondary disabled"}"
- unless has_td_agent_system?
= link_to t('terms.install_it', target: "td-agent"), "http://docs.treasuredata.com/articles/td-agent"

View File

@ -14,7 +14,7 @@
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<%= primary_button %>
</div>
</div>

View File

@ -6,12 +6,13 @@
= field(f, key)
- if @setting.advanced_options.present?
.well.well-sm
.card.bg-light
.card-body
%h4{"data-toggle" => "collapse", "href" => "#advanced-setting"}
= icon('fa-caret-down')
= t('terms.advanced_setting')
#advanced-setting.collapse
- @setting.advanced_options.each do |key|
= field(f, key)
= f.submit t('fluentd.common.finish'), class: "btn btn-lg btn-primary pull-right"
= f.submit t('fluentd.common.finish'), class: "btn btn-lg btn-primary float-right"

View File

@ -1,6 +1,8 @@
- page_title t("fluentd.settings.#{target_plugin_name}.show.page_title")
- add_javascript_pack_tag("nested_settings")
.well
.card.mb-3
.card-body.bg-light
= raw t("fluentd.settings.#{target_plugin_name}.option_guide")
= render "shared/settings/form"

View File

@ -1,20 +1,21 @@
<%- add_javascript_pack_tag("fluent_log") %>
<!-- vue.js -->
<% auto_reload ||= true %>
<div id="fluent-log" logUrl="<%= log_tail_daemon_agent_path(fluentd) %>" initialAutoReload="<%= auto_reload ? "true" : "" %>">
<div class="bottom-margin form-inline">
<button class="btn btn-primary" v-on="click: fetchLogs">
<button class="btn btn-primary mr-3" v-on:click="fetchLogs">
<%= t "terms.reload_log" %>
</button>
<input type="text" v-model="limit" size="4" v-on="keyup: fetchLogs | key enter" class="form-control"/>
<input type="text" v-model="limit" size="4" v-on:keyup.enter="fetchLogs" class="form-control"/>
<%= t('terms.lines') %>
<label>
<label class="ml-3">
<input type="checkbox" v-model="autoFetch" /> <%= t "terms.auto_reload", seconds: 1 %>
</label>
<span v-if="processing"><%= icon('fa-spin fa-refresh') %></span>
</div>
<pre v-if="isPresentedLogs"><!-- be careful indent -->
<div class="log"><span v-repeat="logs">{{ $value }}
<pre v-if="isPresentedLogs" class="card bg-light"><!-- be careful indent -->
<div class="log card-body"><span v-for="log in logs">{{ log }}
</span></div></pre>
<div v-if="!isPresentedLogs && !processing">
@ -22,4 +23,3 @@
</div>
</div>
<!-- /vue.js -->

View File

@ -1,28 +1,4 @@
<script type="text/template" id="format-bundle">
<div class="form-inline form-group">
<label for="in_tail_setting_format">format</label>
<select id="in_tail_setting_format" name="setting[format]" v-model="format" class="form-control">
<option v-repeat="selectableFormats" value="{{ $value }}" v-attr="selected: format==$value">{{ $value }}</option>
</select>
</div>
<div class="form-inline form-group" v-repeat="options">
<label for="in_tail_setting_{{ $value }}" v-if="!useTextArea">{{ $value }} </label>
<input id="in_tail_setting_{{ $value }}" type="{{ useTextArea ? 'hidden' : 'text' }}" name="setting[{{ $value }}]" v-model="params.setting[$value]" v-on="keyup: onKeyup" size="100%" class="form-control" />
</div>
<div v-if="useTextArea">
<div class="form-inline form-group">
<label for="in_tail_setting_format_firstline">format_firstline</label>
<input id="in_tail_setting_format_firstline" type="text" name="setting[format_firstline]" v-model="params.setting['format_firstline']" v-on="keyup: onKeyup" size="100%" class="form-control" />
</div>
<div class="form-group">
<p class="alert alert-warning"><%= t("fluentd.settings.in_tail.notice_for_multiline_limit") %></p>
<label for="in_tail_setting_formats">formats</label>
<textarea id="in_tail_setting_formats" type="text" name="setting[formats]" v-model="params.setting['formats']" v-on="keyup: onKeyup" rows='20' size='100%' class="form-control"></textarea>
</div>
</div>
</script>
<%- add_javascript_pack_tag("in_tail_format") %>
<div id="in_tail_format"
formatOptionsJson="<%= formats.to_json %>"
@ -31,11 +7,37 @@
paramsJson="<%= params.to_json %>"
>
<div v-component="format-bundle" wait-for="data-loaded"></div>
<div class="form-inline form-group">
<label for="in_tail_setting_format">format</label>
<select id="in_tail_setting_format" name="setting[format]" v-model="format" class="form-control">
<option v-for="selectableFormat in selectableFormats" v-bind:value="selectableFormat" v-bind:selected="format==selectableFormat" v-if="selectableFormats">{{ selectableFormat }}</option>
</select>
</div>
<div class="form-inline form-group" v-for="option in options">
<label v-bind:for="'in_tail_setting_' + option" v-if="!useTextArea">{{ option }} </label>
<input v-bind:id="'in_tail_setting_' + option" v-bind:type="useTextArea ? 'hidden' : 'text'" v-bind:name="'setting[' + option + ']'" v-model="params.setting[option]" v-on:keyup="onKeyup" size="100%" class="form-control" />
</div>
<pre>{{{ highlightedLines }}}</pre>
<div v-if="useTextArea">
<div class="form-inline form-group">
<label for="in_tail_setting_format_firstline">format_firstline</label>
<input id="in_tail_setting_format_firstline" type="text" name="setting[format_firstline]" v-model="params.setting['format_firstline']" v-on:keyup="onKeyup" size="100%" class="form-control" />
</div>
<div class="well well-sm">
<div class="form-group">
<p class="alert alert-warning"><%= t("fluentd.settings.in_tail.notice_for_multiline_limit") %></p>
<label for="in_tail_setting_formats">formats</label>
<textarea id="in_tail_setting_formats" type="text" name="setting[formats]" v-model="params.setting['formats']" v-on:keyup="onKeyup" rows='20' size='100%' class="form-control"></textarea>
</div>
</div>
<div class="card mb-3">
<pre class="card-body" v-html="highlightedLines"></pre>
</div>
<div class="card mb-3">
<p class="card-body pb-0">
<%= raw t('fluentd.settings.in_tail_option_guide') %>
</p>
</div>
</div>

View File

@ -1,14 +1,10 @@
<!-- vue.js -->
<li class="dropdown" id="vue-notification">
<a
class="dropdown-toggle"
data-toggle="dropdown" href="#"
>
<li class="nav-item dropdown" id="vue-notification">
<a class="nav-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" href="#">
<i class="fa fa-bell fa-fw"></i>
<span class="badge" v-if="hasAlerts">{{ alertsCount }}</span>
<i class="fa fa-caret-down"></i>
</a>
<ul class="nav dropdown-menu dropdown-alerts">
<ul class="dropdown-menu" aria-labelledby="alertsDropdown">
<li v-if="!hasAlerts">
<a>
<div class="nothing text text-success">
@ -17,11 +13,11 @@
</div>
</a>
</li>
<li v-repeat="alerts">
<li v-for="alert in alerts">
<a>
<div>
<%= icon("fa-cog fa-fw fa-lg fa-spin") %>
{{ text }}
{{ alert }}
</div>
</a>
</li>

View File

@ -1,21 +1,23 @@
<script type="text/template" id="vue-setting-section">
<%- add_javascript_pack_tag('codemirror') %>
<div class='panel panel-default'>
<div class='panel-heading' data-toggle='collapse' href='#{{ id }}' title='{{ content }}'>
<script type="text/x-template" id="vue-setting-section">
<div class="card card-primary mb-3">
<div class="card-header" data-toggle="collapse" v-bind:href="'#'+id" v-bind:title="content">
{{ type }}
<span v-if="name == 'match'">({{ arg }})</span>
<i class="fa fa-caret-down"></i>
</div>
<div class='panel-body collapse' id='{{ id }}'>
<div class="card-body collapse" v-bind:id="id">
<pre v-if="mode != 'edit'">{{ content }}</pre>
<p v-if="mode == 'edit'">
<textarea v-config-editor class="form-control" v-model="editContent" v-attr="disabled: processing"></textarea>
<textarea v-config-editor class="form-control" v-model="content" v-bind:disabled="processing"></textarea>
</p>
<p class="pull-right">
<button v-if="mode != 'edit'" class="btn btn-default" v-on="click: onEdit"><%= t('terms.edit') %></button>
<button v-if="mode != 'edit'" class="btn btn-danger" v-on="click: onDelete"><%= t('terms.destroy') %></button>
<button v-if="mode == 'edit'" class="btn btn-default" v-on="click: onCancel"><%= t('terms.cancel') %></button>
<button v-if="mode == 'edit'" class="btn btn-primary" v-on="click: onSubmit"><%= t('terms.save') %></button>
<p class="float-right">
<button v-if="mode != 'edit'" class="btn btn-secondary" v-on:click="onEdit"><%= t('terms.edit') %></button>
<button v-if="mode != 'edit'" class="btn btn-danger" v-on:click="onDelete"><%= t('terms.destroy') %></button>
<button v-if="mode == 'edit'" class="btn btn-secondary" v-on:click="onCancel"><%= t('terms.cancel') %></button>
<button v-if="mode == 'edit'" class="btn btn-primary" v-on:click="onSubmit"><%= t('terms.save') %></button>
</p>
</div>
</div>

View File

@ -1,30 +1,33 @@
<% add_javascript_pack_tag("treeview") %>
<% name ||= "" %>
<% action ||= "" %>
<% submit_button ||= "" %>
<%= form_tag(action, method: :post) do %>
<div id="treeview" initialPath="/var/log">
<pre>{{ path }}</pre>
<div id="treeview">
<div class="card">
<pre class="card-body pb-0">{{ path }}</pre>
</div>
<input type="hidden" name="<%= name %>" v-model="path" />
<div class="dirs">
<span v-repeat="currentDirs">
<span v-if="$index > 0">
<span v-for="(dir, index) in currentDirs">
<span v-if="index > 0">
<%= icon('fa-caret-right') %>
</span>
<span v-on="click: selectPath($value)" class="dir">{{ basename($value) }}</span>
<span v-on:click="selectPath(dir)" class="dir">{{ basename(dir) }}</span>
</span>
</div>
<div class="tree">
<span v-on="click: selectPath(path)" class="vue-path" v-class="selected: isSelected(path)" v-repeat="paths">
<span v-if="is_dir"><%= icon("fa-folder") %></span>
<span v-if="!is_dir"><%= icon("fa-file-o") %></span>
{{ basename(path) }}
<span v-on:click="selectPath(value.path)" class="vue-path" v-bind:class="{ selected: isSelected(value.path) }" v-for="value in paths">
<span v-if="value.is_dir"><%= icon("fa-folder") %></span>
<span v-if="!value.is_dir"><%= icon("fa-file-o") %></span>
{{ basename(value.path) }}
<br />
</span>
</div>
<pre v-if="preview" class="preview">{{ preview }}</pre>
<p>
<%= submit_tag submit_button, class: "btn btn-lg btn-primary pull-right", "v-attr" => "disabled: selectedIsDir", "v-class" => "btn-disable: selectedIsDir" %>
<%= submit_tag submit_button, class: "btn btn-lg btn-primary float-right", "v-bind:disabled" => "selectedIsDir" %>
</p>
</div>
<% end %>

View File

@ -3,7 +3,7 @@
<% page_title t(".page_title") %>
<p class="clearfix">
<%= link_to t('tutorials.chapter2.page_title') << " >>", tutorials_chapter2_path, class: "pull-right" %>
<%= link_to t('tutorials.chapter2.page_title') << " >>", tutorials_chapter2_path, class: "float-right" %>
</p>
<p>
@ -14,7 +14,7 @@
<div id="chapter1">
<form>
<p v-repeat="payloads">
<input type="button" class="btn btn-default" v-on="click: sendRequest($data)" value="<%= t ".send" %>" />
<input type="button" class="btn btn-primary" v-on="click: sendRequest($data)" value="<%= t ".send" %>" />
<code>
$ curl -X POST http://localhost:<%= @in_http["port"] %>{{ path }} -F 'json={{ data | to_json }}'
</code>
@ -26,6 +26,5 @@
<%= render partial: "shared/vue/fluent_log", locals: { fluentd: @fluentd } %>
<p class="clearfix">
<%= link_to t('tutorials.chapter2.page_title') << " >>", tutorials_chapter2_path, class: "pull-right" %>
<%= link_to t('tutorials.chapter2.page_title') << " >>", tutorials_chapter2_path, class: "float-right" %>
</p>

View File

@ -2,11 +2,11 @@
%p.clearfix
= link_to "<< " << t('tutorials.chapter1.page_title'), tutorials_chapter1_path, class: "pull-left"
= link_to t('tutorials.chapter3.page_title') << " >>", tutorials_chapter3_path, class: "pull-right"
= link_to t('tutorials.chapter3.page_title') << " >>", tutorials_chapter3_path, class: "float-right"
:markdown
#{t('.lesson_markdown', http_port: @in_http["port"])}
%p.clearfix
= link_to "<< " << t('tutorials.chapter1.page_title'), tutorials_chapter1_path, class: "pull-left"
= link_to t('tutorials.chapter3.page_title') << " >>", tutorials_chapter3_path, class: "pull-right"
= link_to t('tutorials.chapter3.page_title') << " >>", tutorials_chapter3_path, class: "float-right"

View File

@ -2,11 +2,11 @@
%p.clearfix
= link_to "<< " << t('tutorials.chapter2.page_title'), tutorials_chapter2_path, class: "pull-left"
= link_to t('tutorials.chapter4.page_title') << " >>", tutorials_chapter4_path, class: "pull-right"
= link_to t('tutorials.chapter4.page_title') << " >>", tutorials_chapter4_path, class: "float-right"
:markdown
#{t(".lesson_markdown", edit_config_url: edit_daemon_setting_path(@fluentd))}
%p.clearfix
= link_to "<< " << t('tutorials.chapter2.page_title'), tutorials_chapter2_path, class: "pull-left"
= link_to t('tutorials.chapter4.page_title') << " >>", tutorials_chapter4_path, class: "pull-right"
= link_to t('tutorials.chapter4.page_title') << " >>", tutorials_chapter4_path, class: "float-right"

View File

@ -2,11 +2,11 @@
%p.clearfix
= link_to "<< " << t('tutorials.chapter3.page_title'), tutorials_chapter3_path, class: "pull-left"
= link_to t('tutorials.chapter5.page_title') << " >>", tutorials_chapter5_path, class: "pull-right"
= link_to t('tutorials.chapter5.page_title') << " >>", tutorials_chapter5_path, class: "float-right"
:markdown
#{t ".lesson_markdown"}
%p.clearfix
= link_to "<< " << t('tutorials.chapter3.page_title'), tutorials_chapter3_path, class: "pull-left"
= link_to t('tutorials.chapter5.page_title') << " >>", tutorials_chapter5_path, class: "pull-right"
= link_to t('tutorials.chapter5.page_title') << " >>", tutorials_chapter5_path, class: "float-right"

View File

@ -2,7 +2,7 @@
.col-xs-6
.col-xl-6.col-sm-6
- if notice
.alert.alert-success= notice
- else

View File

@ -15,10 +15,10 @@ chdir APP_ROOT do
puts '== Installing dependencies =='
system! 'gem install bundler --conservative'
system('bundle check') || system!('bundle install')
system('bundle check') || system!('bundle install --jobs=4 --retry=4')
# Install JavaScript dependencies if using Yarn
# system('bin/yarn')
system('bin/yarn')
puts "\n== Removing old logs and tempfiles =="
system! 'bin/rails log:clear tmp:clear'

15
bin/webpack Executable file
View File

@ -0,0 +1,15 @@
#!/usr/bin/env ruby
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
ENV["NODE_ENV"] ||= "development"
require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath)
require "rubygems"
require "bundler/setup"
require "webpacker"
require "webpacker/webpack_runner"
Webpacker::WebpackRunner.run(ARGV)

15
bin/webpack-dev-server Executable file
View File

@ -0,0 +1,15 @@
#!/usr/bin/env ruby
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
ENV["NODE_ENV"] ||= "development"
require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath)
require "rubygems"
require "bundler/setup"
require "webpacker"
require "webpacker/dev_server_runner"
Webpacker::DevServerRunner.run(ARGV)

View File

@ -1,11 +0,0 @@
{
"name": "fluentd-ui",
"dependencies": {
"es6-promise": "~1.0.0",
"vue": "~0.11.2",
"lodash": "~2.4.0",
"codemirror": "~4.11.0"
},
"devDependencies": {
}
}

View File

@ -17,6 +17,7 @@ require "sprockets/railtie"
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
# these gems are not required by Bundler.require
require "font-awesome-rails"
require "draper"
require "sass"
require "haml-rails"
@ -26,11 +27,12 @@ require "settingslogic"
require "kramdown-haml"
require "jbuilder"
require "diff/lcs"
require "webpacker"
module FluentdUi
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 5.0
config.load_defaults 5.2
# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers

View File

@ -1,4 +1,6 @@
Rails.application.configure do
# Verifies that versions and hashed value of the package contents in the project's package.json
config.webpacker.check_yarn_integrity = true
# Settings specified here will take precedence over those in config/application.rb.
# In the development environment your application's code is reloaded on

View File

@ -1,4 +1,6 @@
Rails.application.configure do
# Verifies that versions and hashed value of the package contents in the project's package.json
config.webpacker.check_yarn_integrity = false
# Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests.

View File

@ -1,2 +1,4 @@
require "plugin" # Avoid: RuntimeError Circular dependency detected while autoloading constant Plugin
unless Rails.env.test?
AllPluginCheckUpdateJob.perform_later
end

View File

@ -0,0 +1,5 @@
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
const environment = require('./environment')
module.exports = environment.toWebpackConfig()

View File

@ -0,0 +1,20 @@
const { environment } = require('@rails/webpacker')
const vue = require('./loaders/vue')
const webpack = require('webpack');
// Get a pre-configured plugin
const manifestPlugin = environment.plugins.get('Manifest')
manifestPlugin.opts.writeToFileEmit = false
// Add an additional plugin of your choosing : ProvidePlugin
environment.plugins.prepend(
'Provide',
new webpack.ProvidePlugin({
$: 'jquery/dist/jquery',
jQuery: 'jquery/dist/jquery',
Popper: 'popper.js/dist/popper'
})
);
environment.loaders.append('vue', vue)
module.exports = environment

View File

@ -0,0 +1,13 @@
const { dev_server: devServer } = require('@rails/webpacker').config
const isProduction = process.env.NODE_ENV === 'production'
const inDevServer = process.argv.find(v => v.includes('webpack-dev-server'))
const extractCSS = !(inDevServer && (devServer && devServer.hmr)) || isProduction
module.exports = {
test: /\.vue(\.erb)?$/,
use: [{
loader: 'vue-loader',
options: { extractCSS }
}]
}

View File

@ -0,0 +1,5 @@
process.env.NODE_ENV = process.env.NODE_ENV || 'production'
const environment = require('./environment')
module.exports = environment.toWebpackConfig()

5
config/webpack/test.js Normal file
View File

@ -0,0 +1,5 @@
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
const environment = require('./environment')
module.exports = environment.toWebpackConfig()

69
config/webpacker.yml Normal file
View File

@ -0,0 +1,69 @@
# Note: You must restart bin/webpack-dev-server for changes to take effect
default: &default
source_path: app/javascript
source_entry_path: packs
public_output_path: packs
cache_path: tmp/cache/webpacker
# Additional paths webpack should lookup modules
# ['app/assets', 'engine/foo/app/assets']
resolved_paths: []
# Reload manifest.json on all requests so we reload latest compiled packs
cache_manifest: false
extensions:
- .vue
- .js
- .sass
- .scss
- .css
- .module.sass
- .module.scss
- .module.css
- .png
- .svg
- .gif
- .jpeg
- .jpg
development:
<<: *default
compile: true
# Reference: https://webpack.js.org/configuration/dev-server/
dev_server:
https: false
host: localhost
port: 3035
public: localhost:3035
hmr: false
# Inline should be set to true if using HMR
inline: true
overlay: true
compress: true
disable_host_check: true
use_local_ip: false
quiet: false
headers:
'Access-Control-Allow-Origin': '*'
watch_options:
ignored: /node_modules/
test:
<<: *default
compile: true
# Compile test packs to a separate directory
public_output_path: packs-test
production:
<<: *default
# Production depends on precompilation of packs prior to booting for performance.
compile: false
# Cache manifest.json for performance
cache_manifest: true

View File

@ -44,4 +44,5 @@ Gem::Specification.new do |spec|
spec.add_dependency "kramdown-haml"
spec.add_dependency "rubyzip", "~> 1.1" # API changed as Zip::ZipFile -> Zip::File since v1.0.0
spec.add_dependency "diff-lcs"
spec.add_dependency "webpacker"
end

19
package.json Normal file
View File

@ -0,0 +1,19 @@
{
"name": "fluentd-ui",
"private": true,
"dependencies": {
"@rails/webpacker": "3.5",
"codemirror": "^5.37.0",
"es6-promise": "^4.2.4",
"jquery": "^3.3.1",
"lodash": "^4.17.10",
"popper.js": "^1.14.3",
"startbootstrap-sb-admin": "^4.0.0",
"vue": "^2.5.16",
"vue-loader": "14.2.2",
"vue-template-compiler": "^2.5.16"
},
"devDependencies": {
"webpack-dev-server": "2.11.2"
}
}

View File

@ -54,17 +54,17 @@ describe "source_and_output", js: true, stub: :daemon do
it do
page.should_not have_content(I18n.t("fluentd.settings.source_and_output.setting_empty"))
page.should have_css('.input .panel .panel-heading')
page.should have_css('.output .panel .panel-heading')
page.should have_css('.input .card .card-header')
page.should have_css('.output .card .card-header')
end
it ".panel-body is hidden by default and click .panel-heading for display" do
page.should_not have_css('.input .panel .panel-body')
page.should_not have_css('.output .panel .panel-body')
all(".input .panel .panel-heading").first.click
page.should have_css('.input .panel .panel-body')
all(".output .panel .panel-heading").first.click
page.should have_css('.output .panel .panel-body')
it ".card-body is hidden by default and click .card-header for display" do
page.should_not have_css('.input .card .card-body')
page.should_not have_css('.output .card .card-body')
all(".input .card .card-header").first.click
page.should have_css('.input .card .card-body')
all(".output .card .card-header").first.click
page.should have_css('.output .card .card-body')
end
it "display plugin name" do
@ -94,7 +94,7 @@ describe "source_and_output", js: true, stub: :daemon do
CONF
before do
all(".input .panel .panel-heading").first.click
all(".input .card .card-header").first.click
end
it "click edit button transform textarea, then click cancel button to be reset" do
@ -136,20 +136,20 @@ describe "source_and_output", js: true, stub: :daemon do
end
it "click delete button transform textarea" do
page.should have_css('.input .panel-body')
confirm_dialog(true) do
page.should have_css('.input .card-body')
accept_confirm do
find(".btn", text: I18n.t('terms.destroy')).click
end
page.should_not have_css('.input .panel-body')
page.should_not have_css('.input .card-body')
daemon.agent.config.strip.should == ""
end
it "click delete button then cancel it" do
page.should have_css('.input .panel-body')
confirm_dialog(false) do
page.should have_css('.input .card-body')
dismiss_confirm do
find(".btn", text: I18n.t('terms.destroy')).click
end
page.should have_css('.input .panel-body')
page.should have_css('.input .card-body')
daemon.agent.config.strip.should == config_contents.strip
end
end

View File

@ -1,10 +0,0 @@
codemirror/*
!codemirror/bower.json
!codemirror/.bower.json
!codemirror/lib
!codemirror/theme
vue/*
!vue/bower.json
!vue/.bower.json
!vue/dist

View File

@ -1,29 +0,0 @@
{
"name": "codemirror",
"version": "4.11.0",
"main": [
"lib/codemirror.js",
"lib/codemirror.css"
],
"ignore": [
"**/.*",
"node_modules",
"components",
"bin",
"demo",
"doc",
"test",
"index.html",
"package.json"
],
"homepage": "https://github.com/marijnh/CodeMirror",
"_release": "4.11.0",
"_resolution": {
"type": "version",
"tag": "4.11.0",
"commit": "1c78007be219f06f1afca059c2ee18316912daac"
},
"_source": "git://github.com/marijnh/CodeMirror.git",
"_target": "~4.11.0",
"_originalSource": "codemirror"
}

View File

@ -1,16 +0,0 @@
{
"name": "codemirror",
"version":"4.11.0",
"main": ["lib/codemirror.js", "lib/codemirror.css"],
"ignore": [
"**/.*",
"node_modules",
"components",
"bin",
"demo",
"doc",
"test",
"index.html",
"package.json"
]
}

View File

@ -1,309 +0,0 @@
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: 300px;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-guttermarker { color: black; }
.CodeMirror-guttermarker-subtle { color: #999; }
/* CURSOR */
.CodeMirror div.CodeMirror-cursor {
border-left: 1px solid black;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
width: auto;
border: 0;
background: #7e7;
}
.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
.cm-animate-fat-cursor {
width: auto;
border: 0;
-webkit-animation: blink 1.06s steps(1) infinite;
-moz-animation: blink 1.06s steps(1) infinite;
animation: blink 1.06s steps(1) infinite;
}
@-moz-keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
@-webkit-keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
@keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
/* Can style cursor different in overwrite (non-insert) mode */
div.CodeMirror-overwrite div.CodeMirror-cursor {}
.cm-tab { display: inline-block; text-decoration: inherit; }
.CodeMirror-ruler {
border-left: 1px solid #ccc;
position: absolute;
}
/* DEFAULT THEME */
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable,
.cm-s-default .cm-punctuation,
.cm-s-default .cm-property,
.cm-s-default .cm-operator {}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}
.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-strikethrough {text-decoration: line-through;}
.cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;}
/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
line-height: 1;
position: relative;
overflow: hidden;
background: white;
color: black;
}
.CodeMirror-scroll {
overflow: scroll !important; /* Things will break if this is overridden */
/* 30px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -30px; margin-right: -30px;
padding-bottom: 30px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-sizer {
position: relative;
border-right: 30px solid transparent;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actuall scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
overflow-x: hidden;
overflow-y: scroll;
}
.CodeMirror-hscrollbar {
bottom: 0; left: 0;
overflow-y: hidden;
overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
-moz-box-sizing: content-box;
box-sizing: content-box;
display: inline-block;
margin-bottom: -30px;
/* Hack to make IE7 behave */
*zoom:1;
*display:inline;
}
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
height: 100%;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-lines {
cursor: text;
min-height: 1px; /* prevents collapsing before first draw */
}
.CodeMirror pre {
/* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0;
background: transparent;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
overflow: auto;
}
.CodeMirror-widget {}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden;
}
.CodeMirror-measure pre { position: static; }
.CodeMirror div.CodeMirror-cursor {
position: absolute;
border-right: none;
width: 0;
}
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 3;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-crosshair { cursor: crosshair; }
.cm-searching {
background: #ffa;
background: rgba(255, 255, 0, .4);
}
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }
/* Used to force a border model for a node */
.cm-force-border { padding-right: .1px; }
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursors {
visibility: hidden;
}
}
/* See issue #2901 */
.cm-tab-wrap-hack:after { content: ''; }
/* Help users use markselection to safely style text background */
span.CodeMirror-selectedtext { background: none; }

File diff suppressed because it is too large Load Diff

View File

@ -1,38 +0,0 @@
/*
Name: 3024 day
Author: Jan T. Sott (http://github.com/idleberg)
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
*/
.cm-s-3024-day.CodeMirror {background: #f7f7f7; color: #3a3432;}
.cm-s-3024-day div.CodeMirror-selected {background: #d6d5d4 !important;}
.cm-s-3024-day .CodeMirror-gutters {background: #f7f7f7; border-right: 0px;}
.cm-s-3024-day .CodeMirror-guttermarker { color: #db2d20; }
.cm-s-3024-day .CodeMirror-guttermarker-subtle { color: #807d7c; }
.cm-s-3024-day .CodeMirror-linenumber {color: #807d7c;}
.cm-s-3024-day .CodeMirror-cursor {border-left: 1px solid #5c5855 !important;}
.cm-s-3024-day span.cm-comment {color: #cdab53;}
.cm-s-3024-day span.cm-atom {color: #a16a94;}
.cm-s-3024-day span.cm-number {color: #a16a94;}
.cm-s-3024-day span.cm-property, .cm-s-3024-day span.cm-attribute {color: #01a252;}
.cm-s-3024-day span.cm-keyword {color: #db2d20;}
.cm-s-3024-day span.cm-string {color: #fded02;}
.cm-s-3024-day span.cm-variable {color: #01a252;}
.cm-s-3024-day span.cm-variable-2 {color: #01a0e4;}
.cm-s-3024-day span.cm-def {color: #e8bbd0;}
.cm-s-3024-day span.cm-bracket {color: #3a3432;}
.cm-s-3024-day span.cm-tag {color: #db2d20;}
.cm-s-3024-day span.cm-link {color: #a16a94;}
.cm-s-3024-day span.cm-error {background: #db2d20; color: #5c5855;}
.cm-s-3024-day .CodeMirror-activeline-background {background: #e8f2ff !important;}
.cm-s-3024-day .CodeMirror-matchingbracket { text-decoration: underline; color: #a16a94 !important;}

View File

@ -1,37 +0,0 @@
/*
Name: 3024 night
Author: Jan T. Sott (http://github.com/idleberg)
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
*/
.cm-s-3024-night.CodeMirror {background: #090300; color: #d6d5d4;}
.cm-s-3024-night div.CodeMirror-selected {background: #3a3432 !important;}
.cm-s-3024-night .CodeMirror-gutters {background: #090300; border-right: 0px;}
.cm-s-3024-night .CodeMirror-guttermarker { color: #db2d20; }
.cm-s-3024-night .CodeMirror-guttermarker-subtle { color: #5c5855; }
.cm-s-3024-night .CodeMirror-linenumber {color: #5c5855;}
.cm-s-3024-night .CodeMirror-cursor {border-left: 1px solid #807d7c !important;}
.cm-s-3024-night span.cm-comment {color: #cdab53;}
.cm-s-3024-night span.cm-atom {color: #a16a94;}
.cm-s-3024-night span.cm-number {color: #a16a94;}
.cm-s-3024-night span.cm-property, .cm-s-3024-night span.cm-attribute {color: #01a252;}
.cm-s-3024-night span.cm-keyword {color: #db2d20;}
.cm-s-3024-night span.cm-string {color: #fded02;}
.cm-s-3024-night span.cm-variable {color: #01a252;}
.cm-s-3024-night span.cm-variable-2 {color: #01a0e4;}
.cm-s-3024-night span.cm-def {color: #e8bbd0;}
.cm-s-3024-night span.cm-bracket {color: #d6d5d4;}
.cm-s-3024-night span.cm-tag {color: #db2d20;}
.cm-s-3024-night span.cm-link {color: #a16a94;}
.cm-s-3024-night span.cm-error {background: #db2d20; color: #807d7c;}
.cm-s-3024-night .CodeMirror-activeline-background {background: #2F2F2F !important;}
.cm-s-3024-night .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}

View File

@ -1,5 +0,0 @@
.cm-s-ambiance.CodeMirror {
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}

File diff suppressed because one or more lines are too long

View File

@ -1,36 +0,0 @@
/*
Name: Base16 Default Dark
Author: Chris Kempson (http://chriskempson.com)
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-chrome-devtools)
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
*/
.cm-s-base16-dark.CodeMirror {background: #151515; color: #e0e0e0;}
.cm-s-base16-dark div.CodeMirror-selected {background: #303030 !important;}
.cm-s-base16-dark .CodeMirror-gutters {background: #151515; border-right: 0px;}
.cm-s-base16-dark .CodeMirror-guttermarker { color: #ac4142; }
.cm-s-base16-dark .CodeMirror-guttermarker-subtle { color: #505050; }
.cm-s-base16-dark .CodeMirror-linenumber {color: #505050;}
.cm-s-base16-dark .CodeMirror-cursor {border-left: 1px solid #b0b0b0 !important;}
.cm-s-base16-dark span.cm-comment {color: #8f5536;}
.cm-s-base16-dark span.cm-atom {color: #aa759f;}
.cm-s-base16-dark span.cm-number {color: #aa759f;}
.cm-s-base16-dark span.cm-property, .cm-s-base16-dark span.cm-attribute {color: #90a959;}
.cm-s-base16-dark span.cm-keyword {color: #ac4142;}
.cm-s-base16-dark span.cm-string {color: #f4bf75;}
.cm-s-base16-dark span.cm-variable {color: #90a959;}
.cm-s-base16-dark span.cm-variable-2 {color: #6a9fb5;}
.cm-s-base16-dark span.cm-def {color: #d28445;}
.cm-s-base16-dark span.cm-bracket {color: #e0e0e0;}
.cm-s-base16-dark span.cm-tag {color: #ac4142;}
.cm-s-base16-dark span.cm-link {color: #aa759f;}
.cm-s-base16-dark span.cm-error {background: #ac4142; color: #b0b0b0;}
.cm-s-base16-dark .CodeMirror-activeline-background {background: #202020 !important;}
.cm-s-base16-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}

View File

@ -1,36 +0,0 @@
/*
Name: Base16 Default Light
Author: Chris Kempson (http://chriskempson.com)
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-chrome-devtools)
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
*/
.cm-s-base16-light.CodeMirror {background: #f5f5f5; color: #202020;}
.cm-s-base16-light div.CodeMirror-selected {background: #e0e0e0 !important;}
.cm-s-base16-light .CodeMirror-gutters {background: #f5f5f5; border-right: 0px;}
.cm-s-base16-light .CodeMirror-guttermarker { color: #ac4142; }
.cm-s-base16-light .CodeMirror-guttermarker-subtle { color: #b0b0b0; }
.cm-s-base16-light .CodeMirror-linenumber {color: #b0b0b0;}
.cm-s-base16-light .CodeMirror-cursor {border-left: 1px solid #505050 !important;}
.cm-s-base16-light span.cm-comment {color: #8f5536;}
.cm-s-base16-light span.cm-atom {color: #aa759f;}
.cm-s-base16-light span.cm-number {color: #aa759f;}
.cm-s-base16-light span.cm-property, .cm-s-base16-light span.cm-attribute {color: #90a959;}
.cm-s-base16-light span.cm-keyword {color: #ac4142;}
.cm-s-base16-light span.cm-string {color: #f4bf75;}
.cm-s-base16-light span.cm-variable {color: #90a959;}
.cm-s-base16-light span.cm-variable-2 {color: #6a9fb5;}
.cm-s-base16-light span.cm-def {color: #d28445;}
.cm-s-base16-light span.cm-bracket {color: #202020;}
.cm-s-base16-light span.cm-tag {color: #ac4142;}
.cm-s-base16-light span.cm-link {color: #aa759f;}
.cm-s-base16-light span.cm-error {background: #ac4142; color: #505050;}
.cm-s-base16-light .CodeMirror-activeline-background {background: #DDDCDC !important;}
.cm-s-base16-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}

View File

@ -1,30 +0,0 @@
/* Port of TextMate's Blackboard theme */
.cm-s-blackboard.CodeMirror { background: #0C1021; color: #F8F8F8; }
.cm-s-blackboard .CodeMirror-selected { background: #253B76 !important; }
.cm-s-blackboard .CodeMirror-gutters { background: #0C1021; border-right: 0; }
.cm-s-blackboard .CodeMirror-guttermarker { color: #FBDE2D; }
.cm-s-blackboard .CodeMirror-guttermarker-subtle { color: #888; }
.cm-s-blackboard .CodeMirror-linenumber { color: #888; }
.cm-s-blackboard .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; }
.cm-s-blackboard .cm-keyword { color: #FBDE2D; }
.cm-s-blackboard .cm-atom { color: #D8FA3C; }
.cm-s-blackboard .cm-number { color: #D8FA3C; }
.cm-s-blackboard .cm-def { color: #8DA6CE; }
.cm-s-blackboard .cm-variable { color: #FF6400; }
.cm-s-blackboard .cm-operator { color: #FBDE2D;}
.cm-s-blackboard .cm-comment { color: #AEAEAE; }
.cm-s-blackboard .cm-string { color: #61CE3C; }
.cm-s-blackboard .cm-string-2 { color: #61CE3C; }
.cm-s-blackboard .cm-meta { color: #D8FA3C; }
.cm-s-blackboard .cm-builtin { color: #8DA6CE; }
.cm-s-blackboard .cm-tag { color: #8DA6CE; }
.cm-s-blackboard .cm-attribute { color: #8DA6CE; }
.cm-s-blackboard .cm-header { color: #FF6400; }
.cm-s-blackboard .cm-hr { color: #AEAEAE; }
.cm-s-blackboard .cm-link { color: #8DA6CE; }
.cm-s-blackboard .cm-error { background: #9D1E15; color: #F8F8F8; }
.cm-s-blackboard .CodeMirror-activeline-background {background: #3C3636 !important;}
.cm-s-blackboard .CodeMirror-matchingbracket {outline:1px solid grey;color:white !important}

View File

@ -1,23 +0,0 @@
.cm-s-cobalt.CodeMirror { background: #002240; color: white; }
.cm-s-cobalt div.CodeMirror-selected { background: #b36539 !important; }
.cm-s-cobalt .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; }
.cm-s-cobalt .CodeMirror-guttermarker { color: #ffee80; }
.cm-s-cobalt .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
.cm-s-cobalt .CodeMirror-linenumber { color: #d0d0d0; }
.cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-cobalt span.cm-comment { color: #08f; }
.cm-s-cobalt span.cm-atom { color: #845dc4; }
.cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; }
.cm-s-cobalt span.cm-keyword { color: #ffee80; }
.cm-s-cobalt span.cm-string { color: #3ad900; }
.cm-s-cobalt span.cm-meta { color: #ff9d00; }
.cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; }
.cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; }
.cm-s-cobalt span.cm-bracket { color: #d8d8d8; }
.cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; }
.cm-s-cobalt span.cm-link { color: #845dc4; }
.cm-s-cobalt span.cm-error { color: #9d1e15; }
.cm-s-cobalt .CodeMirror-activeline-background {background: #002D57 !important;}
.cm-s-cobalt .CodeMirror-matchingbracket {outline:1px solid grey;color:white !important}

View File

@ -1,23 +0,0 @@
.cm-s-eclipse span.cm-meta {color: #FF1717;}
.cm-s-eclipse span.cm-keyword { line-height: 1em; font-weight: bold; color: #7F0055; }
.cm-s-eclipse span.cm-atom {color: #219;}
.cm-s-eclipse span.cm-number {color: #164;}
.cm-s-eclipse span.cm-def {color: #00f;}
.cm-s-eclipse span.cm-variable {color: black;}
.cm-s-eclipse span.cm-variable-2 {color: #0000C0;}
.cm-s-eclipse span.cm-variable-3 {color: #0000C0;}
.cm-s-eclipse span.cm-property {color: black;}
.cm-s-eclipse span.cm-operator {color: black;}
.cm-s-eclipse span.cm-comment {color: #3F7F5F;}
.cm-s-eclipse span.cm-string {color: #2A00FF;}
.cm-s-eclipse span.cm-string-2 {color: #f50;}
.cm-s-eclipse span.cm-qualifier {color: #555;}
.cm-s-eclipse span.cm-builtin {color: #30a;}
.cm-s-eclipse span.cm-bracket {color: #cc7;}
.cm-s-eclipse span.cm-tag {color: #170;}
.cm-s-eclipse span.cm-attribute {color: #00c;}
.cm-s-eclipse span.cm-link {color: #219;}
.cm-s-eclipse span.cm-error {color: #f00;}
.cm-s-eclipse .CodeMirror-activeline-background {background: #e8f2ff !important;}
.cm-s-eclipse .CodeMirror-matchingbracket {outline:1px solid grey; color:black !important;}

View File

@ -1,13 +0,0 @@
.cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom {color: #762;}
.cm-s-elegant span.cm-comment {color: #262; font-style: italic; line-height: 1em;}
.cm-s-elegant span.cm-meta {color: #555; font-style: italic; line-height: 1em;}
.cm-s-elegant span.cm-variable {color: black;}
.cm-s-elegant span.cm-variable-2 {color: #b11;}
.cm-s-elegant span.cm-qualifier {color: #555;}
.cm-s-elegant span.cm-keyword {color: #730;}
.cm-s-elegant span.cm-builtin {color: #30a;}
.cm-s-elegant span.cm-link {color: #762;}
.cm-s-elegant span.cm-error {background-color: #fdd;}
.cm-s-elegant .CodeMirror-activeline-background {background: #e8f2ff !important;}
.cm-s-elegant .CodeMirror-matchingbracket {outline:1px solid grey; color:black !important;}

View File

@ -1,32 +0,0 @@
.cm-s-erlang-dark.CodeMirror { background: #002240; color: white; }
.cm-s-erlang-dark div.CodeMirror-selected { background: #b36539 !important; }
.cm-s-erlang-dark .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; }
.cm-s-erlang-dark .CodeMirror-guttermarker { color: white; }
.cm-s-erlang-dark .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
.cm-s-erlang-dark .CodeMirror-linenumber { color: #d0d0d0; }
.cm-s-erlang-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-erlang-dark span.cm-atom { color: #f133f1; }
.cm-s-erlang-dark span.cm-attribute { color: #ff80e1; }
.cm-s-erlang-dark span.cm-bracket { color: #ff9d00; }
.cm-s-erlang-dark span.cm-builtin { color: #eaa; }
.cm-s-erlang-dark span.cm-comment { color: #77f; }
.cm-s-erlang-dark span.cm-def { color: #e7a; }
.cm-s-erlang-dark span.cm-keyword { color: #ffee80; }
.cm-s-erlang-dark span.cm-meta { color: #50fefe; }
.cm-s-erlang-dark span.cm-number { color: #ffd0d0; }
.cm-s-erlang-dark span.cm-operator { color: #d55; }
.cm-s-erlang-dark span.cm-property { color: #ccc; }
.cm-s-erlang-dark span.cm-qualifier { color: #ccc; }
.cm-s-erlang-dark span.cm-quote { color: #ccc; }
.cm-s-erlang-dark span.cm-special { color: #ffbbbb; }
.cm-s-erlang-dark span.cm-string { color: #3ad900; }
.cm-s-erlang-dark span.cm-string-2 { color: #ccc; }
.cm-s-erlang-dark span.cm-tag { color: #9effff; }
.cm-s-erlang-dark span.cm-variable { color: #50fe50; }
.cm-s-erlang-dark span.cm-variable-2 { color: #e0e; }
.cm-s-erlang-dark span.cm-variable-3 { color: #ccc; }
.cm-s-erlang-dark span.cm-error { color: #9d1e15; }
.cm-s-erlang-dark .CodeMirror-activeline-background {background: #013461 !important;}
.cm-s-erlang-dark .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;}

Some files were not shown because too many files have changed in this diff Show More