First version

This commit is contained in:
rulingcom 2024-12-02 08:35:08 +08:00
commit 6614479976
98 changed files with 11487 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
.bundle/
log/*.log
pkg/
test/dummy/db/*.sqlite3
test/dummy/db/*.sqlite3-journal
test/dummy/log/*.log
test/dummy/tmp/
test/dummy/.sass-cache

14
Gemfile Normal file
View File

@ -0,0 +1,14 @@
source "https://rubygems.org"
# Declare your gem's dependencies in greeting_card.gemspec.
# Bundler will treat runtime dependencies like base dependencies, and
# development dependencies will be added by default to the :development group.
gemspec
# Declare any dependencies that are still in development here instead of in
# your gemspec. These might include edge Rails or gems from your path or
# Git. Remember to move these dependencies to your gemspec before releasing
# your gem to rubygems.org.
# To use debugger
# gem 'debugger'

17
Gemfile.lock Normal file
View File

@ -0,0 +1,17 @@
PATH
remote: .
specs:
greeting_card (0.0.1)
GEM
remote: https://rubygems.org/
specs:
PLATFORMS
x86_64-linux
DEPENDENCIES
greeting_card!
BUNDLED WITH
2.3.19

20
MIT-LICENSE Normal file
View File

@ -0,0 +1,20 @@
Copyright 2014 YOURNAME
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

3
README.rdoc Normal file
View File

@ -0,0 +1,3 @@
= GreetingCard
This project rocks and uses MIT-LICENSE.

32
Rakefile Normal file
View File

@ -0,0 +1,32 @@
begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end
require 'rdoc/task'
RDoc::Task.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'GreetingCard'
rdoc.options << '--line-numbers'
rdoc.rdoc_files.include('README.rdoc')
rdoc.rdoc_files.include('lib/**/*.rb')
end
Bundler::GemHelper.install_tasks
require 'rake/testtask'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = false
end
task default: :test

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none"><path stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 10V5m0 0L4 7m2-2 2 2m-2 7v5m0 0 2-2m-2 2-2-2m8-10h8m0 5h-8m0 5h8"/></svg>

After

Width:  |  Height:  |  Size: 386 B

View File

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

View File

@ -0,0 +1,75 @@
$(document).ready(function(){
var temp_layer;
$('.preview-card').on('click', function(ev, form) {
var active_form, selected_img, category_select,
category_idx = 0;
if (!form)
form = $(this).parents('form');
category_select = form.find('select#greeting_card_record_category_id');
// form maybe not the same as active_form when multiple category exist
if (category_select.length != 0)
{
var selected_option = category_select.find('option:selected');
active_form = $('form#' + selected_option.prop('value'));
category_idx = selected_option.index();
}
else
{
active_form = $('.greeting_card_form');
}
selected_img = active_form.find('.card_images_wrapper input:checked').siblings('img');
if (selected_img.length == 0)
return false;
var img_url = selected_img.attr('src');
if (img_url)
{
var layer;
var data = {};
var fields = collected_fields[category_idx];
var objs = card_img_objs[category_idx];
fields.forEach(function(f) {
var field_input = active_form.find("#greeting_card_record_" + f);
data[f] = field_input.val();
});
if (temp_layer)
{
destroy_layer(temp_layer);
}
layer = create_konva(active_form.find(".preview-card-section"), 'card-container', img_url, data);
window.layer = layer;
objs.forEach(function(obj) {
create_text_box(layer,
{x: obj.x, y: obj.y, w: obj.w, h: obj.h, l_h: obj.l_h},
obj.text,
obj.fontSize, obj.fontFamily, obj.fontColor,
(obj.is_stroke == 'true'), obj.stroke, obj.strokeWidth,
(obj.is_fill == 'true'));
});
fields.forEach(function(f) {
var field_input = active_form.find("#greeting_card_record_" + f);
field_input.on("input", function() {
layer.container.trigger("change", [f, $(this).val()]);
})
});
active_form.find("input[name=\"greeting_card_record[card_id]\"]").on("change", function() {
layer.container_img.attr('src', $(this).siblings('img').attr('src'));
})
temp_layer = layer;
}
});
$('select#greeting_card_record_category_id').on('change', function() {
if (temp_layer)
{
var form = $(this).parents('form');
form.find('.preview-card').trigger('click', [form]);
}
})
})

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,287 @@
Array.prototype.removeItem = function(v) {
function removeValue(value, index, arr) {
// If the value at the current array index matches the specified value (2)
if (value === v) {
// Removes the value from the original array
arr.splice(index, 1);
return true;
}
return false;
}
// Pass the removeValue function into the filter function to return the specified value
return this.filter(removeValue)[0];
};
if (!(String.prototype.replaceAll))
{
String.prototype.replaceAll = function (FindText,RepText) {
regExp = new RegExp(FindText, "g");
return this.replace(regExp,RepText);
}
}
function apply_scale(layer, box)
{
box.x( box.org_x * layer.w_scale );
box.y( box.org_y * layer.h_scale );
if (box.org_w != 'auto')
box.width( box.org_w * layer.w_scale );
if (box.org_h != 'auto')
box.height( box.org_h * layer.h_scale );
box.fontSize( box.org_fontSize * layer.font_scale);
box.strokeWidth( box._strokeWidth * layer.font_scale);
box.scaled = true;
}
function create_konva(container_wrapper, container_id, img_url, data)
{
var container_inner_wrapper = $("<div id=\"container-inner-wrapper\"></div>")
var container_img = $("<img id=\"container-img\" src=\"" + img_url + "\" />");
var container = $("<div id=\"" + container_id + "\"></div>");
var layer = new Konva.Layer({draggable: false});
container_inner_wrapper.appendTo(container_wrapper).append(container_img).append(container);
layer.font_scale = null;
layer.w_scale = null;
layer.h_scale = null;
container_img.on("load", function(){
var img_width = container_img.outerWidth(true),
img_height = container_img.outerHeight(true);
var stage = new Konva.Stage({
container: container_id,
width: img_width,
height: img_height
});
// add canvas element
layer.font_scale = img_width / 500;
layer.img_width = img_width;
layer.img_height = img_height;
layer.w_scale = img_width / 100;
layer.h_scale = img_height / 100;
layer.text_boxes.forEach(function(box) {
if (box.scaled)
return;
else
{
apply_scale(layer, box);
}
});
layer.pending_boxes.forEach(function(args) {
args[0] = layer;
create_text_box.apply(null, args);
});
layer.pending_boxes = [];
stage.add(layer);
});
layer.container_inner_wrapper = container_inner_wrapper;
layer.container = container;
layer.container_img = container_img;
layer.data = data;
layer.text_boxes = [];
layer.pending_boxes = [];
layer.resize_func = function(container_img) {
var img_width, img_height;
var stage = this.getStage();
if (this.resized)
{
window.setTimeout(function(){
this.resize_func(container_img);
}.bind(this), 100);
return;
}
this.resized = true;
stage.setWidth();
stage.setHeight();
img_width = container_img.outerWidth(true);
img_height = container_img.outerHeight(true);
stage.setWidth(img_width);
stage.setHeight(img_height);
this.font_scale = img_width / 500;
this.w_scale = img_width / 100;
this.h_scale = img_height / 100;
this.img_width = img_width;
this.img_height = img_height;
this.pending_boxes = [null];
this.text_boxes.forEach(function(box) {
apply_scale(this, box);
}.bind(this));
this.pending_boxes = [];
this.resized = false;
}.bind(layer, container_img);
$(window).on("resize", layer.resize_func);
return layer;
}
function create_text_box(layer, pos, text, fontSize, fontFamily, fontColor, is_stroke, stroke, strokeWidth, is_fill)
{
if (!layer)
return;
if (!layer.font_scale || !layer.w_scale || !layer.h_scale)
{
layer.pending_boxes.push(arguments);
return;
}
else if (layer.pending_boxes.length != 0)
{
var args = arguments;
window.setTimeout(function(args){
create_text_box.apply(this, args);
}.bind(this, args), 100);
return;
}
var scaled = false;
var org_fontSize = fontSize,
org_x = pos.x,
org_y = pos.y,
x, y, w, h,
org_w, org_h,
org_text = text,
_strokeWidth,
observe_fields = [],
observe_func;
if (!fontFamily)
fontFamily = 'Calibri';
if (!fontColor)
fontColor = '#333333';
if (!stroke)
stroke = '#333333';
if (!strokeWidth)
strokeWidth = 2;
_strokeWidth = strokeWidth;
org_w = (pos.w == 0 ? 'auto' : pos.w);
org_h = (pos.h == 0 ? 'auto' : pos.h);
x = pos.x;
y = pos.y;
w = org_w;
h = org_h;
text = org_text.replace(/{([^{}]+)}/g, function(_, f) {
observe_fields.push(f);
return layer.data[f];
});
if (layer.font_scale && layer.w_scale && layer.h_scale)
{
x = pos.x * layer.w_scale;
y = pos.y * layer.h_scale;
if (w != 'auto')
w *= layer.w_scale;
if (h != 'auto')
h *= layer.h_scale;
fontSize *= layer.font_scale;
strokeWidth *= layer.font_scale;
scaled = true;
}
if (!is_stroke)
is_fill = true;
// create shape
var textNode = new Konva.Text({
text: text,
width: w,
height: h,
x: x,
y: y,
lineHeight: pos.l_h,
fontSize: fontSize,
draggable: true,
fontFamily: fontFamily,
stroke: (is_stroke ? stroke : null),
strokeWidth: (is_stroke ? strokeWidth : null),
fillAfterStrokeEnabled: true
});
textNode.fill((is_fill ? fontColor : false));
layer.add(textNode);
textNode._fill = fontColor;
textNode.scaled = scaled;
textNode.org_fontSize = org_fontSize;
textNode.org_x = org_x;
textNode.org_y = org_y;
textNode.org_w = org_w;
textNode.org_h = org_h;
textNode.org_text = org_text;
textNode.is_stroke = is_stroke;
textNode.is_fill = is_fill;
textNode._stroke = stroke;
textNode._strokeWidth = _strokeWidth;
textNode.observe_fields = observe_fields;
if (observe_fields.length != 0) {
observe_func = function(layer, event, f, content) {
if ($.inArray(f, this.observe_fields) != -1)
{
var new_text;
if (this.prev_change == f)
{
new_text = this.cached_text;
}
else
{
var other_fields = Array.from(this.observe_fields);
other_fields.removeItem(f);
new_text = this.org_text;
other_fields.forEach(function(ff) {
new_text = new_text.replaceAll('{' + ff + '}', layer.data[ff]);
})
this.cached_text = new_text;
this.prev_change = f;
}
layer.data[f] = content;
new_text = new_text.replaceAll('{' + f + '}', content);
this.text(new_text);
}
}.bind(textNode, layer);
textNode.observe_func = observe_func;
layer.container.on("change", observe_func);
}
layer.text_boxes.push(textNode);
return textNode;
}
function destroy_text(textNode)
{
if (textNode.observe_func)
layer.container.off("change", textNode.observe_func);
textNode.destroy();
}
function destroy_layer(layer)
{
layer.text_boxes.forEach(function(textNode) {
destroy_text(textNode);
});
$(window).off("resize", layer.resize_func);
layer.destroy();
layer.container_inner_wrapper.remove();
}

View File

@ -0,0 +1,796 @@
function _round(num, i)
{
if (i == 0 || i == undefined)
{
return Math.round(num);
}
else
{
var scale = 10 ** i;
return Math.round(num * scale) / scale;
}
}
function apply_scale(layer, box)
{
box.x( box.org_x * layer.w_scale );
box.y( box.org_y * layer.h_scale );
if (box.org_w != 'auto')
box.width( box.org_w * layer.w_scale );
if (box.org_h != 'auto')
box.height( box.org_h * layer.h_scale );
box.fontSize( box.org_fontSize * layer.font_scale);
box.strokeWidth( box._strokeWidth * layer.font_scale);
box.scaled = true;
}
function create_konva(container_wrapper, container_hidden_field, container_id, img_url, fonts, trans)
{
var lineheight_trans = "Line Height",
stroke_trans = "Stroke",
fill_trans = "Fill";
if (trans && trans['lineheight'])
lineheight_trans = trans['lineheight'];
if (trans && trans['stroke'])
stroke_trans = trans['stroke'];
else
stroke_trans = [stroke_trans, stroke_trans];
var fill_trans = "Fill";
if (trans && trans['fill'])
fill_trans = trans['fill'];
else
fill_trans = [fill_trans, fill_trans];
var toolbar_wrapper = $("<div class=\"toolbar-wrapper\"></div>");
var container_inner_wrapper = $("<div id=\"container-inner-wrapper\"></div>")
var color_picker = $("<input title=\"" + fill_trans[1] + "\" disabled class=\"set_color color-picker font-color\" value=\"#333333\" type=\"color\"/>");
var font_picker = $("<select class=\"font-picker\" disabled></select>");
var fontsize_picker = $("<input type=\"number\" class=\"fontsize-picker\" value=\"20\" disabled />");
var lineheight_picker = $("<span class=\"line-height-picker-wrapper\"><img src=\"/assets/line-height-line.svg\" title=\"" + lineheight_trans + "\" alt=\"" + lineheight_trans + "\"><input type=\"number\" step=\"0.1\" class=\"line-height-picker\" value=\"1.0\" disabled /></span>")
var stroke_checker = $("<span title=\"" + stroke_trans[1] +"\"><input type=\"checkbox\" class=\"stroke-checker\" value=\"1\" disabled />" + stroke_trans[0] + "</span>");
var stroke_picker = $("<input disabled class=\"set_color color-picker stroke-color hide\" value=\"#333333\" type=\"color\" />");
var strokeWidth_picker = $("<input type=\"number\" step=\"0.1\" class=\"strokeWidth-picker hide\" value=\"2\" />");
var fill_checker = $("<span class=\"fill-checker-wrapper hide\" title=\"" + fill_trans[1] +"\"><input type=\"checkbox\" class=\"fill-checker\" value=\"1\" checked />" + fill_trans[0] + "</span>");
var add_btn = $("<button type=\"button\" class=\"fa fa-add btn btn-info pull-right\" disabled></button>");
var remove_btn = $("<button type=\"button\" class=\"fa fa-remove btn btn-danger pull-right\" disabled></button>");
var container_img = $("<img id=\"container-img\" src=\"" + img_url + "\" />");
var container = $("<div id=\"" + container_id + "\"></div>");
var layer = new Konva.Layer({draggable: false});
var hidden_field_name = container_hidden_field.data('name');
toolbar_wrapper.append(color_picker);
toolbar_wrapper.append(font_picker);
toolbar_wrapper.append(fontsize_picker);
toolbar_wrapper.append(lineheight_picker);
toolbar_wrapper.append(stroke_checker);
toolbar_wrapper.append(stroke_picker);
toolbar_wrapper.append(strokeWidth_picker);
toolbar_wrapper.append(fill_checker);
toolbar_wrapper.append(add_btn);
toolbar_wrapper.append(remove_btn);
toolbar_wrapper.appendTo(container_wrapper);
container_inner_wrapper.appendTo(container_wrapper).append(container_img).append(container);
lineheight_picker = lineheight_picker.find('>input');
stroke_checker = stroke_checker.find('>input');
fill_checker = fill_checker.find('>input');
$.each(fonts, function(i, font){
font_picker.append(new Option(font, i.toString()));
});
font_picker.select2({
// templateResult: function(el){
// var $element = $(el.element),
// image = $element.data("image");
// return $("<img class='thumbnail' src='" + image + "'/><span class='thumbnail-text'>" + el.text + "</span>");
// },
// minimumResultsForSearch: -1,
// width : 250
});
layer.font_scale = null;
layer.w_scale = null;
layer.h_scale = null;
container_img.on("load", function(){
var img_width = container_img.outerWidth(true),
img_height = container_img.outerHeight(true);
var stage = new Konva.Stage({
container: container_id,
width: img_width,
height: img_height
});
// add canvas element
layer.font_scale = img_width / 500;
layer.img_width = img_width;
layer.img_height = img_height;
layer.w_scale = img_width / 100;
layer.h_scale = img_height / 100;
layer.text_boxes.forEach(function(box) {
if (box.scaled)
return;
else
{
apply_scale(layer, box);
}
});
layer.pending_boxes.forEach(function(args) {
args[0] = layer;
create_text_box.apply(null, args);
});
layer.pending_boxes = [];
add_btn.removeAttr('disabled');
remove_btn.removeAttr('disabled');
stage.add(layer);
});
color_picker.on('input', function(layer){
var target_node = layer.target_node;
if (target_node)
{
var _fill = this.val();
target_node._fill = _fill;
if (target_node.is_fill)
target_node.fill(_fill);
target_node.hidden_field_dict.fontColor.val(_fill);
layer.container_hidden_field.trigger("change");
}
}.bind(color_picker, layer));
stroke_picker.on('input', function(layer){
var target_node = layer.target_node;
if (target_node)
{
var _stroke = this.val();
target_node._stroke = _stroke;
if (target_node.is_stroke)
target_node.stroke(_stroke);
target_node.hidden_field_dict.stroke.val(_stroke);
layer.container_hidden_field.trigger("change");
}
}.bind(stroke_picker, layer));
layer.container = container;
layer.container_hidden_field = container_hidden_field;
layer.hidden_field_name = hidden_field_name;
layer.box_idx = -1;
layer.fonts = fonts;
layer.color_picker = color_picker;
layer.font_picker = font_picker;
layer.fontsize_picker = fontsize_picker;
layer.lineheight_picker = lineheight_picker;
layer.stroke_checker = stroke_checker;
layer.stroke_picker = stroke_picker;
layer.strokeWidth_picker = strokeWidth_picker;
layer.fill_checker = fill_checker;
layer.max_y = null;
layer.default_fontsize = 20;
layer.text_boxes = [];
layer.pending_boxes = [];
font_picker.on('change', function(fonts, layer){
var target_node = layer.target_node;
if (target_node)
{
var fontFamily = fonts[Number(this.val())];
target_node.fontFamily(fontFamily);
target_node.hidden_field_dict.fontFamily.val(fontFamily);
layer.container_hidden_field.trigger("change");
}
}.bind(font_picker, fonts, layer));
fontsize_picker.on('change', function(layer){
var target_node = layer.target_node;
if (target_node)
{
var org_fontSize = Number(this.val());
var new_fontSize = layer.font_scale * org_fontSize;
var org_height = target_node.height();
var newlines = target_node.getText().match(/\n/g);
var height_diff = new_fontSize * ((newlines ? newlines.length : 0) + 1) - org_height - 2 * target_node.padding();
target_node.fontSize(new_fontSize);
target_node.org_fontSize = org_fontSize;
target_node.hidden_field_dict.fontSize.val(org_fontSize.toString());
layer.container_hidden_field.trigger("change");
if (height_diff > 0)
{
target_node.height(org_height + height_diff);
}
}
}.bind(fontsize_picker, layer));
lineheight_picker.on('change', function(layer){
var target_node = layer.target_node;
if (target_node)
{
var lineHeight = Number(this.val());
var fontSize = target_node.fontSize();
var org_height = target_node.height();
var newlines = target_node.getText().match(/\n/g);
var height_diff = fontSize * ((newlines ? newlines.length : 0) + 1) * lineHeight - org_height - 2 * target_node.padding();
target_node.setLineHeight(lineHeight);
target_node.hidden_field_dict.l_h.val(lineHeight.toString());
layer.container_hidden_field.trigger("change");
if (height_diff > 0)
{
target_node.height(org_height + height_diff);
}
}
}.bind(lineheight_picker, layer));
strokeWidth_picker.on('input', function(layer){
var target_node = layer.target_node;
if (target_node)
{
var org_strokeWidth = Number(this.val());
if (isNaN(org_strokeWidth))
return;
var new_strokeWidth = layer.font_scale * org_strokeWidth;
target_node.strokeWidth(new_strokeWidth);
target_node._strokeWidth = org_strokeWidth;
target_node.hidden_field_dict.strokeWidth.val(org_strokeWidth.toString());
layer.container_hidden_field.trigger("change");
}
}.bind(strokeWidth_picker, layer));
stroke_checker.on('change', function(layer){
var target_node = layer.target_node;
if (target_node)
{
var is_stroke = this.prop("checked");
if (is_stroke)
{
layer.stroke_checker.attr("checked", "");
layer.stroke_picker.removeClass("hide");
layer.strokeWidth_picker.removeClass("hide");
layer.fill_checker.parent().removeClass("hide");
target_node.stroke(target_node._stroke);
}
else
{
layer.stroke_checker.removeAttr("checked");
layer.stroke_picker.addClass("hide");
layer.strokeWidth_picker.addClass("hide");
layer.fill_checker.parent().addClass("hide");
target_node.stroke(null);
}
target_node.is_stroke = is_stroke;
target_node.hidden_field_dict.is_stroke.val(is_stroke.toString());
layer.container_hidden_field.trigger("change");
}
}.bind(stroke_checker, layer));
fill_checker.on('change', function(layer){
var target_node = layer.target_node;
if (target_node)
{
var is_fill = this.prop("checked");
if (is_fill)
{
target_node.fill(target_node._fill);
}
else
{
target_node.fill(null);
}
target_node.is_fill = is_fill;
target_node.hidden_field_dict.is_fill.val(is_fill.toString());
layer.container_hidden_field.trigger("change");
}
}.bind(fill_checker, layer));
add_btn.on('click', function(layer) {
create_text_box(layer, {x: 50, y: (layer.max_y || 50) + layer.default_fontsize * 100 / layer.img_width, w: 'auto', h: 'auto'}, "Some text here", layer.default_fontsize);
layer.container_hidden_field.trigger("change");
}.bind(add_btn, layer));
remove_btn.on('click', function(layer) {
var target_node = layer.target_node;
if (target_node)
{
destroy_text(target_node);
}
}.bind(remove_btn, layer));
container.prop('tabIndex', 1);
container.focus();
container.on('keydown', function(layer, event) {
const key = event.key;
if (key === "Backspace" || key === "Delete") {
var target_node = layer.target_node;
if (target_node)
{
destroy_text(target_node);
}
}
}.bind(container, layer));
layer.resize_func = function(container_img) {
var img_width, img_height;
var stage = this.getStage();
if (this.resized)
{
window.setTimeout(function(){
this.resize_func(container_img);
}.bind(this), 100);
return;
}
this.resized = true;
stage.setWidth();
stage.setHeight();
img_width = container_img.outerWidth(true);
img_height = container_img.outerHeight(true);
stage.setWidth(img_width);
stage.setHeight(img_height);
this.font_scale = img_width / 500;
this.w_scale = img_width / 100;
this.h_scale = img_height / 100;
this.img_width = img_width;
this.img_height = img_height;
this.pending_boxes = [null];
this.text_boxes.forEach(function(box) {
apply_scale(this, box);
}.bind(this));
this.pending_boxes = [];
this.resized = false;
}.bind(layer, container_img);
$(window).on("resize", layer.resize_func);
return layer;
}
function text_box_to_hidden_field(hidden_field_name, idx)
{
var x = this.org_x.toString();
var y = this.org_y.toString();
var w = this.org_w.toString();
var h = this.org_h.toString();
var l_h = this.lineHeight().toString();
var text = this.text();
var fontSize = this.org_fontSize.toString();
var fontFamily = this.fontFamily();
var fontColor = this.fill();
var is_fill = this.is_fill ? 'true' : 'false';
var is_stroke = this.is_stroke ? 'true' : 'false';
var stroke = this._stroke ? this._stroke : '';
var strokeWidth = this._strokeWidth ? this._strokeWidth : '';
var hidden_field_dict = {
"x": $("<input type=\"hidden\" name=\"" + hidden_field_name + "[" + idx.toString() + "][x]\" value=\"" + x + "\" />"),
"y": $("<input type=\"hidden\" name=\"" + hidden_field_name + "[" + idx.toString() + "][y]\" value=\"" + y + "\" />"),
"w": $("<input type=\"hidden\" name=\"" + hidden_field_name + "[" + idx.toString() + "][w]\" value=\"" + w + "\" />"),
"h": $("<input type=\"hidden\" name=\"" + hidden_field_name + "[" + idx.toString() + "][h]\" value=\"" + h + "\" />"),
"l_h": $("<input type=\"hidden\" name=\"" + hidden_field_name + "[" + idx.toString() + "][l_h]\" value=\"" + l_h + "\" />"),
"text": $("<input type=\"hidden\" name=\"" + hidden_field_name + "[" + idx.toString() + "][text]\" value=\"" + text + "\" />"),
"fontSize": $("<input type=\"hidden\" name=\"" + hidden_field_name + "[" + idx.toString() + "][fontSize]\" value=\"" + fontSize + "\" />"),
"fontFamily": $("<input type=\"hidden\" name=\"" + hidden_field_name + "[" + idx.toString() + "][fontFamily]\" value=\"" + fontFamily + "\" />"),
"fontColor": $("<input type=\"hidden\" name=\"" + hidden_field_name + "[" + idx.toString() + "][fontColor]\" value=\"" + fontColor + "\" />"),
"is_fill": $("<input type=\"hidden\" name=\"" + hidden_field_name + "[" + idx.toString() + "][is_fill]\" value=\"" + is_fill + "\" />"),
"is_stroke": $("<input type=\"hidden\" name=\"" + hidden_field_name + "[" + idx.toString() + "][is_stroke]\" value=\"" + is_stroke + "\" />"),
"stroke": $("<input type=\"hidden\" name=\"" + hidden_field_name + "[" + idx.toString() + "][stroke]\" value=\"" + stroke + "\" />"),
"strokeWidth": $("<input type=\"hidden\" name=\"" + hidden_field_name + "[" + idx.toString() + "][strokeWidth]\" value=\"" + strokeWidth + "\" />"),
};
Object.keys(hidden_field_dict).forEach(function(dict, k)
{
dict[k].appendTo(this.hidden_field_block);
}.bind(this, hidden_field_dict));
return hidden_field_dict;
}
function create_text_box(layer, pos, text, fontSize, fontFamily, fontColor, is_stroke, stroke, strokeWidth, is_fill)
{
if (!layer)
return;
if (!layer.font_scale || !layer.w_scale || !layer.h_scale)
{
layer.pending_boxes.push(arguments);
return;
}
else if (layer.pending_boxes.length != 0)
{
var args = arguments;
window.setTimeout(function(args){
create_text_box.apply(this, args);
}.bind(this, args), 100);
return;
}
var scaled = false;
var org_fontSize = fontSize,
org_x = pos.x,
org_y = pos.y,
x, y, w, h,
line_height,
org_w, org_h,
_strokeWidth;
var hidden_field_block = $("<div class=\"hidden-field-block\"></div>");
var hidden_field_dict;
if (!fontFamily)
fontFamily = 'Calibri';
if (!fontColor)
fontColor = '#333333';
if (!stroke)
stroke = '#333333';
if (!strokeWidth)
strokeWidth = 2;
_strokeWidth = strokeWidth;
org_w = (pos.w == 0 ? 'auto' : pos.w);
org_h = (pos.h == 0 ? 'auto' : pos.h);
x = pos.x;
y = pos.y;
w = org_w;
h = org_h;
if (layer.font_scale && layer.w_scale && layer.h_scale)
{
x = pos.x * layer.w_scale;
y = pos.y * layer.h_scale;
if (w != 'auto')
w *= layer.w_scale;
if (h != 'auto')
h *= layer.h_scale;
fontSize *= layer.font_scale;
strokeWidth *= layer.font_scale;
scaled = true;
}
if (!is_stroke)
is_fill = true;
// create shape
var textNode = new Konva.Text({
text: text,
width: w,
height: h,
x: x,
y: y,
lineHeight: pos.l_h,
fontSize: fontSize,
draggable: true,
fontFamily: fontFamily,
stroke: (is_stroke ? stroke : null),
strokeWidth: (is_stroke ? strokeWidth : null),
fillAfterStrokeEnabled: true
});
textNode.fill((is_fill ? fontColor : false));
layer.add(textNode);
textNode._fill = fontColor;
textNode.scaled = scaled;
textNode.org_fontSize = org_fontSize;
textNode.org_x = org_x;
textNode.org_y = org_y;
textNode.org_w = org_w;
textNode.org_h = org_h;
textNode.is_stroke = is_stroke;
textNode.is_fill = is_fill;
textNode._stroke = stroke;
textNode._strokeWidth = _strokeWidth;
textNode.hidden_field_block = hidden_field_block;
if (layer.max_y)
layer.max_y = Math.max(layer.max_y, pos.y);
else
layer.max_y = pos.y;
layer.box_idx += 1;
hidden_field_dict = text_box_to_hidden_field.call(textNode, layer.hidden_field_name, layer.box_idx);
layer.container_hidden_field.append(hidden_field_block);
textNode.hidden_field_dict = hidden_field_dict;
// textNode.on('transformend', function () {
// console.log('transform end - before reset font size = ' + this.fontSize() + ' at scale ' + this.scaleX());
// this.fontSize(this.fontSize() * this.scaleX());
// this.scale({x: 1, y: 1});
// layer.batchDraw();
// console.log('transform end - after reset font size = ' + this.fontSize() + ' at scale ' + this.scaleX());
// });
textNode.on('transformend', function (layer) {
this.org_w = _round(this.width() / layer.w_scale, 5);
this.org_h = _round(this.height() / layer.h_scale, 5);
this.hidden_field_dict.w.val(this.org_w.toString());
this.hidden_field_dict.h.val(this.org_h.toString());
layer.container_hidden_field.trigger("change");
}.bind(textNode, layer));
textNode.on('dragend', function () {
this.org_x = _round(this.x() / layer.w_scale, 5);
this.org_y = _round(this.y() / layer.h_scale, 5);
this.hidden_field_dict.x.val(this.org_x.toString());
this.hidden_field_dict.y.val(this.org_y.toString());
layer.container_hidden_field.trigger("change");
}.bind(textNode));
textNode.on('transform', function() {
this.setAttrs({
width: Math.max(this.width() * this.scaleX(), 5),
height: Math.max(this.height() * this.scaleY(), 5),
scaleX: 1,
scaleY: 1,
});
}.bind(textNode));
var tr_border = new Konva.Transformer({
// node: textNode,
keepRatio: false,
borderEnabled: true,
borderStrokeWidth: 3,
rotateEnabled: false,
enabledAnchors: []
});
var tr = new Konva.Transformer({
// node: textNode,
ignoreStroke: true,
rotateEnabled: false,
// flipEnabled: false,
keepRatio: false,
borderEnabled: true,
// enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
// set minimum width of text
boundBoxFunc: function (oldBox, newBox) {
newBox.width = Math.max(30, newBox.width);
return newBox;
},
});
textNode.children = [tr, tr_border];
// window.tr_border = tr_border;
// window.tr = tr;
// window.layer = layer;
layer.add(tr_border);
layer.add(tr);
// add cursor styling
textNode.on('mouseover', function(tr_border) {
document.body.style.cursor = 'pointer';
if (tr_border.nodes().length == 0)
{
tr_border.nodes([this]);
tr_border.forceUpdate();
}
}.bind(textNode, tr_border));
textNode.on('mouseout', function(tr_border) {
document.body.style.cursor = 'default';
if (tr_border.nodes().length != 0)
{
tr_border.nodes([]);
tr_border.forceUpdate();
}
}.bind(textNode, tr_border));
textNode.on('click', function(tr, layer, _, e) {
if (tr.nodes().length == 0)
{
tr.nodes([this]);
tr.forceUpdate();
layer.target_node = this;
layer.color_picker.removeAttr('disabled');
layer.font_picker.removeAttr('disabled');
layer.fontsize_picker.removeAttr('disabled');
layer.lineheight_picker.removeAttr('disabled');
layer.stroke_checker.removeAttr('disabled');
layer.stroke_picker.removeAttr('disabled');
layer.color_picker.val(this._fill);
layer.font_picker.val(layer.fonts.indexOf(this.fontFamily()).toString());
layer.fontsize_picker.val(this.org_fontSize.toString());
layer.lineheight_picker.val(this.lineHeight().toString());
layer.stroke_checker.prop("checked", this.is_stroke);
layer.fill_checker.prop("checked", this.is_fill);
layer.stroke_picker.val(this._stroke);
layer.strokeWidth_picker.val(this._strokeWidth);
if (this.is_stroke)
{
layer.stroke_checker.attr("checked", "");
layer.stroke_picker.removeClass("hide");
layer.strokeWidth_picker.removeClass("hide");
layer.fill_checker.parent().removeClass("hide");
}
else
{
layer.stroke_checker.removeAttr("checked");
layer.stroke_picker.addClass("hide");
layer.strokeWidth_picker.addClass("hide");
layer.fill_checker.parent().addClass("hide");
}
layer.font_picker.trigger("change");
}
this.click_triggered = true;
layer.click_triggered = true;
}.bind(textNode, tr, layer));
textNode.global_click = function(tr, layer, e) {
if (this.click_triggered) {
this.click_triggered = false;
return;
}
if (tr.nodes().length != 0)
{
tr.nodes([]);
tr.forceUpdate();
if (!layer.click_triggered)
{
layer.target_node = null;
layer.color_picker.attr('disabled', '');
layer.font_picker.attr('disabled', '');
layer.fontsize_picker.attr('disabled', '');
layer.lineheight_picker.attr('disabled', '');
layer.stroke_checker.prop('checked', false);
layer.stroke_checker.attr('disabled', '');
layer.stroke_picker.attr('disabled', '');
layer.stroke_picker.addClass("hide");
layer.strokeWidth_picker.addClass("hide");
layer.fill_checker.parent().addClass("hide");
}
}
if (layer.click_triggered)
{
layer.click_triggered = false;
}
}.bind(textNode, tr, layer);
layer.container.on('click', textNode.global_click);
textNode.on('dblclick dbltap', function(tr, layer) {
var textNode = this;
// hide text node and transformer:
this.hide();
// tr.hide();
// create textarea over canvas with absolute position
// first we need to find position for textarea
// how to find it?
// at first lets find position of text node relative to the stage:
var textPosition = this.absolutePosition();
// so position of textarea will be the sum of positions above:
var areaPosition = {
x: layer.container.prop('offsetLeft') + textPosition.x,
y: layer.container.prop('offsetTop') + textPosition.y,
};
// create textarea and style it
var textarea = document.createElement('textarea');
layer.container.parent().append(textarea);
// apply many styles to match text on canvas as close as possible
// remember that text rendering on canvas and on the textarea can be different
// and sometimes it is hard to make it 100% the same. But we will try...
textarea.value = this.text();
textarea.style.top = areaPosition.y + 'px';
textarea.style.left = areaPosition.x + 'px';
textarea.style.width = this.width() - this.padding() * 2 + 'px';
textarea.style.height =
this.height() - this.padding() * 2 + 'px';
textarea.style.fontSize = this.fontSize() + 'px';
textarea.style.lineHeight = this.lineHeight();
textarea.style.fontFamily = this.fontFamily();
textarea.style.textAlign = this.align();
textarea.style.color = this._fill;
rotation = this.rotation();
var transform = '';
if (rotation) {
transform += 'rotateZ(' + rotation + 'deg)';
}
var px = 0;
// also we need to slightly move textarea on firefox
// because it jumps a bit
var isFirefox =
navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
if (isFirefox) {
px += 2 + Math.round(this.fontSize() / 20);
}
transform += 'translateY(-' + px + 'px)';
textarea.style.transform = transform;
// reset height
// textarea.style.height = 'auto';
// // after browsers resized it we can set actual value
// textarea.style.height = textarea.scrollHeight + 3 + 'px';
textarea.focus();
function removeTextarea() {
textNode.hidden_field_dict.text.val(textNode.text());
layer.container_hidden_field.trigger("change");
textarea.parentNode.removeChild(textarea);
window.removeEventListener('click', handleOutsideClick);
// textNode.width('auto');
textNode.show();
// tr.show();
tr.forceUpdate();
}
function setTextareaWidth(newWidth) {
if (!newWidth) {
// set width for placeholder
newWidth = this.placeholder.length * this.fontSize();
}
// some extra fixes on different browsers
var isSafari = /^((?!chrome|android).)*safari/i.test(
navigator.userAgent
);
var isFirefox =
navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
if (isSafari || isFirefox) {
newWidth = Math.ceil(newWidth);
}
var isEdge =
document.documentMode || /Edge/.test(navigator.userAgent);
if (isEdge) {
newWidth += 1;
}
textarea.style.width = newWidth + 'px';
}
textarea.addEventListener('keydown', function (e) {
// hide on enter
// but don't hide on shift + enter
if (e.keyCode === 13 && !e.shiftKey) {
textNode.text(textarea.value);
removeTextarea();
}
// on esc do not set value back to node
if (e.keyCode === 27) {
removeTextarea();
}
});
textarea.addEventListener('keydown', function (e) {
scale = textNode.getAbsoluteScale().x;
setTextareaWidth(textNode.width() * scale);
// textarea.style.height = 'auto';
// textarea.style.height =
// textarea.scrollHeight + textNode.fontSize() + 'px';
});
function handleOutsideClick(e) {
if (e.target !== textarea) {
textNode.text(textarea.value);
removeTextarea();
}
}
setTimeout(function(){
window.addEventListener('click', handleOutsideClick);
});
}.bind(textNode, tr, layer));
layer.text_boxes.push(textNode);
return textNode;
}
function destroy_text(target_node)
{
target_node.children.forEach(function(child){
child.destroy();
})
target_node.hidden_field_block.remove();
target_node.destroy();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
/*
Place all the styles related to the matching controller here.
They will automatically be included in application.css.
*/
.table .expired{
color: #BE2E2E;
}

View File

@ -0,0 +1,28 @@
input[type=checkbox] {
font-size: 1em;
/*-webkit-appearance: none;*/
width: 1.2em;
height: 1.2em;
border-radius: 5px;
margin: 0.2em;
border: 0.12em solid;
}
input[type=checkbox]:checked {
background: #90b8d9;
}
input[type=checkbox]:focus {
outline: none;
}
@media (max-width: 768px){
.greeting_card-question .control-group{
justify-content: center;
}
}
.file-selector,.greeting_card-question .controls >.file-selector{
display: inline-flex;
flex-wrap: wrap;
justify-content: center;
}
.filename{
word-break: break-all;
}

View File

@ -0,0 +1,3 @@
.preview-card-section {
margin-top: 2em;
}

View File

@ -0,0 +1,71 @@
.greeting_card-question .control-group.col-sm-6:nth-child(2n+1) {
clear: left;
}
.greeting_card-question .controls label.radio-inline{
float: left;
}
.greeting_card_form {
background-color: #fdfdfd;
padding: 2em;
}
.greeting_card_form .control-group {
margin-bottom: 1em;
padding-bottom: 0.5em;
}
.greeting_card_form .control-label {
font-size: 1em;
float: left;
width: 10em;
text-align: right;
line-height: 1em;
margin-top: 0;
margin-bottom: 0;
display: block;
}
.greeting_card_form .control-group .controls {
margin-left: 13.5em;
}
.greeting_card_form input[type="text"],
.greeting_card_form textarea,
.greeting_card_form select {
line-height: 2.1em;
width: 220px;
background-color: #FFF;
border: 1px solid #d7dadb;
border-radius: 0.3em;
}
.greeting_card_form input[type="text"],
.greeting_card_form textarea {
height: 2.1em;
}
.greeting_card_form textarea {
width: 97%;
height: 180px;
}
/*button*/
.greeting_card_form .form-actions {
border-top: 1px solid #d7dadb;
/*padding: 1em 0 0 20em;*/
}
.greeting_card_form .form-actions input, .greeting_card_form .form-actions a {
float: right;
}
.greeting_card_form .form-actions [type="reset"] {
float: right;
margin-right: 1em;
}
.greeting_card_form .datetime_selector {
white-space: pre;
}
/*驗證碼*/
.text-error {
color: #b94a48;
font-size: 0.83em;
}

View File

@ -0,0 +1,7 @@
#container-inner-wrapper {
position: relative;
}
#container-img {
position: absolute;
width: 100%;
}

View File

@ -0,0 +1,63 @@
input.color-picker {
width: 2.2em;
height: 2.2em;
padding: 0;
}
.miniColors-trigger {
border: 3px solid #666666;
// margin-left: 0.5em;
}
input[disabled] + a{
cursor: not-allowed;
}
#container-inner-wrapper {
position: relative;
}
#container-img {
position: absolute;
width: 100%;
}
.toolbar-wrapper {
font-size: 1.2em;
}
.toolbar-wrapper > span:not(.select2, .line-height-picker-wrapper) {
font-size: 1.2em;
}
.toolbar-wrapper > span:not(.select2, .line-height-picker-wrapper) input {
width: 1.2em;
height: 1.2em;
vertical-align: text-bottom;
margin-left: 0.5em;
}
.fontsize-picker {
width: 2.5em;
}
.line-height-picker-wrapper img {
height: 2em;
}
.line-height-picker-wrapper input.line-height-picker {
width: 2.5em;
padding-left: 0.5em;
}
.strokeWidth-picker {
width: 3em;
}
.stroke-color {
margin-left: 0.2em;
}
#container-inner-wrapper textarea {
position: absolute;
border: none;
padding: 0px;
margin: 0px;
overflow: hidden;
background: none;
outline: none;
resize: none;
line-height: 1;
font-family: Calibri;
transform-origin: left top;
text-align: left;
color: rgb(51, 51, 51);
transform: translateY(0px);
}

View File

@ -0,0 +1,39 @@
.default_picker > *{
display: none;
}
.default_picker > input{
display: inline-block;
}
select.ui-timepicker-select.ui-state-default.ui-corner-all {
width: auto;
}
.ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
.ui-timepicker-div dl { text-align: left; }
.ui-timepicker-div dl dt { float: left; clear:left; padding: 0 0 0 5px; }
.ui-timepicker-div dl dd { margin: 0 10px 10px 40%; }
.ui-timepicker-div td { font-size: 90%; }
.ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; }
.ui-timepicker-div .ui_tpicker_unit_hide{ display: none; }
.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input { background: none; color: inherit; border: none; outline: none; border-bottom: solid 1px #555; width: 95%; }
.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input:focus { border-bottom-color: #aaa; }
.ui-timepicker-rtl{ direction: rtl; }
.ui-timepicker-rtl dl { text-align: right; padding: 0 5px 0 0; }
.ui-timepicker-rtl dl dt{ float: right; clear: right; }
.ui-timepicker-rtl dl dd { margin: 0 40% 10px 10px; }
/* Shortened version style */
.ui-timepicker-div.ui-timepicker-oneLine { padding-right: 2px; }
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time,
.ui-timepicker-div.ui-timepicker-oneLine dt { display: none; }
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time_label { display: block; padding-top: 2px; }
.ui-timepicker-div.ui-timepicker-oneLine dl { text-align: right; }
.ui-timepicker-div.ui-timepicker-oneLine dl dd,
.ui-timepicker-div.ui-timepicker-oneLine dl dd > div { display:inline-block; margin:0; }
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_minute:before,
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_second:before { content:':'; display:inline-block; }
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_millisec:before,
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_microsec:before { content:'.'; display:inline-block; }
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide,
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide:before{ display: none; }

View File

@ -0,0 +1,74 @@
:root {
--background-color: #fff;
--border-color: #ccc;
--text-color: #555;
--selected-text-color: rgb(56, 241, 164);
--hover-background-color: #eee;
}
.yearpicker-container {
z-index: 2000000000;
position: absolute;
color: var(--text-color);
width: 280px;
border: 1px solid var(--border-color);
border-radius: 3px;
font-size: 1rem;
box-shadow: 1px 1px 8px 0px rgba(0, 0, 0, 0.2);
background-color: var(--background-color);
}
.yearpicker-header {
display: flex;
width: 100%;
height: 2.5rem;
border-bottom: 1px solid var(--border-color);
align-items: center;
justify-content: space-around;
}
.yearpicker-prev,
.yearpicker-next {
cursor: pointer;
font-size: 2rem;
}
.yearpicker-prev:hover,
.yearpicker-next:hover {
color: var(--selected-text-color);
}
.yearpicker-year {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
text-align: center;
padding: 0.5rem;
}
.yearpicker-items {
list-style: none;
padding: 1rem 0.5rem;
flex: 0 0 33.3%;
width: 100%;
}
.yearpicker-items:hover {
background-color: var(--hover-background-color);
color: var(--selected-text-color);
cursor: pointer;
}
.yearpicker-items.selected {
color: var(--selected-text-color);
}
.hide {
display: none;
}
.yearpicker-items.disabled {
pointer-events: none;
color: #bbb;
}

View File

@ -0,0 +1,20 @@
class Admin::GreetingCardAcknowledgementsController < OrbitAdminController
helper Admin::GreetingCardsHelper
def initialize
super
@app_title = 'greeting_card_acknowledgement'
end
def index
@greeting_card_acknowledgements = GreetingCardAcknowledgement.first || GreetingCardAcknowledgement.create
@url = admin_greeting_card_acknowledgement_path(@greeting_card_acknowledgements)
end
def update
@greeting_card_acknowledgements = GreetingCardAcknowledgement.first
@greeting_card_acknowledgements.update_attributes(params.require(:greeting_card_acknowledgement).permit!)
redirect_to admin_greeting_card_acknowledgements_path, notice: t('greeting_card.save_success')
end
end

View File

@ -0,0 +1,45 @@
# encoding: utf-8
class Admin::GreetingCardAdminsController < OrbitAdminController
def initialize
super
@app_title = 'greeting_card'
end
def index
@greeting_card_admin = GreetingCardAdmin.new
@table_fields = [:email]
@greeting_card_admins = GreetingCardAdmin.order_by(sort)
end
def create
@greeting_card_admins = GreetingCardAdmin.new(greeting_card_admin_params)
@greeting_card_admins.save
redirect_to admin_greeting_card_admins_path
end
def edit
@greeting_card_admin = GreetingCardAdmin.find(params[:id])
@table_fields = [:email]
@greeting_card_admins = GreetingCardAdmin.order_by(sort)
@url = admin_greeting_card_admin_path(@greeting_card_admin)
end
def update
@greeting_card_admin = GreetingCardAdmin.find(params[:id])
@greeting_card_admin.update_attributes(greeting_card_admin_params)
redirect_to admin_greeting_card_admins_path
end
def destroy
@greeting_card_admin = GreetingCardAdmin.find(params[:id])
@greeting_card_admin.destroy
redirect_to admin_greeting_card_admins_path
end
def greeting_card_admin_params
params.require(:greeting_card_admin).permit!
end
end

View File

@ -0,0 +1,659 @@
# encoding: utf-8
class Admin::GreetingCardsController < OrbitAdminController
helper Admin::GreetingCardsHelper
include Admin::GreetingCardsHelper
before_action ->(module_app = @app_title) { set_variables module_app }
before_action :set_greeting_cardquestion, only: [:edit, :destroy, :update, :print]
before_action :prepare_category_select, only: [:layout_design, :index, :order_fields]
layout :compute_layout
helper_method :greeting_card_thead
def show
@greeting_card_status_histories = @greeting_card_record.greeting_card_status_histories.reverse
end
def compute_layout
if action_name=='print'
false
else
'back_end_with_jquery_first'
end
end
def initialize
super
@app_title = "greeting_card"
end
def layout_design
category_id = (@category_id.present? ? @category_id : nil)
@set = GreetingCardLayoutDesign.where(:category_id=> category_id).first
@set = GreetingCardLayoutDesign.create(:category_id=> category_id) if @set.nil?
@images = GreetingCardCategorySetting.get_images(@category_id)
@url = layout_design_save_admin_greeting_cards_path
end
def layout_design_save
locale = I18n.locale
layout_design_params = params[:greeting_card_layout_design]
category_id = (layout_design_params[:category_id].present? ? layout_design_params[:category_id] : nil)
set = GreetingCardLayoutDesign.where(:category_id=> category_id).first
set = GreetingCardLayoutDesign.create(:category_id=> category_id) if set.nil?
update_params = {save_name: layout_design_params[:save_name]}
if layout_design_params[:img_objs_changed] == '1'
img_objs = layout_design_params[:img_objs].map.with_index do |(k, v), i|
[i.to_s, v]
end.to_h
update_params[:img_objs] = img_objs
end
set.update_attributes(update_params)
redirect_to layout_design_admin_greeting_cards_path(locale: locale, category: category_id)
end
def filter_fields(categories, tags=[])
{
:situation=> GreetingCardTicketStatus.all.map{|s| {:title=> s.title, :id=>s.key}}
}
end
# 抓取網址的狀態參數
def filter2(type)
case type
when "situation"
params[:filters][:situation].blank? ? [] : params[:filters][:situation] rescue []
when "identity"
params[:filters][:identity].blank? ? [] : params[:filters][:identity] rescue []
end
end
def setting_save
locale = I18n.locale
greeting_card_setting = GreetingCardSetting.first
p1 = greeting_card_setting_params(greeting_card_setting,'greeting_card_setting')
greeting_card_setting.update_attributes(p1)
redirect_to "/#{locale}/admin/greeting_cards/setting"
end
def switch_to_default_setting
if GreetingCardCategorySetting.where(:id=>params[:id]).update_all(:use_default=>params[:use_default] == "true").documents[0]["nModified"] != 0
render :json => {success: true}
else
render :json => {success: false}
end
end
def category_setting_save
# render :html => params and return
locale = I18n.locale
host_url = Site.first.root_url rescue "http://"
if host_url == "http://"
host_url = request.protocol + request.host_with_port
end
update_user_id = current_user.id
greeting_card_setting = GreetingCardCategorySetting.where(category_id: params['category_id']).first
greeting_card_setting = GreetingCardCategorySetting.create(category_id: params['category_id']) if greeting_card_setting.nil?
p1 = greeting_card_setting_params(greeting_card_setting,'greeting_card_category_setting', greeting_card_setting.agree_customs.map{|k| "default@#{k}"})
p1[:update_user_id] = update_user_id
p1[:host_url] = host_url
greeting_card_setting.update_attributes(p1)
redirect_to "/#{locale}/admin/greeting_cards/category_setting"
end
def setting
@default_greeting_card_setting = GreetingCardSetting.first
@url = setting_save_admin_greeting_cards_path
end
def backend_table_setting
category_id = params[:category_id].present? ? params[:category_id] : nil
@greeting_card_list_setting = GreetingCardListSetting.where(:category_id=>category_id).first || GreetingCardListSetting.create(:category_id=>category_id)
@url = greeting_card_list_setting_save_admin_greeting_cards_path
end
def greeting_card_list_setting_save
@greeting_card_list_setting = GreetingCardListSetting.find(params[:id])
greeting_card_list_setting_params = params.require('greeting_card_list_setting').permit!
@greeting_card_list_setting.update_attributes(greeting_card_list_setting_params)
redirect_to admin_greeting_cards_path(:locale=>locale)
end
def get_new_setting_index
greeting_card_setting_index = GreetingCardSettingIndex.first
greeting_card_setting_index = GreetingCardSettingIndex.create() if greeting_card_setting_index.nil?
greeting_card_setting_index.key = greeting_card_setting_index.key + 1
greeting_card_setting_index.save
render :json => {key: greeting_card_setting_index.key.to_i}
end
def get_new_category_setting_index
greeting_card_setting_index = GreetingCardCategorySettingIndex.where(category_id: params['category_id']).first
greeting_card_setting_index = GreetingCardCategorySettingIndex.create(category_id: params['category_id']) if greeting_card_setting_index.nil?
greeting_card_setting_index.key = greeting_card_setting_index.key + 1
greeting_card_setting_index.save
render :json => {key: greeting_card_setting_index.key.to_i}
end
def apply_default_custom_fields
greeting_card_setting = GreetingCardCategorySetting.where(:category_id=>params[:category]).first
if greeting_card_setting
if params[:apply_all].to_s == 'true'
apply_fields = greeting_card_setting.need_check_customs
if params[:include_reject].to_s == 'true'
apply_fields += greeting_card_setting.reject_customs
apply_fields = apply_fields.sort_by{|k| k.to_i}
end
else
apply_fields = params[:apply_fields].to_a
end
is_agree = params[:agree].to_s == 'true'
if is_agree
greeting_card_setting.agree_customs_func(apply_fields)
custom_fields = GreetingCardSetting.first.custom_fields
set_input_name_for_greeting_card('greeting_card_category_setting[custom_fields]')
view_context.set_input_name_for_greeting_card('greeting_card_category_setting[custom_fields]') #prevent not setting variables
html = apply_fields.map do |k|
view_context.custom_field_block_for_greeting_card("default@#{k}", custom_fields[k])
end.join("\n")
else
greeting_card_setting.delete_customs_func(apply_fields, true)
html = ""
end
render :json => {:success=>true, :html=>html}
else
render :json => {:success=>false}
end
end
def index
@greeting_card_setting = GreetingCardSetting.first
category_id = @category_id.present? ? @category_id : nil
@greeting_card_list_setting = GreetingCardListSetting.where(:category_id=>category_id).first || GreetingCardListSetting.create(:category_id=>category_id)
# @tags = @module_app.tags
@categories = @module_app.categories.enabled.sort_by{|category| (((@module_app.asc rescue true) ? category.sort_number.to_i : -category.sort_number.to_i) rescue category.id)}
@filter_fields = filter_fields(@categories)
# 列表欄位
@table_fields = @greeting_card_list_setting.default_fields.select{|f| @greeting_card_setting.default_setting[f].nil? || @greeting_card_setting.default_setting[f] }
if !category_id.nil?
greeting_card_setting = GreetingCardCategorySetting.where(:category_id=>@category_id, :use_default.ne=>true).first
if greeting_card_setting.nil?
greeting_card_setting = GreetingCardSetting.first
tmp = greeting_card_setting.custom_fields.map{|k,v| ["default@#{k}", v]}.to_h
else
tmp = greeting_card_setting.custom_fields.map{|k,v| ["custom@#{category_id}@#{k}", v]}.to_h
end
list_setting_custom_fields = @greeting_card_list_setting.custom_fields
else
tmp = []
default_setting = GreetingCardSetting.first
if default_setting
tmp += default_setting.custom_fields.map{|k,v| ["default@#{k}", v]}
end
GreetingCardCategorySetting.all.each do |greeting_card_setting|
tmp += greeting_card_setting.custom_fields.map{|k,v| ["custom@#{greeting_card_setting.id}@#{k}", v]}
end
tmp = tmp.to_h
list_setting_custom_fields = (tmp.keys & @greeting_card_list_setting.custom_fields)
end
@table_ext_fields = list_setting_custom_fields.map{|k| [k,tmp[k]]}.select{|k,v| v}
# 列表排序
# debugger
if filter2("situation").blank? and filter2("identity").blank?
@greeting_cards = GreetingCardRecord.order_by(sort)
.with_categories(filters("category"))
elsif filter2("situation").blank?
@greeting_cards = GreetingCardRecord.order_by(sort)
.with_categories(filters("category"))
.any_in(:identity => filter2("identity"))
elsif filter2("identity").blank?
@greeting_cards = GreetingCardRecord.order_by(sort)
.with_categories(filters("category"))
.any_in(:situation => filter2("situation"))
else
@greeting_cards = GreetingCardRecord.order_by(sort)
.with_categories(filters("category"))
.any_in(:identity => filter2("identity"))
.any_in(:situation => filter2("situation"))
end
@greeting_cards = @greeting_cards.where(:category_id=>category_id) if category_id
@greeting_cards = @greeting_cards.where(:is_hidden.ne=> true)
# 分頁
@greeting_cards = search_data(@greeting_cards,[:title]).page(params[:page]).per(10)
if request.xhr?
render :partial => "index"
end
end
def search_tag(tag)
Tag.find(tag).name_translations{}
end
def category_setting
@default_greeting_card_setting = GreetingCardSetting.first
@categories = current_user.approved_categories_for_module(@module_app).sort_by{|category| (((@module_app.asc rescue true) ? category.sort_number.to_i : -category.sort_number.to_i) rescue category.id)}
@category_ids = @categories.collect(&:id)
@category_titles = @categories.collect{|v| v.title}
@category_added = GreetingCardCategorySetting.all.asc(:created_at).map{|a| [a.category_id, a]}.to_h
@category_added_ids = @category_added.map{|k,v| k}
@url = category_setting_save_admin_greeting_cards_path
end
def get_category_setting_partial
greeting_card_setting = GreetingCardCategorySetting.where(:category_id=>params['id']).first
@default_greeting_card_setting = GreetingCardSetting.first
if greeting_card_setting.nil?
greeting_card_setting = @default_greeting_card_setting
is_default = true
else
is_default = false
end
render :partial=> "category_setting_partial", locals: {f: nil, greeting_card_setting: greeting_card_setting, is_default: is_default}
end
def get_category_setting_field
@default_greeting_card_setting = GreetingCardSetting.first
greeting_card_setting = GreetingCardCategorySetting.find(params['id'])
render partial: 'category_setting_field',locals: {greeting_card_setting: greeting_card_setting, is_default: false}
end
def category_setting_delete
greeting_card_setting = GreetingCardCategorySetting.find(params['id'])
greeting_card_setting.destroy
locale = I18n.locale
redirect_to "/#{locale}/admin/greeting_cards/category_setting"
end
def process_format_text(text,custom_fields)
customs = text.scan(/<tr(?:(?!<tr).)+\{custom\}(?:(?!<tr).)+<\/tr>/m).uniq
if customs.length != 0
custom_exist_nums = []
custom_exists = text.scan(/{custom\d+}/)
custom_exists.each do |custom_exist|
k = custom_exist[6...-1].to_i - 1
custom_exist_nums << k
end
customs.each do |custom|
tmp = custom_fields.keys.collect.with_index do |k,i|
if custom_exist_nums.exclude?(i)
tp = custom.gsub(/{custom}/,"{custom#{i+1}}")
tp = tp.gsub(/{custom_title}/,"{custom#{i+1}_title}")
tp
else
nil
end
end.compact.join
text = text.gsub(custom,tmp)
end
end
format_texts = text.scan(/{\w+\|*\w+}/).uniq
format_texts.each do |format_text|
if format_text[-7...-1] == '_title'
case format_text[1...-7]
when /custom\d+/
i = format_text.scan(/\d+/)[0].to_i - 1
k = custom_fields.keys[i] rescue nil
if !k.blank?
text_tp = custom_fields[k]['field'][I18n.locale] rescue ''
text = text.gsub(format_text,text_tp)
end
when 'title'
text = text.gsub(format_text,I18n.t('title'))
when 'greeting_card_time'
text = text.gsub(format_text,I18n.t('greeting_card.greeting_card_time'))
when 'category'
text = text.gsub(format_text,I18n.t('mongoid.attributes.greeting_card_record.greeting_card_category_id'))
when 'name','sex','mail','phone','appointment','agree_show'
text = text.gsub(format_text,I18n.t("mongoid.attributes.greeting_card_record.#{format_text[1...-7]}"))
end
else
case format_text[1...-1]
when 'greeting_card_time'
text = text.gsub(format_text,@greeting_card_record.created_at.strftime('%Y/%m/%d %H:%M'))
when 'title','name','sender_mail','recipients','appointment'
text = text.gsub(format_text,@greeting_card_record.send(format_text[1...-1]).to_s)
when 'category'
cat = Category.find(@greeting_card_record.category_id).title rescue ''
text = text.gsub(format_text,cat)
when 'name|mask'
name_tp = @greeting_card_record.name.to_s
if name_tp.length>1
if name_tp.strip.match(/^[a-zA-Z]/) # english
name_tp = name_tp.gsub(/\b\S{2}(\S{1,2})\b/,'**\1').gsub(/\b\S{2}(\S{2,})\S\b/,'**\1*')
else
name_tp = name_tp[0] + '*'*(name_tp.length-1)
end
end
text = text.gsub(format_text,name_tp)
when 'sex'
sex = @greeting_card_record.sex
if ['male','female'].include? sex.to_s
sex = I18n.t("mongoid.attributes.greeting_card_record.#{sex}")
else
sex = ''
end
text = text.gsub(format_text,sex)
when 'agree_show'
if @greeting_card_record.agree_show
text = text.gsub(format_text,I18n.t('greeting_card.yes'))
else
text = text.gsub(format_text,I18n.t('greeting_card.no'))
end
when /custom\d+\|format/
i = format_text.scan(/\d+/)[0].to_i - 1
k = custom_fields.keys[i] rescue nil
if !k.blank?
v = custom_fields[k] rescue {}
text_tp = Admin::GreetingCardsHelper.show_on_front(k,v,@greeting_card_record,true,true)
text = text.gsub(format_text,text_tp.to_s)
end
when /custom\d+/
i = format_text.scan(/\d+/)[0].to_i - 1
k = custom_fields.keys[i] rescue nil
if !k.blank?
v = custom_fields[k] rescue {}
text_tp = Admin::GreetingCardsHelper.show_on_front(k,v,@greeting_card_record,true)
text = text.gsub(format_text,text_tp.to_s)
end
end
end
end
text
end
def print
@layout_design = GreetingCardLayoutDesign.where(category_id: @greeting_card_record.category_id.to_s).first
@layout_design = GreetingCardLayoutDesign.first if @layout_design.nil?
@save_name = @layout_design.save_name rescue ''
@print_text = @layout_design.print_format rescue ''
@print_text = "<style>img{width: 100%;}</style>"+ @print_text
greeting_card_setting = GreetingCardCategorySetting.where(category_id: @greeting_card_record.category_id.to_s, :use_default.ne=>true).first
greeting_card_setting = GreetingCardSetting.first if greeting_card_setting.nil?
custom_fields = greeting_card_setting.custom_fields
@print_text = process_format_text(@print_text,custom_fields)
@save_name = process_format_text(@save_name,custom_fields)
end
def edit
@greeting_card_setting = GreetingCardCategorySetting.where(category_id: @greeting_card_record.category_id.to_s, :use_default.ne=>true).first
@greeting_card_setting = GreetingCardSetting.first if @greeting_card_setting.nil?
@url = admin_greeting_card_path(@greeting_card_record)
end
def batch_modify_status
GreetingCardRecord.where(:id.in=>params[:ids]).update_all(:situation=>params[:status_key])
render :body => nil, :status => 204
end
def delete
GreetingCardRecord.where(:id.in=>params[:ids]).destroy
render :body => nil, :status => 204
end
def destroy
locale = I18n.locale
@greeting_card_record.destroy
redirect_to admin_greeting_cards_path(:locale=>locale)
end
def update
locale = I18n.locale
temp_params = params.require(:greeting_card_record).permit!
all_to_save = []
greeting_card_setting = GreetingCardCategorySetting.where(category_id: params['greeting_card_record']['category_id']).first
if greeting_card_setting.nil?
greeting_card_setting = GreetingCardSetting.first
end
if temp_params['custom_values'].nil?
temp_params['custom_values'] = {}
end
greeting_card_setting.custom_fields.select{|k,v| v['type']=='file' || v['type']=='image'}.each do |k,v|
file = temp_params['custom_values'][k] rescue nil
if !file.blank?
if v['type']=='image'
all_to_save += [[k,GreetingCardImage.new(file: file,greeting_card_record_id: @greeting_card_record.id)]]
else
all_to_save += [[k,GreetingCardFile.new(file: file,greeting_card_record_id: @greeting_card_record.id)]]
end
else
temp_params['custom_values'][k] = @greeting_card_record.custom_values[k] rescue nil
end
end
temp_params['custom_values'] = @greeting_card_record.custom_values.merge(temp_params['custom_values'])
flag = @greeting_card_record.save
if flag
all_to_save.each do |to_save|
flag = flag && to_save[1].save
temp_params['custom_values'][to_save[0]] = [temp_params['custom_values'][to_save[0]].original_filename ,to_save[1].file.url]
end
end
temp_params = temp_params.merge({reviewer: current_user.member_profile, review_time: DateTime.now, user: current_user})
@greeting_card_record.update_attributes(temp_params)
if @greeting_card_record.send_email?
build_email(@greeting_card_record)
end
redirect_to admin_greeting_cards_path(:locale=>locale), notice: t('greeting_card.reply_success')
end
def build_email(email_er)
email = Email.new
email.save
email_er.email_id = email.id
email_er.save
@group_mail = email_er.mail
@mail_sentdate = DateTime.now
site = Site.first
mail_from = site.title_translations[site['default_locale']]
new_history = email_er.new_history
host_url = Site.first.root_url rescue "http://"
if host_url == "http://"
host_url = request.protocol + request.host_with_port
end
email_er.email.update_attributes(
:mail_lang=> site['default_locale'],
:create_user=>current_user,
:mail_sentdate=>@mail_sentdate,
:module_app=>@module_app,
:mail_to=>@group_mail,
:mail_subject=>mail_from+" #{t('greeting_card.reply')}",
:template=>'admin/greeting_cards/email',
:template_data=>{
"host_url" => host_url,
"reply" => email_er.reply,
"attachment" => (new_history ? new_history.file.url : nil)
}
)
end
def export
end
def do_export
def process_trans(trans)
trans.collect{|k,v| v if !v.blank?}.compact.uniq.join('/')
end
def get_fields_with_key(s)
fields_with_key = {}
fields_with_key['default_values'] = s.default_setting.collect{|k,v| [k, process_trans(s.field_name_translations(k))] if v && !['greeting_card_category_id','recaptcha'].include?(k)}.compact
fields_with_key['default_values'] = [['greeting_card_category_id', process_trans(s.field_name_translations('greeting_card_category_id'))]] + [['situation', process_trans(I18n.available_locales.map{|v| [v.to_s, I18n.with_locale(v){I18n.t('greeting_card.situation')}]}.to_h)]] + fields_with_key['default_values']
fields_with_key['default_values'] = fields_with_key['default_values'].to_h
fields_with_key['custom_values'] = s.custom_fields.collect{|k, field_setting| [k, process_trans(field_setting['field'])]}.to_h
fields_with_key
end
Rails.application.config.mongoid.use_activesupport_time_zone = true
date_start = "#{params[:export]['start(1i)']}-#{params[:export]['start(2i)']}-#{params[:export]['start(3i)']}"
date_end = "#{params[:export]['end(1i)']}-#{params[:export]['end(2i)']}-#{params[:export]['end(3i)']}"
greeting_card_records = GreetingCardRecord.where(:created_at.gte => date_start.to_datetime, :created_at.lte => date_end.to_datetime)
categories = Category.where(:id.in => greeting_card_records.collect(&:category_id).uniq).to_a
greeting_card_default_setting = GreetingCardSetting.first()
greeting_card_settings = GreetingCardCategorySetting.where(:category_id.in => categories.collect(&:id)).collect{|s| [BSON::ObjectId(s.category_id), s]}.to_h
greeting_card_category_settings = {}
fields_with_key_group = {}
categories.each do |c|
s = greeting_card_settings.fetch(c.id, greeting_card_default_setting)
greeting_card_category_settings[c.id] = s
fields_with_key_group[c.id] = get_fields_with_key(s)
end
greeting_card_category_settings[nil] = greeting_card_default_setting
fields_with_key_group[nil] = get_fields_with_key(greeting_card_default_setting)
situations = GreetingCardTicketStatus.all.collect{|situation| [situation.key, situation.get_title_translations]}.to_h
render xlsx: 'do_export.xlsx',
handlers: ['axlsx'],
filename: "Questions-#{date_start}-#{date_end}.xlsx",
locals: {
:greeting_card_category_settings => greeting_card_category_settings,
:fields_with_key_group => fields_with_key_group,
:categories => categories.collect{|c| [c.id, c]}.to_h,
:greeting_card_records => greeting_card_records,
:situations => situations
}
end
def set_greeting_cardquestion
@greeting_card_record = GreetingCardRecord.find(params[:id])
end
def order_fields
greeting_card_setting = GreetingCardCategorySetting.where(:category_id=>@category_id).first
@disp_fields_infos = GreetingCardSetting.get_disp_fields_infos(false, greeting_card_setting, (greeting_card_setting ? true : false))
end
def prepare_category_select
@cats_relations = get_categories_info_for_greeting_card
@category_id = (params[:category] || @cats_relations[0][0] rescue nil)
end
def update_order_fields
greeting_card_setting = GreetingCardCategorySetting.where(:category_id=>params[:category]).first
use_default = greeting_card_setting && greeting_card_setting.use_default
sort_number = params[:sort_number].map{|k,v| [k,v.to_i]}.to_h
if params[:category].present?
if greeting_card_setting.nil?
use_default = true
default_setting = GreetingCardSetting.first
greeting_card_setting = GreetingCardCategorySetting.create(category_id: params[:category])
p1 = default_setting.get_attrs
p1['need_check_customs'] = []
p1['agree_customs'] = p1['custom_fields'].keys rescue []
p1['reject_customs'] = []
p1['custom_fields'] = p1['custom_fields'].map{|k,v| ["default@#{k}", v]}.to_h rescue {}
greeting_card_setting.update_attributes(p1)
greeting_card_setting.update(:use_default => use_default)
greeting_card_setting_index = GreetingCardCategorySettingIndex.where(category_id: params[:category]).first
greeting_card_setting_index = GreetingCardCategorySettingIndex.create(category_id: params[:category]) if greeting_card_setting_index.nil?
greeting_card_setting_index.key = default_setting.custom_fields.keys[-1].to_i rescue 0
greeting_card_setting_index.save
end
if use_default
greeting_card_setting.update(:default_sort_number=> sort_number)
else
sort_number_was = GreetingCardSetting.get_sort_number_only(false, greeting_card_setting, true).merge(greeting_card_setting.sort_number.to_h)
greeting_card_setting.update(:sort_number=> sort_number)
default_greeting_card_setting = GreetingCardSetting.first
last_fields = ["recaptcha", "usage_rule", "agree_show", "agree_usage"]
default_sort_number = GreetingCardSetting.get_sort_number_only(false, default_greeting_card_setting, true).select{|k,v| k.exclude?('@') && last_fields.exclude?(k)}.map.with_index{|(k,v), i| [k, i]}.to_h.merge(default_greeting_card_setting.sort_number)
greeting_card_setting_id = greeting_card_setting.id.to_s
sort_number_changed = (sort_number.map.with_index{|(k,v), i| [k,i]} - sort_number_was.map.with_index{|(k,v), i| [k,i]}).to_h
part_sort_number = sort_number_changed.select{|k,v| k.start_with?('default@')}.map{|k,v| tmp=k.split('@')[1..-1].join('@');[(tmp.start_with?('default@') ? tmp : "custom@#{greeting_card_setting_id}@#{tmp}"), v]}.to_h
intersect_keys = part_sort_number.keys & default_sort_number.keys
non_intersect_keys = (part_sort_number.keys - default_sort_number.keys).select{|k| k.exclude?('default@')}
if intersect_keys.count != 0
org_order = intersect_keys.map{|k| [k, default_sort_number[k]]}.sort_by{|k,v| v}.to_h
default_sort_number = default_sort_number.merge(org_order.sort_by{|k, v| part_sort_number[k]}.map{|k,v| k}.zip(org_order.values).to_h)
end
preserve_count = GreetingCardSetting::All_default_fields.count
if non_intersect_keys.count != 0
max_sort_number = default_sort_number.map{|k,v| v.to_i}.max.to_i
max_sort_number += 1
max_sort_number += preserve_count
part_sort_number = non_intersect_keys.map.with_index{|(k,v), i| [k, max_sort_number + i]}
default_sort_number = default_sort_number.merge(part_sort_number.to_h)
end
default_greeting_card_setting.update(:sort_number=>default_sort_number)
end
else
greeting_card_setting = GreetingCardSetting.first
original_sort_info = GreetingCardSetting.get_sort_number_only(false, greeting_card_setting, true)
sort_number_was = original_sort_info.merge(greeting_card_setting.sort_number.to_h)
sort_number_changed = (sort_number.map.with_index{|(k,v), i| [k,i]} - sort_number_was.map.with_index{|(k,v), i| [k,i]}).to_h
greeting_card_setting.update(:sort_number=>sort_number)
unless use_default
default_customs_sort_number = sort_number_changed.select{|k, v| k.start_with?('default@')}.map{|k,v| ["default@#{k}",v]}
custom_sort_number = sort_number.select{|k, v| k.start_with?('custom@')}
all_custom_sort_numbers = custom_sort_number.group_by{|k, v| k.split('@')[1]}
preserve_count = GreetingCardSetting::All_default_fields.count
last_fields = ["recaptcha", "usage_rule", "agree_show", "agree_usage"]
all_custom_sort_numbers.each do |greeting_card_category_setting_id, part_sort_number|
greeting_card_setting = GreetingCardCategorySetting.find(greeting_card_category_setting_id) rescue nil
if greeting_card_setting
sort_number = GreetingCardSetting.get_sort_number_only(false, greeting_card_setting, true).select{|k,v| last_fields.exclude?(k)}.map.with_index{|(k,v), i| [k, i]}.to_h.merge(greeting_card_setting.sort_number)
tmp_default_customs_sort_number = default_customs_sort_number.select{|k, v| greeting_card_setting.agree_customs.include?(k.split('@')[-1])}
part_sort_number = (part_sort_number.map{|k,v| ["default@#{k.split('@')[-1]}", v]} + tmp_default_customs_sort_number).to_h
intersect_keys = part_sort_number.keys & sort_number.keys
non_intersect_keys = part_sort_number.keys - sort_number.keys
if intersect_keys.count != 0
org_order = intersect_keys.map{|k| [k, sort_number[k]]}.sort_by{|k,v| v}.to_h
sort_number = sort_number.merge(org_order.sort_by{|k, v| part_sort_number[k]}.map{|k,v| k}.zip(org_order.values).to_h)
end
if non_intersect_keys.count != 0
max_sort_number = sort_number.map{|k,v| v.to_i}.max.to_i
max_sort_number += 1
max_sort_number += preserve_count
part_sort_number = non_intersect_keys.map.with_index{|(k,v), i| [k, max_sort_number + i]}
sort_number = sort_number.merge(part_sort_number.to_h)
end
greeting_card_setting.update(:sort_number=>sort_number)
end
end
end
end
render :json => {:success=>true}
end
def ticket_status
@ticket_statuses = GreetingCardTicketStatus.all
if request.xhr?
render 'ticket_status', :layout => false
end
end
def get_ticket_status
ticket_status = GreetingCardTicketStatus.where(:id=>params[:id]).first
render :json => {
"id"=>params[:id],
"title_translations"=> (ticket_status ? ticket_status.get_title_translations : {})
}
end
def update_ticket_status
if params[:id].blank?
ticket_status = GreetingCardTicketStatus.new
else
ticket_status = GreetingCardTicketStatus.where(:id=>params[:id]).first
end
ticket_status.update_attributes(params.require(:greeting_card_ticket_status).permit!)
render :json => {:success=>true}
end
def delete_ticket_status
ticket_status = GreetingCardTicketStatus.where(:id=>params[:id]).first
unless ticket_status.is_default
ticket_status.destroy
end
render :json => {:success=>true}
end
private
def greeting_card_setting_params(greeting_card_setting,collection_name, except_customs=[])
param = params.require(collection_name).except("id").permit!
if param['default_setting']
param_clone = param.clone
param_clone['default_setting'].each { |k, v| param_clone['default_setting'][k] = (v == 'true'? true : false) if param_clone['default_setting'][k].class==String}
param_clone['default_setting_required'].each { |k, v| param_clone['default_setting_required'][k] = (v == 'true'? true : false) if param_clone['default_setting_required'][k].class==String}
param_clone.delete('custom_fields')
param_clone.delete('email_regex') unless collection_name == 'greeting_card_setting'
greeting_card_setting.custom_fields_will_change!
custom_fields = params['not_clone_attrs'] ? {} : greeting_card_setting['custom_fields'].clone
params_custom_fields = (params.require(collection_name).require('custom_fields') rescue {})
params_custom_fields.each do |k,v|
next if except_customs.include?(k.to_s)
custom_fields[k] = v
end
field_to_delete = params['delete_field'].to_s.split(',').select{|v| !v.empty?}
field_to_delete.each do |k|
if custom_fields.keys.include? k
custom_fields[k]['delete'] = true
end
end
param_clone.merge({"custom_fields"=> custom_fields})
else
param
end
end
def greeting_card_thead(field, trans,center=false)
sort = field.to_s.include?('.') ? field.to_s.split('.')[1] : field.to_s
active = params[:sort].eql? sort
order = active ? (["asc", "desc"]-[params[:order]]).first : "asc"
arrow = (order.eql? "desc") ? "<b class='icons-arrow-up-3'></b>" : "<b class='icons-arrow-down-4'></b>"
klass = field.eql?(:title) ? "span5" : "span2"
th_data = "<a href='?sort=#{sort}&order=#{order}'>#{trans} #{active ? arrow : ""}</a>"
"<th class='#{klass} #{active ? "active" : ""}' style='#{center ? "text-align:center" : ""}'>#{th_data}</th>".html_safe
end
end

View File

@ -0,0 +1,703 @@
class GreetingCardsController < ApplicationController
helper Admin::GreetingCardsHelper
include Admin::GreetingCardsHelper
include ActionView::Helpers::FormHelper
include ActionView::Helpers::FormOptionsHelper
helper ActionView::Helpers::UrlHelper
include ActionController::RequestForgeryProtection
include RuCaptcha::ViewHelpers
FrontendMethods = ["thank", "sorry", "see_email"]
def widget
subpart = OrbitHelper.get_current_widget
case subpart.widget_type
when /.*_form/
read_more_page = Page.where(id: subpart.read_more_page_id).first || Page.where(:module => 'greeting_card').first
referer_url = read_more_page ? "/#{I18n.locale}#{read_more_page.url}" : "/#{I18n.locale}/greeting_cards"
module_app = ModuleApp.where(:key => "greeting_card").first
if OrbitHelper.widget_categories.include?('all')
categories = module_app.categories.enabled
else
categories = Category.where(:id.in=>OrbitHelper.widget_categories).enabled
end
unless Category.respond_to?(:sorted)
if (module_app.asc rescue true)
categories = categories.sort_by{|category| (category.sort_number.to_i rescue category.id)}
else
categories = categories.sort_by{|category| (-category.sort_number.to_i rescue category.id)}
end
end
tags = module_app.tags
greeting_card_record = GreetingCardRecord.new
locale = I18n.locale
category_ids = categories.collect{|v| v.id.to_s}
default_setting = GreetingCardSetting.first
default_setting = GreetingCardSetting.create() if default_setting.nil?
greeting_card_settings_map = GreetingCardCategorySetting.where(:category_id.in=> category_ids).map{|s| [s.category_id.to_s, s]}.to_h
greeting_card_settings = category_ids.map do |category_id|
if greeting_card_settings_map.has_key?(category_id)
greeting_card_settings_map[category_id]
else
default_setting
end
end
tmp_
first_category_id = category_ids.first
greeting_card_setting = greeting_card_settings[0]
@default_greeting_card_setting = default_setting
all_fields = cal_form_from_setting(greeting_card_setting,categories)
request = OrbitHelper.request
csrf_value = OrbitHelper.request.session[:_csrf_token] || SecureRandom.base64(32)
token_tag = hidden_field_tag('authenticity_token',csrf_value)
switch_form = cal_switch_form(greeting_card_settings,categories,token_tag,referer_url, OrbitHelper.params[:id])
email_regex = @default_greeting_card_setting.get_email_regex(true)
{
'fields' => all_fields,
'extras'=>{
'switch_form' => switch_form,
'email_regex' => email_regex
}
}
else
data_count = OrbitHelper.widget_data_count.to_i
if data_count != 0
greeting_card_records = GreetingCardRecord.where(situation: 'is_published').page(1).per(data_count)
else
greeting_card_records = GreetingCardRecord.where(situation: 'is_published')
end
greeting_card_index_page = OrbitHelper.widget_more_url rescue nil
greeting_card_records = greeting_card_records.collect do |v|
url = ((greeting_card_index_page+"?item=#{v.id}") rescue "javascript:alert('#{t('greeting_card.no_index_page')}')")
{'td'=> [
{'content' =>v.category.title},
{'content' => link_to(v.title,"#{url}",title: v.title)}
]
}
end
{
'greeting_card_records' => greeting_card_records,
'th' => [{'td'=>t('categories')},{'td'=>t('title')}],
'extras' => {'more_title'=>I18n.t('greeting_card.more_title'),
'more_href'=>greeting_card_index_page}
}
end
end
def get_layout_type
@params = OrbitHelper.params
page = Page.where(url:@params['url']).first
@layout_type = 'index'
if page.methods.include? 'select_option_items'.to_sym
ModuleApp.all.select{|tmp| tmp.key.to_s=='greeting_card'}.each do |modile_app|
@show_option_items = modile_app.show_option_items rescue nil
end
page.select_option_items.each do |select_option_item|
if !(@show_option_items.nil?) && select_option_item.field_name == @show_option_items.keys.first.to_s
value = YAML.load(select_option_item.value)
I18n.with_locale(:en) do
if value[locale] == t('greeting_card.widget.index')
@layout_type = 'index'
elsif value[locale] == t('greeting_card.is_published')
@layout_type = 'published_index'
end
end
end
end
end
end
def initialize
super
@app_title = 'greeting_card'
self.request = OrbitHelper.request
end
def show
greeting_card_record = GreetingCardRecord.where(id: @params['item']).first
greeting_card_setting = GreetingCardCategorySetting.enabled.where(category_id: greeting_card_record.category_id.to_s).first
greeting_card_setting = GreetingCardSetting.first if greeting_card_setting.nil?
{'greeting_card_record' => greeting_card_record,'layout_type'=>'show','greeting_card_setting'=>greeting_card_setting}
end
def index
@params = OrbitHelper.params
referer_url = OrbitHelper.request.path
if @params['item'].to_s.empty?
get_layout_type
else
@layout_type = 'show'
end
if @layout_type == 'index'
module_app = ModuleApp.where(:key => "greeting_card").first
if OrbitHelper.page_categories.include? 'all'
categories = module_app.categories.enabled
else
categories = Category.where(:id.in=>OrbitHelper.page_categories).enabled
end
unless Category.respond_to?(:sorted)
if (module_app.asc rescue true)
categories = categories.sort_by{|category| (category.sort_number.to_i rescue category.id)}
else
categories = categories.sort_by{|category| (-category.sort_number.to_i rescue category.id)}
end
end
category_ids = categories.collect{|v| v.id.to_s}
default_setting = GreetingCardSetting.first
default_setting = GreetingCardSetting.create() if default_setting.nil?
greeting_card_settings_map = GreetingCardCategorySetting.where(:category_id.in=> category_ids).map{|s| [s.category_id.to_s, s]}.to_h
greeting_card_settings = category_ids.map do |category_id|
if greeting_card_settings_map.has_key?(category_id)
greeting_card_settings_map[category_id]
else
default_setting
end
end
first_category_id = category_ids.first
greeting_card_setting = greeting_card_settings[0]
@default_greeting_card_setting = default_setting
csrf_value = OrbitHelper.request.session[:_csrf_token] || SecureRandom.base64(32)
token_tag = hidden_field_tag('authenticity_token',csrf_value)
switch_form = cal_switch_form(greeting_card_settings,categories,token_tag,referer_url, @params[:id])
tags = module_app.tags
greeting_card_record = GreetingCardRecord.new(id: nil)
email_regex = @default_greeting_card_setting.get_email_regex(true)
{
'layout_type' => 'index',
'greeting_card_record' => greeting_card_record,
'categories' => categories,
'tags' => tags,
'module_app' => module_app,
'switch_form' => switch_form,
'greeting_card_setting' => greeting_card_setting,
'default_greeting_card_setting' => @default_greeting_card_setting,
'email_regex' => email_regex
}
elsif @layout_type == 'published_index'
page_number = OrbitHelper.page_number.to_i
page_number = 1 if page_number == 0
page_data_count = OrbitHelper.page_data_count.to_i
if page_data_count != 0
greeting_card_records = GreetingCardRecord.where(situation: 'is_published').page(page_number).per(page_data_count)
else
greeting_card_records = GreetingCardRecord.where(situation: 'is_published')
end
{
'layout_type' => 'published_index',
'greeting_card_records' => greeting_card_records,
'url' => @params['url']
}
else
show
end
end
def create
if !params[:referer_url].blank? && !params[:referer_url].to_s.start_with?("/")
render :file => "#{Rails.root}/app/views/errors/403.html", :layout => false, :status => 403 and return
end
temp_params = create_params
if temp_params[:id].present?
@greeting_card_record = GreetingCardRecord.where(id: temp_params[:id]).first
if @greeting_card_record.nil?
render_404 and return
end
else
@greeting_card_record = GreetingCardRecord.new(:ip=>request.remote_ip)
end
new_record = @greeting_card_record.new_record?
all_to_save = []
greeting_card_setting = GreetingCardCategorySetting.enabled.where(category_id: params['greeting_card_record']['category_id']).first
override_sort_number = nil
if greeting_card_setting && greeting_card_setting.use_default
override_sort_number = greeting_card_setting.default_sort_number
greeting_card_setting = nil
end
if greeting_card_setting.nil?
greeting_card_setting = GreetingCardSetting.first
greeting_card_setting = GreetingCardSetting.create() if greeting_card_setting.nil?
end
@greeting_card_setting = greeting_card_setting
@must_verify_email = greeting_card_setting.must_verify_email && new_record
if @must_verify_email
only_email = true
@greeting_card_record.is_hidden = true
else
only_email = false
check_fields = greeting_card_setting.default_setting.select{|k,v| v}.keys & greeting_card_setting.default_setting_required.select{|k,v| v}.keys - GreetingCardSetting::No_required
unless new_record
@greeting_card_record.is_hidden = false
check_fields.delete('mail')
end
flag = true
check_fields.each do |f|
next if f == 'greeting_card_category_id' || f == 'recaptcha'
if temp_params[f].blank?
puts "field = #{f} is empty"
flag = false
break
end
end
end
custom_values = temp_params[:custom_values]
custom_values = {} if custom_values.nil?
if flag
check_custom_fields = greeting_card_setting.custom_fields.select{|k,v| v["required"] == 'true' }
if check_custom_fields.count != 0
check_custom_fields.each do |k,v|
next if v['type'] == 'instructions'
tmp = custom_values[k]
v_type = v['type']
is_date = false
if v_type == "checkbox"
tmp = tmp.values rescue []
elsif v_type == 'date'
is_date = true
tmp = tmp["datetime"].values[0].values rescue []
end
if tmp.present?
if is_date && v["range_flag"] == 'true'
if (tmp.class != Array) || (tmp.select{|v| v.blank?}.count != 0)
flag = false
break
end
end
else
flag = false
break
end
end
end
end
if !flag && !only_email
redirect_to "#{params[:referer_url]}?method=sorry" and return
end
email_regex = greeting_card_setting.get_email_regex
unless only_email
greeting_card_setting.custom_fields.select{|k,v| v['type']=='file' || v['type']=='image'}.each do |k,v|
file = custom_values[k]
if !file.blank?
if v['type']=='image'
all_to_save += [[k,GreetingCardImage.new(file: file,greeting_card_record_id: @greeting_card_record.id)]]
else
all_to_save += [[k,GreetingCardFile.new(file: file,greeting_card_record_id: @greeting_card_record.id)]]
end
end
end
end
flag = !greeting_card_setting.default_setting['recaptcha'] || gotcha_valid?
if flag && !only_email
all_to_save.each do |to_save|
flag = flag && to_save[1].save
custom_values[to_save[0]] = [custom_values[to_save[0]].original_filename ,to_save[1].file.url]
end
end
if (email_regex ? ::Regexp.new(email_regex).match(temp_params["mail"].to_s) : true) && flag
@disp_fields_infos = GreetingCardSetting.get_disp_fields_infos(true, greeting_card_setting, true, override_sort_number, true)
@usage_rule = greeting_card_setting.usage_rule
if temp_params['mail'].blank?
temp_params = temp_params.merge({
situation: GreetingCardTicketStatus::DefaultKeys[1]
})
end
@greeting_card_record.update_attributes(temp_params)
if @must_verify_email
referer_url = "#{params[:referer_url]}?id=#{@greeting_card_record.id}"
else
referer_url = nil
end
if (greeting_card_setting.validate_enable || @must_verify_email) && GreetingCardSafeEmail.where(:email=> @greeting_card_record.sender_mail).count == 0
build_verification_email(@greeting_card_record, referer_url)
elsif @must_verify_email
redirect_to referer_url and return
else
@greeting_card_record.update(:situation => GreetingCardTicketStatus::DefaultKeys[1])
build_email(@greeting_card_record)
end
if @must_verify_email
redirect_to "#{params[:referer_url]}?method=see_email"
else
redirect_to "#{params[:referer_url]}?method=thank"
end
else
redirect_to "#{params[:referer_url]}?method=sorry"
end
end
def thank
acknowledgement = GreetingCardAcknowledgement.last
{
"acknowledgement" => acknowledgement
}
end
def sorry
{}
end
def see_email
end
def render_404
render :file => "#{Rails.root}/app/views/errors/404", :layout => false, :status => :not_found, :formats => [:html]
end
def verify_email
@greeting_card_record = GreetingCardRecord.where(:id=>params[:id]).first
if @greeting_card_record.nil?
render_404 and return
elsif @greeting_card_record.situation != GreetingCardTicketStatus::DefaultKeys[0]
@already_verify = true
else
@already_verify = false
@greeting_card_record.update(:situation => GreetingCardTicketStatus::DefaultKeys[1])
GreetingCardSafeEmail.create(:email=> @greeting_card_record.sender_mail)
build_email(@greeting_card_record)
end
end
def build_verification_email(email_er, referer_url)
email = Email.new
email.save
email_er.email_id = email.id
email_er.save
group_mail = email_er.sender_mail
manager_emails = email_er.reviewer_emails
mail_sentdate = DateTime.now
site = current_site rescue Site.first
mail_from = site.title_translations[site.default_locale]
host_url = Site.first.root_url rescue "http://"
if host_url == "http://"
host_url = request.protocol + request.host_with_port
end
verify_url = "#{host_url}/#{I18n.locale}/xhr/greeting_cards/verify_email/#{email_er.id}"
verify_link = "<a title=\"#{t('greeting_card.verify_link')}\" href=\"#{verify_url}\" target=\"_blank\">#{verify_url}</a>"
if referer_url
referer_url = host_url + referer_url
referer_link = "<a title=\"#{I18n.t('greeting_card.go_to_form')}\" href=\"#{referer_url}\" target=\"_blank\">#{referer_url}</a>"
else
referer_link = nil
end
mail_subject = mail_from+": #{t('greeting_card.email_verification_notification')}"
email_er.email.update_attributes(
:mail_lang=> site.default_locale,
:create_user=>(current_user rescue nil),
:mail_sentdate=>mail_sentdate,
:module_app=>@module_app,
:mail_to=>group_mail,
:mail_subject=>mail_subject,
:template=>'greeting_cards/email_verification',
:template_data=>{
"validation_email_content" => @greeting_card_setting.validation_email_content,
"verify_link" => verify_link,
"referer_link" => referer_link,
"site_host" => host_url
},
:mail_reply_to => (manager_emails.empty? ? nil : manager_emails)
)
# email_er.email.deliver
end
def build_email(email_er)
site = current_site rescue Site.first
host_url = Site.first.root_url rescue "http://"
if host_url == "http://"
host_url = request.protocol + request.host_with_port
end
locale = site.default_locale
email_er.build_email(site, host_url, current_user, @module_app, locale)
end
def create_params
params.require(:greeting_card_record).permit!
end
private
def cal_card_html(greeting_card_images)
field_name = "greeting_card_record[card]"
greeting_card_images_html = "<div class=\"card_images_wrapper row\">"
greeting_card_images.each do |image|
img_url = image.file.url
next if img_url.blank?
greeting_card_images_html += "<div class=\"col-md-4\"><img src=\"#{img_url}\" title=\"#{image.description}\" /><input name=\"#{field_name}\" type=\"radio\" value=\"#{image.id}\"></div>"
end
greeting_card_images_html += "</div>"
greeting_card_images_html
end
def cal_form_from_setting(greeting_card_setting,categories,show_categories=false,filter_fields=nil)
is_cat_record = (greeting_card_setting.class == GreetingCardCategorySetting)
override_sort_number = nil
greeting_card_images = []
if is_cat_record
category_id = greeting_card_setting.category_id
greeting_card_images = @default_greeting_card_setting.greeting_card_images.to_a + greeting_card_setting.greeting_card_images.to_a
if greeting_card_setting.use_default
override_sort_number = greeting_card_setting.default_sort_number
if override_sort_number.blank?
override_sort_number = nil
elsif @default_fields
all_fields = @default_fields.sort_by{|h| override_sort_number[h['field']].to_i}
all_fields.each do |f1|
if f1['field'] == 'card'
f1['content'] = cal_card_html(greeting_card_images)
end
end
return all_fields
end
greeting_card_setting = @default_greeting_card_setting
is_cat_record = false
elsif greeting_card_setting.default_sort_number.blank?
greeting_card_setting = @default_greeting_card_setting
is_cat_record = false
end
else
category_id = (categories[0].id.to_s rescue '')
greeting_card_images = greeting_card_setting.greeting_card_images.to_a
end
tmp_greeting_card_cat_id = (is_cat_record ? greeting_card_setting.id.to_s : '')
disp_fields_infos = GreetingCardSetting.get_disp_fields_infos(true, greeting_card_setting, true, override_sort_number, true)
if filter_fields
disp_fields_infos = disp_fields_infos.select{|field, info| filter_fields.include?(field)}
end
# tmp = 'mongoid.attributes.greeting_card_record'
all_fields = []
set_input_name_for_greeting_card("greeting_card_record")
has_greeting_card_category_id = false
if greeting_card_setting.must_verify_email && @greeting_card_record.nil?
field = "mail"
field_name = "greeting_card_record[#{field}]"
id = field_name
required = true
placeholder = @default_greeting_card_setting.prompt_word(field)
f1 = {'style_html'=>''}
f1['content'] = text_field_tag(field_name,nil,data: (required ? {"fv-validation" => "required;check_email;", "fv-messages" => "必填欄位;Email不正確;"} : {}),required: required,placeholder: placeholder)
f1['field'] = field
f1['label'] = greeting_card_label(id, @default_greeting_card_setting.field_name("#{field}"),required.to_s)
all_fields << f1
field = "recaptcha"
id = "greeting_card_rucaptcha"
f1 = {'style_html'=>''}
f1['content'] = "#{gotcha_error(:espeak=>true)}#{gotcha(id: id)}"
f1['field'] = field
f1['label'] = greeting_card_label(id, @default_greeting_card_setting.field_name("#{field}"),required.to_s)
all_fields << f1
all_fields << {'field'=>'must_verify_email','style_html'=>'display: block; text-align: center;','label'=>'','content'=> I18n.t('greeting_card.must_verify_email')}
else
disp_fields_infos.each do |field, info|
if field.start_with?("default@")
k = is_cat_record ? field : field[8..-1]
v = greeting_card_setting.custom_fields[k]
if v
field_name = info['trans']
if field_name.present?
id = "#{get_input_name_for_greeting_card}[custom_values][#{k}]"
all_fields << {'field'=>field,'label'=>greeting_card_label(id, field_name, v['required']),'content'=>show_on_front(k,v)}
end
end
elsif field.start_with?("custom@") && is_cat_record
if field.include?(tmp_greeting_card_cat_id)
k = field[8+tmp_greeting_card_cat_id.length..-1]
v = greeting_card_setting.custom_fields[k]
if v
field_name = info['trans']
if field_name.present?
id = "#{get_input_name_for_greeting_card}[custom_values][#{k}]"
all_fields << {'field'=>field,'label'=>greeting_card_label(id, v['field'][I18n.locale],v['required']),'content'=>show_on_front(k,v)}
end
end
end
else
if field == 'greeting_card_category_id'
has_greeting_card_category_id = true
if show_categories || greeting_card_setting.default_setting[field]
if categories.count > 1
id = "greeting_card_record[category_id]"
all_fields << {'field'=>field,'style_html'=>'','label'=>greeting_card_label(id, @default_greeting_card_setting.field_name("greeting_card_category_id"),'true'),'content'=>select_tag('greeting_card_record[category_id]', options_for_select(categories.collect{|t| [ t.title, t.id ]}))}
else
all_fields << {'field'=>field,'style_html'=>'','label'=>greeting_card_label(nil, @default_greeting_card_setting.field_name("greeting_card_category_id"),'true'),'content'=>"<span>#{(categories[0].title rescue '')}</span>"+hidden_field_tag('greeting_card_record[category_id]', (categories[0].id.to_s rescue ''))}
end
else
all_fields << {'field'=>field,'style_html'=>'display: none;','label'=>'','content'=>hidden_field_tag('greeting_card_record[category_id]', (categories[0].id.to_s rescue ''))}
end
else
if greeting_card_setting.default_setting[field] || field == "usage_rule"
required = greeting_card_setting.is_required(field)
f1 = {'style_html'=>''}
field_name = "greeting_card_record[#{field}]"
placeholder = @default_greeting_card_setting.prompt_word(field)
id = field_name
case field
when 'title'
f1['content'] = text_field_tag(field_name,nil,placeholder: placeholder,required: required)
when 'name'
f1['content'] = text_field_tag(field_name,nil,data: (required ? {"fv-validation" => "required;", "fv-messages" => "必填欄位;"} : {}),required: required,placeholder: placeholder)
when 'sender_mail', 'recipients'
if @greeting_card_record
f1['content'] = @greeting_card_record.send(field)
else
f1['content'] = text_field_tag(field_name,nil,data: (required ? {"fv-validation" => "required;check_email;", "fv-messages" => "必填欄位;Email不正確;"} : {}),required: required,placeholder: placeholder)
end
when 'greetings'
f1['content'] = text_field_tag(field_name,nil,placeholder: placeholder,required: required)
when 'card'
f1['content'] = cal_card_html(greeting_card_images)
f1['inner_style_html'] = "max-width: unset; width: 76%;"
when 'sending_time'
f1['content'] = "<div class=\"default_picker\">#{text_field_tag(field_name,nil,placeholder: placeholder,data: {format: 'yyyy/MM/dd hh:mm'},required: required)}</div>"
when 'recaptcha'
id = "greeting_card_rucaptcha"
f1['content'] = "#{gotcha_error(:espeak=>true)}#{gotcha(id: id)}"
when 'usage_rule'
next if greeting_card_setting.usage_rule.blank?
f1['content'] = greeting_card_setting.usage_rule
when 'agree_show'
f1['content'] = check_box_tag(field_name, "1", false, {required: required})
when 'agree_usage'
f1['content'] = check_box_tag(field_name, "1", false, {required: required})
end
f1['field'] = field
f1['label'] = greeting_card_label(id, @default_greeting_card_setting.field_name("#{field}"),required.to_s)
all_fields << f1
end
end
end
end
if @greeting_card_record
all_fields << {'field'=>'greeting_card_record_id','style_html'=>'display: none;','label'=>'','content'=>hidden_field_tag('greeting_card_record[id]', @greeting_card_record.id)}
end
end
unless has_greeting_card_category_id
all_fields << {'field'=>'greeting_card_category_id','style_html'=>'display: none;','label'=>'','content'=>hidden_field_tag('greeting_card_record[category_id]', category_id)}
end
unless is_cat_record
@default_fields = all_fields
end
all_fields
end
def cal_html(fields,token_tag,form_id,referer_url,greeting_card_setting,is_hidden=true)
form_url = "/#{I18n.locale.to_s}/greeting_cards"
submit_tag = submit_tag(t('submit'), :class=> 'btn btn-primary', :id => 'button-mail')
close_tag = button_tag(t('cancel'), type: 'reset', :class=> 'btn')
multi_col_class = (greeting_card_setting.title_layout>0 rescue false) ? ' multi-col' : ' single-col'
col_class = (greeting_card_setting.title_layout==1 rescue false) ? ' col-sm-6' : ''
tmp = fields.collect do |field|
style_html = field['style_html']
inner_style_html = field['inner_style_html']
label = field['label']
content = field['content']
"<div class=\"control-group#{col_class}\" style=\"#{style_html}\">
#{label}
<div class=\"controls\" style=\"#{inner_style_html}\">
#{content}
</div>
</div>"
end.join
preview_btn = "<div style=\"text-align: center;\"><a href=\"javascript:;\" class=\"btn btn-primary preview-card\">#{I18n.t('greeting_card.preview')}</a></div>"
preview_section = "<div class=\"preview-card-section\"></div>"
"<form id=\"#{form_id}\" action=\"#{form_url}\" enctype=\"multipart/form-data\" method=\"post\" class=\"form-horizontal greeting_card_form#{multi_col_class}\" accept-charset=\"UTF-8\" style=\"#{is_hidden ? 'display: none;' : ''}\">
#{token_tag}
<div data-level=\"0\" data-list=\"fields\">
#{tmp}
#{preview_btn}
#{preview_section}
</div>
<div class=\"form-actions\">
<input type=\"hidden\" name=\"referer_url\" value=\"#{referer_url}\">
#{submit_tag}
#{close_tag}
</div>
</form>"
end
def script_text
"<script type=\"text/javascript\">
$(document).ready(function(){
$('select[name=\"greeting_card_record[category_id]\"]').change(function(){
var category_id = $(this).val()
$(this).parents('.greeting_card-question').eq(0).find('select[name=\"greeting_card_record[category_id]\"]').val(category_id)
var id
if ($('form#'+category_id).length != 0){
id = category_id
}
else{
id = 'greeting_card-default-form'
}
if (id != $(this).parents('form').eq(0).attr('id')){
var self = $(this)
var old_controls = self.parents('form').eq(0).find('.control-group')
var old_inputs = old_controls.children('label').map(function(){
return $.trim($(this).text().replace(/\\\*/g,''));
}).get()
var new_controls = self.parents('.greeting_card-question').eq(0).find('form#'+id).find('.control-group')
var new_inputs = new_controls.children('label').map(function(){
return $.trim($(this).text().replace(/\\\*/g,''));
}).get()
$(new_inputs).each(function(i,v){
var i0 = old_inputs.indexOf(v)
if (i0 != -1 && new_controls.eq(i).find('select#greeting_card_record_category_id').length==0){
var new_ = new_controls.eq(i).find('.controls').eq(0),
old_ = old_controls.eq(i0).find('.controls').eq(0),
new_input = new_.find('input, select'),
old_input = old_.find('input, select');
if(new_input.length != 0 && old_input.length != 0){
if(new_input.length == old_input.length){
var old_clone = old_.clone();
old_clone.find('input, select').attr('name', new_input.attr('name'));
old_clone.replaceAll(new_);
}
}
}
})
self.parents('.greeting_card-question').eq(0).find('form').hide()
self.parents('.greeting_card-question').eq(0).find('form#'+id).show()
}
})
})
</script>"
end
def cal_switch_form(greeting_card_settings,categories,token_tag,referer_url, greeting_card_record_id)
switch_form = ''
default_idx = 0
if greeting_card_record_id.present?
@greeting_card_record = GreetingCardRecord.where(:id=> greeting_card_record_id).first
if @greeting_card_record && !(@greeting_card_record.is_hidden)
@greeting_card_record = nil
end
if @greeting_card_record
GreetingCardSafeEmail.create(:email=> @greeting_card_record.sender_mail) if GreetingCardSafeEmail.where(:email=> @greeting_card_record.sender_mail).count == 0
greeting_card_settings = GreetingCardCategorySetting.enabled.where(:category_id=> @greeting_card_record.category_id).to_a
if greeting_card_settings.blank?
return switch_form
end
end
else
@greeting_card_record = nil
end
if categories.count != 0
default_idx = greeting_card_settings[1..-1].to_a.map{|a| a.category_id.to_s}.index(categories[0].id.to_s)
default_idx = default_idx.nil? ? 0 : default_idx + 1
end
@default_greeting_card_setting ||= GreetingCardSetting.first
collected_fields_var = "var collected_fields = "
collected_fields = []
img_objs_var = "var card_img_objs = "
img_objs = []
default_layout_design = GreetingCardLayoutDesign.where(:category_id=> nil).first
switch_form = script_text + greeting_card_settings.collect.with_index do |greeting_card_setting,i|
category_id = categories[i].id.to_s
layout_design = GreetingCardLayoutDesign.where(:category_id=> category_id).first
if layout_design.nil?
if default_layout_design.nil?
next
else
layout_design = default_layout_design
end
end
collected_fields << layout_design.preserved_keys
img_objs << layout_design.img_objs.values
fields = cal_form_from_setting(greeting_card_setting,categories,true)
is_hidden = (i != default_idx)
cal_html(fields,token_tag,category_id,referer_url,greeting_card_setting,is_hidden)
end.join
collected_fields_var += collected_fields.to_json
img_objs_var += img_objs.to_json
img_objs_var = "<script type=\"text/javascript\">\n#{collected_fields_var};\n#{img_objs_var};\n</script>"
switch_form + img_objs_var
end
end

View File

@ -0,0 +1,478 @@
module Admin::GreetingCardsHelper
extend self
extend ActionView::Helpers::FormTagHelper
extend ActionView::Helpers::FormOptionsHelper
extend ActionView::Helpers::DateHelper
extend ActionView::Helpers::TagHelper
extend ActionView::Helpers::RenderingHelper
extend ActionView::Context
extend OrbitBasis::RenderAnywhere
extend ActionView::Helpers::UrlHelper
extend OrbitFormHelper
extend Ckeditor::Helpers::FormHelper
def get_categories_info_for_greeting_card
current_user = OrbitHelper.current_user
OrbitHelper.set_params(params,current_user)
OrbitHelper.set_this_module_app("greeting_card")
cats_relations = []
access_level = OrbitHelper.user_access_level?
include_all = false
cats = []
if access_level == "sub_manager"
cats = current_user.approved_categories_for_module(@module_app)
elsif access_level && access_level != "user"
cats = @module_app.categories.enabled
include_all = true
end
if (@module_app.asc rescue true)
cats = cats.sort_by{|category| (category.sort_number.to_i rescue category.id) }
else
cats = cats.sort_by{|category| (-category.sort_number.to_i rescue category.id)}
end
cats_relations = cats.map{|c| [c.id.to_s, c.title]}
if include_all && cats_relations.count != 1
cats_relations.insert(0, ["",t(:all)])
end
cats_relations
end
def set_input_name_for_greeting_card(input_name)
@input_name = input_name
end
def get_input_name_for_greeting_card
@input_name
end
def create_lang_panel_for_greeting_card(field)
tmp2 = content_tag(:div,:class => 'btn-group', :data=>{:toggle=>"buttons-radio"}) do
I18n.available_locales.collect do |key|
link_entry_ary = ["##{field}", "_#{key}", @field_postfix]
link_entry = link_entry_ary.join
link_to(I18n.t(key),link_entry,:data=>{:toggle=>"tab"},:class=>"btn #{(key == I18n.locale ? "active" : nil)}",:for=>key)
end.join.html_safe
end
end
def multiple_lang_show_tag_for_greeting_card(field_name, index1,field,value=nil,combine_element='',exteral_options={},sortable=false, extra_tr_class="",only_contents=false)
if !index1.nil?
all_field = (get_input_name_for_greeting_card + "[#{index1}][#{field}][parant]").gsub(/[\[@]/,'_').gsub(/\]/,'')
else
all_field = (get_input_name_for_greeting_card + "[#{field}][parant]").gsub(/[\[@]/,'_').gsub(/\]/,'')
end
if @field_postfix.nil?
@field_postfix = 1
else
@field_postfix += 1
end
tmp = (I18n.available_locales.collect do |locale|
active_flag = ((locale == I18n.locale) ? ' active' : '')
content_tag(:div,:class => "tab-content#{active_flag}",:id=>"#{all_field}_#{locale}#{@field_postfix}") do
value_locale = value[locale.to_s] rescue nil
"<div class=\"show_field\" id=\"#{index1 ? "#{get_input_name_for_greeting_card}[#{index1}][#{field}][#{locale}]" : "#{get_input_name_for_greeting_card}[#{field}][#{locale}]"}\">#{value_locale}</div>".html_safe
end
end.join + create_lang_panel_for_greeting_card(all_field)).html_safe + combine_element
if sortable
if exteral_options['style'].nil?
exteral_options['style'] = 'display: flex;align-items: center;flex-wrap: nowrap;'
else
exteral_options['style'] = exteral_options['style'] + 'display: flex;align-items: center;flex-wrap: nowrap;'
end
tmp = content_tag(:div,{:class => "tab-panel border"}.merge(exteral_options)) do
("<i class=\"icons-list-2\" style=\"cursor: grab;font-size: x-large;\"></i>" +content_tag(:div) do
tmp
end).html_safe
end
else
tmp = content_tag(:div,{:class => "tab-panel"}.merge(exteral_options)) do
tmp
end
end
if only_contents
tmp
else
tmp = "<tr class=\"#{extra_tr_class}\"><td>#{field_name}".html_safe + ":</td><td>".html_safe + tmp + "</td></tr>".html_safe
end
end
def multiple_lang_tag_for_greeting_card(index1,type_of_tag,field,value=nil,custom_options={},combine_element='',exteral_options={},sortable=false)
if !index1.nil?
all_field = (get_input_name_for_greeting_card + "[#{index1}][#{field}][parant]").gsub(/[\[@]/,'_').gsub(/\]/,'')
else
all_field = (get_input_name_for_greeting_card + "[#{field}][parant]").gsub(/[\[@]/,'_').gsub(/\]/,'')
end
if @field_postfix.nil?
@field_postfix = 1
else
@field_postfix += 1
end
tmp = (I18n.available_locales.collect do |locale|
active_flag = ((locale == I18n.locale) ? ' active' : '')
content_tag(:div,:class => "tab-content#{active_flag}",:id=>"#{all_field}_#{locale}#{@field_postfix}") do
value_locale = value[locale.to_s] rescue nil
if !index1.nil?
self.__send__("#{type_of_tag}_tag","#{get_input_name_for_greeting_card}[#{index1}][#{field}][#{locale}]",value_locale,custom_options)
else
self.__send__("#{type_of_tag}_tag","#{get_input_name_for_greeting_card}[#{field}][#{locale}]",value_locale,custom_options)
end
end
end.join + create_lang_panel_for_greeting_card(all_field)).html_safe + combine_element
if sortable
if exteral_options['style'].nil?
exteral_options['style'] = 'display: flex;align-items: center;flex-wrap: nowrap;'
else
exteral_options['style'] = exteral_options['style'] + 'display: flex;align-items: center;flex-wrap: nowrap;'
end
content_tag(:div,{:class => "tab-panel border"}.merge(exteral_options)) do
("<i class=\"icons-list-2\" style=\"cursor: grab;font-size: x-large;\"></i>" +content_tag(:div) do
tmp
end).html_safe
end
else
content_tag(:div,{:class => "tab-panel"}.merge(exteral_options)) do
tmp
end
end
end
def time_setting_block(key,value={})
class_block = (value['type'] != 'date') ? "time_setting_block" : "time_setting_block active"
format_selected = (value['type'] != 'date') ? nil : value['format']
range_selected = (value['type'] != 'date') ? nil : value['range_flag']
options1 = [['YYYY / MM / DD HH:mm','format1'],['YYYY / MM / DD','format2'],['YYYY / MM','format3'],['YYYY','format4']]
options2 = [[t('yes'),'true'],[t('no'),'false']]
format_setting_tag = field_select_tag_for_greeting_card(key,'format',options1,format_selected)
range_setting_tag = field_select_tag_for_greeting_card(key,'range_flag',options2,range_selected)
"<div class=\"#{class_block}\">
<table>
<tbody>
<tr>
<td>#{t('greeting_card.format')}:</td><td>#{format_setting_tag}</td>
</tr>
<tr>
<td>#{t('greeting_card.enable_range_setting')}:</td><td>#{range_setting_tag}</td>
</tr>
</tbody>
</table>
</div>"
end
def field_select_tag_for_greeting_card(index1,field,options,selected=nil,custom_options={})
select_tag("#{get_input_name_for_greeting_card}[#{index1}][#{field}]",options_for_select(options,selected: selected),custom_options)
end
def field_radio_button_tag(index1,field,show_value,checked,custom_options={})
radio_button_tag("#{get_input_name_for_greeting_card}[#{index1}][#{field}]",show_value,checked,custom_options)
end
def render_date_block(field_name,v,i,value, prefix_contents="")
case v['format']
when 'format1'
t1 = text_field_tag("#{field_name}[datetime][date][#{i}]",(value['datetime']['date']["#{i}"] rescue nil),{:required => v['required']=='true',autocomplete: 'off',placeholder: t('greeting_card.datepicker'),title: t('greeting_card.datepicker')})
t1 = prefix_contents + t1
#t2_value = value['datetime']['h']["#{i}"] rescue nil
#t3_value = value['datetime']['m']["#{i}"] rescue nil
#t2 = select_tag("#{field_name}[datetime][h][#{i}]",options_for_select((1..24).collect{|v1| v1.to_s.rjust(2, "0")},selected: t2_value))
#t3 = select_tag("#{field_name}[datetime][m][#{i}]",options_for_select((0..59).collect{|v1| v1.to_s.rjust(2, "0")},selected: t3_value))
#t4 = "#{t2}<b style=\"padding: 0 0.1em;\">:</b>#{t3}"
"<div class=\"datetime_selector\">#{t1}</div>
<script>
jQuery(document).ready(function( $ ) {
$(\"input[name='#{field_name}[datetime][date][#{i}]']\").ui_datetimepicker({dateFormat: 'yy-mm-dd',controlType: 'select',timeInput: true,oneLine: true,timeFormat: 'HH:mm'});
})
</script>".html_safe
when 'format2'
t1 = text_field_tag("#{field_name}[datetime][date][#{i}]",(value['datetime']['date']["#{i}"] rescue nil),{:required => v['required']=='true',autocomplete: 'off',placeholder: t('greeting_card.datepicker'),title: t('greeting_card.datepicker')})
t1 = prefix_contents + t1
"<div class=\"datetime_selector\">#{t1}</div>
<script>
jQuery(document).ready(function( $ ) {
$(\"input[name='#{field_name}[datetime][date][#{i}]']\").ui_datepicker({dateFormat: 'yy-mm-dd'});
})
</script>".html_safe
when 'format3'
t1 = text_field_tag("#{field_name}[datetime][date][#{i}]",(value['datetime']['date']["#{i}"] rescue nil),{:required => v['required']=='true',autocomplete: 'off',placeholder: t('greeting_card.datepicker'),title: t('greeting_card.datepicker'),:class => 'yearpicker'})
t1 = prefix_contents + t1
"<div class=\"datetime_selector\">#{t1}</div>
<script>
jQuery(document).ready(function( $ ) {
$(\"input[name='#{field_name}[datetime][date][#{i}]']\").ui_datepicker({dateFormat: 'yy-mm',show_view: 'month'});
})
</script>
"
when 'format4'
t1 = text_field_tag("#{field_name}[datetime][date][#{i}]",(value['datetime']['date']["#{i}"] rescue nil),{:required => v['required']=='true',autocomplete: 'off',placeholder: t('greeting_card.datepicker'),title: t('greeting_card.datepicker'),:class => 'yearpicker'})
t1 = prefix_contents + t1
"<div class=\"datetime_selector\">#{t1}</div>
<script>
jQuery(document).ready(function( $ ) {
$(\"input[name='#{field_name}[datetime][date][#{i}]']\").ui_datepicker({dateFormat: 'yy',show_view: 'year'});
})
</script>
"
end
end
def greeting_card_label(id, value, required='false')
label_tag(id,value,{:class=>"control-label#{required=='true' ? ' required' : ''}"})
end
def format_checkbox(options,value,multple_choose=false)
options.select{|index1,option| option['disabled'] != 'true'}.collect do |index1,option|
if multple_choose
if value && value[index1]==index1
"#{option[I18n.locale]}"
else
"#{option[I18n.locale]}"
end
else
if index1 == value
"#{option[I18n.locale]}"
else
"#{option[I18n.locale]}"
end
end
end.join('&nbsp;&nbsp;')
end
def show_on_front(k,v,object=nil,readonly=false,lock=false)
value = nil
if !object.nil?
value = object.custom_values[k]
if value.nil?
if k.start_with?("default@")
value = object.custom_values[k.sub(/.*@/,'')]
elsif k.start_with?("custom@")
category_id, k = k.scan(/custom@((?:(?!@).)*)@\w+/)[0][0]
if category_id==object.category_id.to_s
value = object.custom_values[k]
end
end
end
end
field_name = "#{get_input_name_for_greeting_card}[custom_values][#{k}]"
begin
case v['type']
when 'text_field'
readonly ? value : text_field_tag(field_name,value,{:required => v['required']=='true',placeholder: v['prompt_word'][I18n.locale],title: v['prompt_word'][I18n.locale]})
when 'instructions'
(v['instructions'][I18n.locale].html_safe rescue "")
when 'select'
prompt_hash = v['prompt_word'][I18n.locale].blank? ? {} : {prompt: v['prompt_word'][I18n.locale]}
prompt_hash.merge!(required: v['required']=='true')
options_hash = Hash(v['options'])
if lock
format_checkbox(options_hash,value)
else
if v['default_option'].present?
default_idx = v['default_option'].to_i
default_key = options_hash.keys[default_idx]
value ||= default_key
end
readonly ? (v['options'][value.to_s][I18n.locale] rescue '') : select_tag(field_name,options_for_select(options_hash.select{|index1,option| option['disabled'] != 'true'}.collect{|index1,option| [option[I18n.locale],index1]},selected: value),prompt_hash)
end
when 'date'
if value.nil?
value = {}
end
if v['range_flag']=='true'
if readonly
format_str = "%Y/%m/%d %H:%M"
case v['format']
when 'format1'
format_str = "%Y/%m/%d %H:%M"
when 'format2'
format_str = "%Y/%m/%d"
when 'format3'
format_str = "%Y/%m"
when 'format4'
format_str = "%Y"
end
tmp = value['datetime']['date'] rescue {}
"#{DateTime.parse(tmp['0']).strftime(format_str) rescue ''}~#{DateTime.parse(tmp['1']).strftime(format_str) rescue ''}"
else
"<div style=\"display:inline-flex;flex-direction:column;\">
#{render_date_block(field_name,v,0,value, t('greeting_card.start') + ': ')}
<div style=\"display: inline-flex;align-items: center;writing-mode: tb-rl;padding: 0.3em;\">~</div>
#{render_date_block(field_name,v,1,value, t('greeting_card.end') + ': ')}
</div>".html_safe
end
else
if readonly
format_str = "%Y/%m/%d %H:%M"
case v['format']
when 'format1'
format_str = "%Y/%m/%d %H:%M"
when 'format2'
format_str = "%Y/%m/%d"
when 'format3'
format_str = "%Y/%m"
when 'format4'
format_str = "%Y"
end
tmp = value['datetime']['date'] rescue {}
(DateTime.parse(tmp['0']).strftime(format_str) rescue '')
else
render_date_block(field_name,v,0,value)
end
end
when 'text_area'
readonly ? value : text_area_tag(field_name,value,{:required => v['required']=='true',:placeholder=> v['prompt_word'][I18n.locale],:title=> v['prompt_word'][I18n.locale],:class=>'ckeditor'})
when 'radio_button'
options_hash = Hash(v['options'])
if lock
format_checkbox(options_hash,value)
else
field_name_underscre = field_name.gsub(/(\[|\])/,'_').gsub('__','_').chomp('_')
default_idx = v['default_option'].to_i
value ||= options_hash.keys[default_idx]
readonly ? (options_hash[value.to_s][I18n.locale] rescue '') : options_hash.collect do |index1,option|
next if option['disabled'] == 'true'
"<label class=\"radio-inline\" for=\"#{field_name_underscre}_#{index1}\">#{radio_button_tag(field_name,index1,value==index1,{:required => v['required']=='true'})}#{option[I18n.locale]}</label>"
end.compact.join
end
when 'checkbox'
options_hash = Hash(v['options'])
if lock
format_checkbox(options_hash,value,true)
else
default_idx = v['default_option'].to_i
default_key = options_hash.keys[default_idx]
options_values = options_hash.values
value ||= {default_key=>default_key}
field_name_underscre = field_name.gsub(/(\[|\])/,'_').gsub('__','_').chomp('_')
readonly ? value.collect{|k1,v1| options_values[v1.to_i][I18n.locale]}.join(', ') : ("<span class=\"checkbox\">" + options_hash.collect do |index1,option|
next if option['disabled'] == 'true'
checkbox_option = option[I18n.locale]
"<label class=\"checkbox-inline\" for=\"#{field_name_underscre}_#{index1}\">#{check_box_tag("#{field_name}[#{index1}]",index1,value[index1]==index1,{title: checkbox_option})}#{checkbox_option}</label>"
end.compact.join + "</span>")
end
when 'file'
file_value = value[0] rescue nil
file_path = value[1] rescue nil
file_required = v['required']=='true'
readonly ? (file_path ? "<a href=\"#{file_path}\" title=\"file\">#{file_value}</a>" : "") : "<div class=\"file-selector\"><label class=\"ui-button\">
#{file_field_tag(field_name, {:data => {:src => file_path}, style: "position: absolute;width:0.1em;opacity: 0;padding: 0;border: 0;opacity: 0;left: 50%;top: 0;", :class => 'upload', :required => file_required, value: file_value})}
<i class=\"fa fa-file\"></i> #{t('greeting_card.upload_file')}
</label><div class=\"filename\"></div></div>"
when 'image'
file_value = value[0] rescue nil
file_path = value[1] rescue nil
file_required = v['required']=='true'
readonly ? (file_value ? "<img src=\"#{file_path}\" alt=\"#{file_value}\">" : "") : "<div class=\"file-selector\"><label class=\"ui-button\">
#{file_field_tag(field_name, {:data => {'image-src' => file_path}, style: "position: absolute;width:0.1em;padding: 0;border: 0;opacity: 0;left: 50%;top: 0;", :class => 'upload', :required => file_required, value: file_value, accept: "image/*"})}
<i class=\"fa fa-photo\"></i> #{t('greeting_card.upload_image')}
</label><div class=\"filename\"></div></div>"
end
rescue => e
"<pre>#{e.inspect}<br>#{e.backtrace.to_yaml}</pre>"
end
end
def custom_field_block_for_greeting_card(k,v={},show_only=false, other_first_rows="",extra_class="")
# markups = LIST[:markups].select{|k,v| k != 'member_relationship' && k != 'address'}.collect{|key,val| [t("lists.markups."+key),key]} +[[t('greeting_card.file_field'),'file'],[t('greeting_card.image_field'),'image'],[t('greeting_card.instructions'),'instructions']]
allow_types = ['text_field']
markups = LIST[:markups].select{|k,v| allow_types.include?(k)}
if show_only
multi_lang_tag = multiple_lang_show_tag_for_greeting_card(t('greeting_card.field_name'),k,'field',v['field'])
require_greeting_card_tag = "<tr><td>#{t('greeting_card.required')}:</td><td>#{v['required']=='true' ? t('greeting_card.yes') : t('greeting_card.no')}</td></tr>"
markups = markups.map{|k,v| [v,k]}.to_h
tmp = markups[v['type']]
tmp = markups.values[0] if tmp.nil?
options_hash = Hash(v['options'])
tmp_field_select_tag_for_greeting_card = "<tr><td>#{t('greeting_card.setting_type')}:</td><td><div id=\"#{get_input_name_for_greeting_card}[#{k}][type]\">#{tmp}</div></td></tr>"
active_prompt_class = (v['type'] != 'instructions' ? '' : ' hide')
active_class = (['select','radio_button','checkbox'].include?(v['type']) ? '' : ' hide')
multi_lang_prompt_tag = multiple_lang_show_tag_for_greeting_card(t('greeting_card.prompt_word'),k,'prompt_word',v['prompt_word'],'',{},false, active_prompt_class)
multi_lang_default_option = multiple_lang_show_tag_for_greeting_card(t('greeting_card.default_option'),k,'default_option',v['default_option'].present? ? options_hash.values[v['default_option'].to_i] : I18n.t('greeting_card.please_select'),'',{},false, active_class)
options_area = options_hash.collect do |key,value|
"#{multiple_lang_show_tag_for_greeting_card("",k,"options][#{key}",value,'',{},false,"",true)}"
end.join
options_area = "<tr><td>#{I18n.t('greeting_card.options')}</td><td>#{options_area}</td></tr>"
field_html = "
<style>
.show_field {
border: 1px solid black;
padding: 3px;
min-width: 1em;
height: 20px;
overflow-y: auto;
}
</style>
<tbody class=\"custom_field #{extra_class}\" data-key=\"#{k}\">
#{other_first_rows}
#{multi_lang_tag}
#{require_greeting_card_tag}
#{tmp_field_select_tag_for_greeting_card}
#{multi_lang_prompt_tag}
#{multi_lang_default_option}
#{options_area}
</tbody>"
else
not_editable = k.to_s.include?('default@')
hint_text = ""
if not_editable
hint_text = "<div style=\"font-weight: bold;\">" + t('greeting_card.this_field_is_default_custom_fields') + "</div>"
end
disabled_attr = (not_editable ? 'disabled' : nil)
multi_lang_tag = multiple_lang_tag_for_greeting_card(k,'text_field','field',v['field'],{placeholder: t('greeting_card.field_name'), title: t('greeting_card.field_name'), disabled: disabled_attr})
tmp_field_select_tag_for_greeting_card = field_select_tag_for_greeting_card(k,'type',markups,v['type'],{:onchange=>'check_available_setting_block(this)', :disabled=>disabled_attr})
key = hidden_field_tag "#{get_input_name_for_greeting_card}[#{k}][key]",k,{'class' => 'key'}
options_hash = Hash(v['options'])
all_new_options = options_hash.collect do |key,value|
tmp = create_delete_button_for_greeting_card('delete_added_select_option').html_safe+hidden_field_tag("#{get_input_name_for_greeting_card}[#{k}][options][#{key}][disabled]",value['disabled'],{'class' => 'disabled_field'})
hidden_style = value['disabled'] == 'true' ? {style: 'display:none;'} : {}
"#{multiple_lang_tag_for_greeting_card(k,'text_field',"options][#{key}",value,{ placeholder: t('greeting_card.option_name'), class: 'option_name_field', title: t('greeting_card.option_name'), disabled: disabled_attr},tmp,hidden_style,true)}"
end.join
tmp_count = {}
options_hash.each{|k,v| v.each{|l,vv| tmp_count[l] = tmp_count[l].to_i + 1 if vv.present?}}
current_locale = I18n.locale.to_s
maximum_locale = tmp_count.sort_by{|k,v| [v, k == current_locale]}[0][0] rescue nil
maximum_locale = I18n.locale.to_s if maximum_locale.nil?
locale_options_for_field = options_hash.map.with_index{|(k, v), i| [v[maximum_locale], i] rescue ""}
is_selection_field = ['select','radio_button','checkbox'].include?(v['type'])
active_class = is_selection_field ? ' active' : ''
active_prompt_class = (v['type'] != 'instructions' ? ' active' : '')
multi_lang_prompt_tag = "<div class=\"prompt_word#{active_prompt_class}\">#{multiple_lang_tag_for_greeting_card(k,'text_field','prompt_word',v['prompt_word'],{ placeholder: t('greeting_card.prompt_word'), title: t('greeting_card.prompt_word'), disabled: disabled_attr})}</div>"
multi_lang_default_option = "<div class=\"default_option#{active_class}\">#{field_select_tag_for_greeting_card(k,'default_option',locale_options_for_field,v['default_option'],{ title: t('greeting_card.default_option'), class: 'default_option_select', disabled: disabled_attr, data: {locale: maximum_locale}, prompt: I18n.t('greeting_card.please_select')})}</div>"
instructions_text_area = "<div class=\"instructions_text_area#{v['type'] == 'instructions' ? '' : ' hide'}\">#{multiple_lang_tag_for_greeting_card(k,'text_area','instructions',v['instructions'],{ placeholder: t('greeting_card.prompt_word'), title: t('greeting_card.prompt_word'), class: 'ckeditor', disabled: disabled_attr})}</div>"
require_greeting_card_tag = "<div>#{t('greeting_card.required')}:&nbsp;&nbsp;#{field_radio_button_tag(k,'required','true',v['required']=='true',{disabled: disabled_attr})}#{t('greeting_card.yes')}#{field_radio_button_tag(k,'required','false',v['required']!='true',{disabled: disabled_attr})}#{t('greeting_card.no')}</div>"
tmp = "<div class=\"add_new_options#{active_class}\">#{all_new_options}<input class=\"btn btn-info\" type=\"button\" value=\"#{t('greeting_card.add_new_options')}\" onclick=\"add_new_options_for_field(this,#{k})\"></div>"
field_html = "<tr class=\"custom_field #{extra_class}\" data-key=\"#{k}\">
<td>
#{other_first_rows}
#{hint_text}
#{multi_lang_tag}
#{require_greeting_card_tag}
#{tmp_field_select_tag_for_greeting_card}<br>
#{multi_lang_prompt_tag}
#{multi_lang_default_option}
#{instructions_text_area}
#{time_setting_block(k,v)}
#{tmp}
#{key}
</td>
<td>
#{create_delete_button_for_greeting_card('delete_field_func')}
</td>
</tr>"
end
end
def create_delete_button_for_greeting_card(func_name)
"<input class=\"btn btn-danger\" type=\"button\" value=\"#{t('delete_')}\" onclick=\"#{func_name}(this)\">"
end
def page_for_greeting_cardquestion(greeting_cardquestion)
ann_page = nil
pages = Page.where(:module=>'greeting_card')
pages.each do |page|
if page.categories.count ==1
if page.categories.include?(greeting_cardquestion.category.id.to_s)
ann_page = page
end
end
break if !ann_page.nil?
end
if ann_page.nil?
pages.each do |page|
if page.categories.include?(greeting_cardquestion.category.id.to_s)
ann_page = page
end
break if !ann_page.nil?
end
end
ann_page = pages.first if ann_page.nil?
request.protocol+(request.host_with_port+ann_page.url+'/'+greeting_cardquestion.to_param).gsub('//','/') rescue "/"
end
end

0
app/mailers/.keep Normal file
View File

0
app/models/.keep Normal file
View File

View File

@ -0,0 +1,99 @@
module GreetingCardSettingConcern
extend ActiveSupport::Concern
included do
self.field :email_regex_enable, type: Boolean, default: false
self.field :email_regex, type: String, default: '\A[^@\s]+@([^@.\s]+\.)+[^@.\s]+\z'
self.field :only_logged_in_users, type: Boolean, default: false
self.field :validate_enable, type: Boolean, default: false
self.field :must_verify_email, type: Boolean, default: false
self.field :validation_email_content, type: String, localize: true
self.field :tmp_sort_number, type: Hash, default: {} # For Frontend
self.field :sort_number, type: Hash, default: {}
self.field :default_setting, type: Hash,default: {title:true,greeting_card_category_id: true,name: true,sender_mail: true,recipients: true,greetings: true,card: true,sending_time: true,recaptcha: true,agree_show: true,agree_usage: true}
self.field :default_setting_required, type: Hash,default: {title:true,greeting_card_category_id: true,name: true,sender_mail: true,recipients: true,greetings: true,card: true,sending_time: true,recaptcha: true,agree_show: false,agree_usage: true}
self.field :default_setting_field_name, type: Hash,default: {}
self.field :default_setting_prompt_word, type: Hash,default: {}
self.field :custom_fields, type: Hash,default: {}
self.field :usage_rule, type: String, default: ''
self.field :title_layout, type: Integer, default: 0
self.has_many :greeting_card_images, :autosave => true, :dependent => :destroy
self.accepts_nested_attributes_for :greeting_card_images, :allow_destroy => true
self.before_save do
unless @skip_callback
if self.sort_number_changed?
self.sort_number = self.sort_number.map{|k,v| [k,v.to_i]}.sort_by{|k,v| v}.to_h
end
@custom_fields_changed = self.custom_fields_changed?
if @custom_fields_changed
@delete_custom_fields = self.custom_fields.select{|k,v| v['delete'] == true}.keys
@delete_custom_fields.each{|f| self.sort_number.delete(f)}
self.custom_fields = self.custom_fields.select{|k,v| v['delete'] != true}
end
self.recalc_sort(false)
end
true
end
end
def recalc_sort(save_flag=true)
self.tmp_sort_number = GreetingCardSetting.get_sort_number_only(true, self, true).map.with_index{|(k,v), i| [k,i]}.to_h
self.save if save_flag
end
def get_cache_sort_number #For Frontend
if self.tmp_sort_number.blank?
self.recalc_sort
end
self.tmp_sort_number
end
def default_field_name(k, locale=I18n.locale.to_s, use_checkbox_trans=false)
I18n.with_locale(locale) do
if use_checkbox_trans && ['agree_show','agree_usage'].include?(k.to_s)
I18n.t("greeting_card.#{k}_checkbox")
else
if ['serial_number','situation','ip'].include?(k)
I18n.t("greeting_card.#{k}")
else
I18n.t("mongoid.attributes.greeting_card_record.#{k}")
end
end
end
end
def field_name(k, locale=I18n.locale.to_s, use_checkbox_trans=false)
tmp = self.default_setting_field_name[k]
(tmp && tmp[locale]) ? tmp[locale] : self.default_field_name(k, locale, use_checkbox_trans)
end
def prompt_word(k,locale=I18n.locale.to_s,use_checkbox_trans=false)
tmp = self.default_setting_prompt_word[k]
(tmp&&tmp[locale]) ? tmp[locale] : self.field_name(k,locale)
end
def field_name_translations(k)
I18n.available_locales.map{|v| [v.to_s,self.field_name(k,v.to_s)]}.to_h
end
def prompt_word_translations(k)
I18n.available_locales.map{|v| [v.to_s,self.prompt_word(k,v.to_s)]}.to_h
end
def is_required(k)
self.default_setting_required[k]
end
def get_email_regex(frontend=false)
tmp = self.email_regex
if tmp && frontend
tmp = tmp.gsub("\\A","^").gsub("\\z","$").gsub("\\","\\\\\\\\")
end
tmp = nil if !(self.email_regex_enable) || ((self.default_setting[:mail] == false) rescue false)
tmp
end
end

View File

@ -0,0 +1,6 @@
class GreetingCardAcknowledgement
include Mongoid::Document
include Mongoid::Timestamps
field :content, type: Hash,default:{}
end

View File

@ -0,0 +1,7 @@
class GreetingCardAdmin
include Mongoid::Document
include Mongoid::Timestamps
field :email, type: String
has_and_belongs_to_many :categories
end

View File

@ -0,0 +1,197 @@
class GreetingCardCategorySetting
include Mongoid::Document
include Mongoid::Timestamps
include ::GreetingCardSettingConcern
DateTypes = ['regular_date', 'birthday']
field :default_sort_number, type: Hash, default: {}
field :automatically_send, type: Boolean, default: false
field :auto_send_image_id, type: BSON::ObjectId
field :auto_send_date_type, type: Integer, default: -1
field :sender_mail, type: String
field :regular_date, type: String
field :recipient_ids, type: Array, default: []
field :need_check_customs, type: Array, default: [] #From GreetingCardSetting
field :reject_customs, type: Array, default: [] #From GreetingCardSetting
field :agree_customs, type: Array, default: [] #From GreetingCardSetting
field :category_id, type: String
field :use_default, type: Boolean, default: false
field :host_url
field :update_user_id
scope :enabled, ->{any_of([{:use_default.ne=>true}, {:use_default=>true, :default_sort_number.nin=>[nil, {}]}])}
scope :custom_enabled, ->{where({:use_default.ne=>true})}
before_save do
unless @skip_callback
if @custom_fields_changed
@delete_custom_fields = @delete_custom_fields.select{|k| k.include?("default@")}
self.delete_customs_func(@delete_custom_fields, true)
end
if self.automatically_send
if !self.automatically_send_was || self.auto_send_image_id_changed? || self.auto_send_date_type_changed? || self.sender_mail_changed? || self.regular_date_changed?
self.generate_records
end
end
true # prevent return false in before_save
end
end
def self.get_images(category_id)
greeting_card_setting = GreetingCardSetting.first
images = []
if greeting_card_setting
images += greeting_card_setting.greeting_card_images.map{|img| img.file.url}
end
if category_id
greeting_card_setting2 = self.where(:category_id=> category_id).first
if greeting_card_setting2
images += greeting_card_setting2.greeting_card_images.map{|img| img.file.url}
end
end
images
end
def agree_customs_func(apply_custom_fields, check_custom_fields=nil)
if apply_custom_fields.count != 0
self.agree_customs += apply_custom_fields
self.agree_customs.uniq!
if check_custom_fields.nil?
check_custom_fields = GreetingCardSetting.first.custom_fields
end
apply_custom_fields.each{|k| self.custom_fields["default@#{k}"] = check_custom_fields[k]}
self.need_check_customs -= apply_custom_fields
self.reject_customs -= apply_custom_fields
self.recalc_sort(false)
@skip_callback = true
self.save
@skip_callback = false
end
true
end
def delete_customs_func(delete_custom_fields, add_to_reject=false)
if delete_custom_fields.count != 0
delete_custom_fields = delete_custom_fields.map{|f| f.sub(/^default@/, '')}
self.need_check_customs -= delete_custom_fields
self.agree_customs -= delete_custom_fields
if add_to_reject
self.reject_customs += delete_custom_fields
self.reject_customs.uniq!
else
self.reject_customs -= delete_custom_fields
delete_custom_fields.each do |f|
self.custom_fields.delete("default@#{f}")
end
end
self.recalc_sort(false)
@skip_callback = true
self.save
@skip_callback = false
end
true
end
def update_need_check_customs(check_custom_fields, is_locale=false, need_check=false)
if need_check
check_custom_fields = check_custom_fields.map{|k,v| [k, v["field"][I18n.default_locale.to_s]]}.to_h unless is_locale
category_custom_fields = self.custom_fields.map{|k,v| v["field"][I18n.default_locale.to_s]}
self.need_check_customs += check_custom_fields.select{|k,v| v.blank? || !(category_custom_fields.include?(v))}.keys
else
self.need_check_customs += check_custom_fields.keys
end
self.need_check_customs = self.need_check_customs.uniq
self.need_check_customs -= self.reject_customs
self.need_check_customs -= self.agree_customs
unless is_locale
self.agree_customs.each{|k| self.custom_fields["default@#{k}"] = check_custom_fields[k]}
end
self.recalc_sort(false)
@skip_callback = true
self.save
@skip_callback = false
end
def recipients
MemberProfile.where(:id.in=> self.recipient_ids)
end
def enabled
if use_default
default_sort_number.present?
else
true
end
end
def generate_record(site, module_app, member_profile, locale, sending_time, today)
update_user = User.where(id: self.update_user_id).first
if sending_time.nil?
sending_time = member_profile.birthday
sending_time = Date.parse(sending_time.strftime("#{today.year}-%m-%d"))
end
if sending_time < today
sending_time += 1.year
end
# only update future email
email_record = GreetingCardEmail.where(category_id: self.category_id, member_profile: member_profile, year: today.year, sending_time: {"$gt"=> today.to_datetime}, is_sent: false).first
if email_record.nil?
I18n.with_locale(locale) do
email = Email.new
email.save
r = GreetingCardRecord.new(category_id: self.category_id, is_hidden: true, title: member_profile.name, name: member_profile.name, sender_mail: self.sender_mail, recipients: member_profile.email, sending_time: sending_time, card: self.auto_send_image_id)
r.email_id = email.id
r.save
email_record = GreetingCardEmail.create(category_id: self.category_id, year: today.year, sending_time: sending_time, member_profile: member_profile, email: email, greeting_card_record: r)
r.build_email(site, self.host_url, update_user, module_app, locale, email, {"model_class"=> "GreetingCardEmail", "model_id"=> email_record.id})
end
else
r = email_record.greeting_card_record
r.instance_variable_set(:@skip_callback, true)
if r.card != self.auto_send_image_id # no need to generate image
r.generate_image
end
r.update(sending_time: sending_time, card: self.auto_send_image_id)
# I18n.with_locale(locale) do
# r.build_email(site, self.host_url, update_user, module_app, locale, r.email, {"model_class"=> "GreetingCardEmail", "model_id"=> email_record.id})
# end
email_record.update(sending_time: sending_time)
r.email.update(mail_sentdate: sending_time)
end
end
def generate_records
layout_design = GreetingCardLayoutDesign.where(:category_id=> category_id).first
if layout_design.nil?
default_layout_design = GreetingCardLayoutDesign.where(:category_id=> nil).first
if default_layout_design.nil?
return false
else
layout_design = default_layout_design
end
end
if @generating_records
return false
else
@generating_records = true
Thread.new do
site = Site.first
module_app = ModuleApp.where(key: 'greeting_card').first
today = Date.today
if self.auto_send_date_type == 0
sending_time = DateTime.parse("#{today.year}/#{self.regular_date}")
else
sending_time = nil # use birthday
end
self.recipients.to_a.each do |member_profile|
self.generate_record(site, module_app, member_profile, I18n.locale, sending_time, today)
end
@generating_records = false
end
return true
end
end
end

View File

@ -0,0 +1,6 @@
class GreetingCardCategorySettingIndex
include Mongoid::Document
include Mongoid::Timestamps
field :key,type: Integer,default: 0
field :category_id
end

View File

@ -0,0 +1,36 @@
class GreetingCardEmail
include Mongoid::Document
include Mongoid::Timestamps
field :category_id
field :year, type: Integer
field :sending_time, type: DateTime
field :is_sent, :type => Boolean, :default => false
belongs_to :member_profile
belongs_to :email, dependent: :destroy
belongs_to :greeting_card_record, dependent: :destroy, index: true
index({category_id: 1, year: -1, sending_time: -1, member_profile_id: 1}, { unique: false, background: true })
def email_sent(mails, flag)
if flag # Generate next record when email is sent
new_sending_time = self.sending_time + 1.year
new_email_record = self.dup
new_record = self.greeting_card_record.dup
new_email_record.year += 1
new_email_record.sending_time = new_sending_time
new_record.sending_time = new_sending_time
new_email = self.email.dup
new_email.mail_sentdate = new_sending_time
new_email.template_data["model_id"] = new_email_record.id
new_email.save
new_record.email_id = new_email.id
new_email_record.email_id = new_email.id
new_email_record.greeting_card_record = new_record
new_record.save
new_email_record.save
self.update(is_sent: true)
end
end
end

View File

@ -0,0 +1,7 @@
class GreetingCardFile
include Mongoid::Document
include Mongoid::Timestamps
mount_uploader :file, AssetUploader
field :greeting_card_record_id
end

View File

@ -0,0 +1,22 @@
# encoding: utf-8
class GreetingCardImage
include Mongoid::Document
include Mongoid::Timestamps
mount_uploader :file, ImageUploader
field :description, localize: true
belongs_to :greeting_card_setting
belongs_to :greeting_card_category_setting
def description_text
if self.description.blank?
""
else
Nokogiri::HTML::fragment(self.description.to_s).text
end
end
end

View File

@ -0,0 +1,403 @@
class GreetingCardLayoutDesign
require 'freetype/api'
include Mongoid::Document
include Mongoid::Timestamps
field :print_format, type: String,default: ''
field :save_name, type: String,default: 'greeting_card_{title}'
field :img_objs, type: Hash, default: {}
field :preserved_keys, type: Array
field :category_id
before_save do
self.preserved_keys = img_objs.map do |i, obj|
get_preserved_keys(obj[:text])
end.flatten
self.preserved_keys += get_preserved_keys(self.save_name)
self.preserved_keys = self.preserved_keys.uniq.map(&:to_sym)
end
def get_preserved_keys(text)
if text.present?
text.scan(/(?<={)[^{}]+(?=})/)
else
[]
end
end
# 微軟正黑體
# need to call f.close manually to prevent memory leak
def get_font(font_name)
font_file = `fc-match '#{font_name}' -f "%{file}" 2>/dev/null`
if font_file.blank?
puts "#{font_name} font not found!"
nil
else
f = FreeType::API::Font.open(font_file)
font_info = {
m_w: 1.0 * f.face[:max_advance_width] / f.face[:units_per_EM],
m_h: 1.0 * f.face[:max_advance_height] / f.face[:units_per_EM],
l_g: 1.0 * (f.face[:height] - f.face[:max_advance_height]) / f.face[:units_per_EM], # line gap
f: f,
file: font_file
}
font_info
end
end
def set_char_size(f, font_size)
f.set_char_size(0, font_size * 64, 0, 0)
end
def get_char_real_width(c, font_size, f=nil, prev_c=nil)
if f.nil?
c_w = get_char_estimate_width(c, font_size)
else
c_w = (f.glyph(c).char_width >> 6) # this size is 64 times larger
if prev_c
c_w += (f.kerning_unscaled(prev_c, c).x >> 6)
end
end
c_w
end
def get_char_estimate_width(c, font_size)
chinese_ratio = 1
sixth_chars = ('0'..'9').to_a
seventh_chars = ('A'..'Z').to_a + ['g', 'h', 'n', 'o', 'p', 'q', 'w']
half_chars = ['-', '_', '?'] + (('a'..'z').to_a - ['m', 't'])
third_chars = [' ', '[', ']', '【', '】', '《', '》', '(', ')', 'i', 'l', 'r', 't', 'f', '!', '.', '-', ':', ';']
point_chars = []
if point_chars.include?(c)
w = 0.1
elsif third_chars.include?(c)
w = 0.3
elsif half_chars.include?(c)
w = 0.5
elsif sixth_chars.include?(c)
w = 0.6
elsif seventh_chars.include?(c)
w = 0.7
elsif c.match(/\p{Han}/)
w = chinese_ratio
else
w = 1
end
return w * font_size
end
def wrap_text_accurate(text, font_info, font_size, width, height, line_height=1, ellipsis=true)
if font_info.nil?
wrap_text_estimate(text, font_size, width, height, line_height, ellipsis)
else
if width == 0.0 && height == 0.0 # auto width and auto height
return text
end
if height == 0.0
max_lines = 0
else
max_lines = [height / (line_height * font_size * font_info[:m_h]).to_i, 1].max
end
f = font_info[:f]
set_char_size(f, font_size)
new_text = ""
last_line = ""
w = 0
lines = 1
prev_c = nil
check_ellipsis = false
text.chars.each do |c|
if c == "\n"
lines += 1
if max_lines != 0 && lines > max_lines
check_ellipsis = true
break
end
new_text += last_line
new_text += c
last_line = ""
prev_c = nil
w = 0
elsif width != 0.0
c_w = get_char_real_width(c, font_size, f, prev_c)
prev_c = c
tmp_w = w + c_w
if tmp_w > width
lines += 1
if max_lines != 0 && lines > max_lines
check_ellipsis = true
break
end
# Wrap the word
last_word = nil
last_line.sub!(/ ([^ ]+)$/){|s| last_word = $1; ' '}
new_text += last_line
new_text += "\n"
if last_word
# last line starts with word
last_line = last_word
w = get_text_real_width(last_word, font_size, f) + c_w
else
w = c_w
last_line = ""
end
else
w = tmp_w
end
last_line += c
end
end
if check_ellipsis && ellipsis # Add ...
last_w = w
ellipsis_text = "..."
ellipsis_width = get_text_real_width(ellipsis_text, font_size, f)
remain_width = width - last_w
if width == 0.0 || remain_width >= ellipsis_width
new_text += ellipsis_text
else
last_line_arr = last_line.split(/ /)
if last_line_arr.count > 1
space_width = get_char_real_width(' ', font_size, f)
while remain_width < ellipsis_width do
if last_line_arr.count > 1
remain_width += space_width
prev_c = ' '.freeze
else
prev_c = nil
end
s = last_line_arr.pop
s_width = get_text_real_width(s, font_size, f, prev_c)
remain_width += s_width
break if last_line_arr.empty?
end
last_line = last_line_arr.join(' ')
else
while remain_width < ellipsis_width do
c = last_line[-1]
last_line.chop!
if last_line.empty?
prev_c = nil
else
prev_c = last_line[-1]
end
remain_width += get_char_real_width(c, font_size, f, prev_c)
if prev_c.nil?
break
end
end
end
new_text += last_line
new_text += ellipsis_text
end
else
new_text += last_line
end
new_text
end
end
def wrap_text_estimate(text, font_size, width, height, line_height=1, ellipsis=true)
if width == 0.0 && height == 0.0 # auto width and auto height
return text
end
if height == 0.0
max_lines = 0
else
max_lines = [height / (line_height * font_size).to_i, 1].max
end
new_text = ""
last_line = ""
w = 0
lines = 1
check_ellipsis = false
text.chars.each do |c|
if c == "\n"
lines += 1
if max_lines != 0 && lines > max_lines
check_ellipsis = true
break
end
new_text += last_line
new_text += c
last_line = ""
prev_c = nil
w = 0
elsif width != 0.0
c_w = get_char_estimate_width(c, font_size)
tmp_w = w + c_w
if tmp_w > width
lines += 1
if max_lines != 0 && lines > max_lines
check_ellipsis = true
break
end
# Wrap the word
last_word = nil
last_line.sub!(/ ([^ ]+)$/){|s| last_word = $1; ' '}
new_text += last_line
new_text += "\n"
if last_word
# last line starts with word
last_line = last_word
w = get_text_estimate_width(last_word, font_size) + c_w
else
w = c_w
last_line = ""
end
else
w = tmp_w
end
last_line += c
end
end
if check_ellipsis && ellipsis
last_w = w
ellipsis_text = "..."
ellipsis_width = get_text_estimate_width(ellipsis_text, font_size)
remain_width = width - last_w
if width == 0.0 || remain_width >= ellipsis_width
new_text += "..."
else
last_line_arr = last_line.split(/ /)
if last_line_arr.count > 1
space_width = get_char_estimate_width(' ', font_size)
while remain_width < ellipsis_width do
if last_line_arr.count > 1
remain_width += space_width
end
s = last_line_arr.pop
s_width = get_text_estimate_width(s, font_size)
remain_width += s_width
break if last_line_arr.empty?
end
last_line = last_line_arr.join(' ')
else
while remain_width < ellipsis_width do
c = last_line[-1]
last_line.chop!
remain_width += get_char_estimate_width(c, font_size)
if last_line.empty?
break
end
end
end
new_text += last_line
new_text += '...'
end
else
new_text += last_line
end
new_text
end
def get_text_real_width(text, font_size, f=nil, prev_c=nil)
if f.nil?
get_text_estimate_width(text, font_size)
else
set_char_size(f, font_size)
w = 0
text.chars.each do |c|
w += get_char_real_width(c, font_size, f, prev_c)
prev_c = c
end
w
end
end
def get_text_estimate_width(text, font_size)
w = 0
text.chars.each do |c|
w += get_char_estimate_width(c, font_size)
end
return w
end
def generate_image(record, image_source, data, saved=true)
# change locale to chinese
ENV['LANG'] = "zh_TW.UTF-8"
begin
img = MiniMagick::Image.open(image_source)
rescue => e
puts "image open: #{image_source} failed!"
return nil
end
data = data.select{|k, v| self.preserved_keys.include?(k)}
img_objs_arr = self.img_objs.map do |i, _obj|
obj = _obj.dup
obj[:text].gsub!(/{([^{}]+)}/){|k| data[$1.to_sym]}
obj[:text].gsub!("\r\n", "\n")
obj[:text].strip!
obj
end
img_width = img[:width]
img_height = img[:height]
font_scale = img_width / 500.0
width_scale = img_width / 100.0
height_scale = img_height / 100.0
image_filename = save_name.gsub!(/{([^{}]+)}/){|k| data[$1.to_sym]}.gsub(CarrierWave::SanitizedFile.sanitize_regexp, '_') + File.extname(image_source)
record.image_will_change!
record[:image] = image_filename # must called
record.image.retrieve_from_store!(image_filename) # must called
dest_image_path = record.image.file.path
image_dir = File.dirname(dest_image_path)
FileUtils.rm_rf image_dir
FileUtils.mkdir_p image_dir
FileUtils.copy_file(image_source, dest_image_path)
record.image.manipulate! do |image|
image.combine_options do |c|
# c << "thumb_榮獲設計競賽-transformed.png"
img_objs_arr.each do |obj|
is_stroke = (obj[:is_stroke] == 'true')
if is_stroke
is_fill = obj[:is_fill] != 'false'
else
is_fill = true
end
x = width_scale * obj[:x].to_f
y = height_scale * obj[:y].to_f
w = width_scale * obj[:w].to_f
h = height_scale * obj[:h].to_f
fontSize = font_scale * obj[:fontSize].to_f
fontFamily = obj[:fontFamily]
font_info = get_font(fontFamily)
if font_info
fontFamily = font_info[:file]
end
line_height = (obj[:l_h] ? obj[:l_h].to_f : 1.0)
wrapped_text = wrap_text_accurate(obj[:text], font_info, fontSize, w, h, line_height)
y = y + fontSize
# y = img_height - y
# x = img_width - x
# c.interline_spacing caption_interline_spacing
line_gap = 0
if font_info
line_gap = -(font_info[:l_g] * fontSize)
end
if obj[:l_h]
line_gap = line_gap + (line_height - 1.0) * fontSize
end
c.interline_spacing line_gap.round(2)
c.font fontFamily
c.pointsize fontSize
c.fill (is_fill ? obj[:fontColor] : 'none')
if is_stroke
c.stroke obj[:stroke]
c.strokewidth (font_scale * obj[:strokeWidth].to_f)
else
c.stroke 'none'
end
# c.kerning -2
c.kerning 1.5
c.annotate "+#{x}+#{y}"
c << wrapped_text #.force_encoding("UTF-8")
# c << "123"
if font_info
font_info[:f].close
end
end
end
end
record.save if saved
end
end

View File

@ -0,0 +1,29 @@
class GreetingCardListSetting
include Mongoid::Document
include Mongoid::Timestamps
DefaultFields = ['serial_number','image','greeting_card_category_id','title','name','sender_mail','recipients','created_at','ip']
DefaultEnabled = ['serial_number','image','greeting_card_category_id','title','name','created_at','ip']
field :default_fields, type: Array, default: []
field :custom_fields, type: Array, default: []
field :category_id
def default_fields
tmp = super()
if tmp.empty?
tmp = self.class::DefaultEnabled
end
return tmp
end
def custom_fields_list
locale = I18n.locale
default_setting = GreetingCardSetting.first
use_default = self.category_id.blank? || GreetingCardCategorySetting.where(:category_id=>self.category_id, :use_default.ne=>true).first.nil?
if use_default
fields = default_setting ? {I18n.t(:default) => default_setting.custom_fields.map{|k,v| ["default@#{k}",v['field'][locale]]}.to_h} : {}
cat_ids_map = Category.where(:id.in=> GreetingCardCategorySetting.all.pluck(:category_id),:disabled.ne=>true).map{|c| [c.id.to_s, c.title]}.to_h
fields = fields.merge(GreetingCardCategorySetting.where(:category_id.in => cat_ids_map.keys()).map{|c| [cat_ids_map[c.category_id] , c.custom_fields.select{|k,v| !(k.start_with?('default@'))}.map{|k,v| ["custom@#{c.id}@#{k}",v['field'][locale]]}]}.to_h)
else
fields = GreetingCardCategorySetting.where(:category_id=>self.category_id).to_a.map{|c| [(Category.find(c.category_id).title rescue ''), c.custom_fields.map{|k,v| [k,v['field'][locale]]}]}.to_h
end
fields
end
end

View File

@ -0,0 +1,183 @@
class GreetingCardRecord
include Mongoid::Document
include Mongoid::Timestamps
# include ActiveModel::Validations
include OrbitCategory::Categorizable
include OrbitTag::Taggable
#https://stackoverflow.com/questions/378887/how-do-i-calculate-a-strings-width-in-ruby
mount_uploader :image, ImageUploader
# 欄位定義
field :serial_number, type: Integer
field :ip, type: String
field :title, type: String
field :name, type: String
field :sender_mail, type: String
field :recipients, type: String
field :greetings, type: String
field :sending_time, type: DateTime
field :situation, type: String, default: "is_email_not_confirmed" # 預設email未驗證
field :send_email, type: Integer, default: 0
field :email_id
field :verify_email_id
field :custom_values, type: Hash, default: {}
field :agree_show, type: Boolean, default: false
field :agree_usage, type: Boolean, default: false
field :is_hidden, type: Boolean
field :review_time, type: DateTime
belongs_to :reviewer, class_name: "MemberProfile", foreign_key: :reviewer_id
belongs_to :card_image, class_name: "GreetingCardImage", foreign_key: :card
has_many :greeting_card_status_histories
index({situation: 1, is_hidden: -1}, { unique: false, background: true })
attr_accessor :release_comment, :release_file, :user
before_create do
unless self.is_hidden
last_serial_number = GreetingCardSetting.update_last_serial_number
self.serial_number = last_serial_number
end
self.generate_image(false)
end
before_save :create_greeting_card_status_history
def self.get_fonts
["Arial", "Calibri", "Times New Roman", "微軟正黑體", "標楷體", "新細明體"]
end
def release_comment=(v)
@changed = true
@release_comment = v
end
def release_file=(v)
@changed = true
@release_file = v
end
def email
mail = Email.where(:id=>self.email_id).first
end
def verify_email
verify_email = Email.where(:id=>self.verify_email_id).first
end
def reviewer_emails
email_address = GreetingCardAdmin.or(:category_ids.in => [self.category_id, [], nil]).pluck(:email).select { |s| s.present? }.uniq rescue []
authorizes = Authorization.where(module_app_id: ModuleApp.where(key: 'greeting_card').first.id).to_a rescue []
authorizes.each do |a|
if a.category_id
next if a.category_id != self.category_id
end
if a.user_id
u = a.user
email_address << u.email if u && u.email
elsif a.role_id
email_address = email_address + MemberProfile.where(role_ids: a.role_id).pluck(:email).select { |s| s.present? }.uniq
else
a.destroy
end
end
email_address = email_address.flatten
email_address.uniq
end
def get_serial_number(last_serial_number=nil, display_length=nil)
if display_length.nil? && last_serial_number.nil?
can_update_shared_hash = (defined?(OrbitHelper::SharedHash) && OrbitHelper::SharedHash)
last_serial_number = (can_update_shared_hash ? OrbitHelper::SharedHash["greeting_card"][:last_serial_number] : GreetingCardSetting.pluck(:last_serial_number)[0].to_i)
end
display_length = [last_serial_number.to_s.length + 1, 4].max if display_length.nil?
display_format_string(self.serial_number, display_length) if self.serial_number
end
def display_format_string(num, str_length)
format("%0#{str_length}d", num)
end
def send_email?
self.send_email == 1
end
def new_history
@new_history
end
def generate_image(saved=true)
if self.card_image
layout_design = GreetingCardLayoutDesign.where(:category_id=> self.category_id.to_s).first
if layout_design.nil?
layout_design = GreetingCardLayoutDesign.where(:category_id=> nil).first
if layout_design.nil?
puts "Layout Design not exist!"
return false
end
end
data = {
title: self.title,
name: self.name,
sender_mail: self.sender_mail,
recipients: self.recipients,
greetings: self.greetings
}
layout_design.generate_image(self, self.card_image.file.path, data, saved)
end
end
def build_email(site, host_url, current_user, module_app, locale, email=nil, extra_data={})
if email.nil?
email = Email.new
email.save
self.email_id = email.id
self.save
end
group_mail = self.recipients
manager_emails = self.sender_mail
mail_sentdate = self.sending_time
mail_from = site.title_translations[locale]
mail_subject = mail_from + " #{I18n.t('greeting_card.new_card')}"
template_data = {
"greeting_card_record_id" => self.id.to_s,
"site_host" => host_url
}
template_data.merge!(extra_data) if extra_data.present?
email.update_attributes(
:mail_lang=> locale,
:create_user=> current_user,
:mail_sentdate=> mail_sentdate,
:module_app=> module_app,
:mail_to=>group_mail,
:mail_subject=>mail_subject,
:template=>'greeting_cards/email',
:template_data=> template_data,
:mail_reply_to => (manager_emails.empty? ? nil : manager_emails)
)
email
end
private
def create_greeting_card_status_history
if !@skip_callback && (changed? || @changed)
@new_history = GreetingCardStatusHistory.create(
greeting_card_record: self,
status: self.situation,
comment: @release_comment,
file: @release_file,
user: @user
)
else
@new_history = nil
end
end
end

View File

@ -0,0 +1,5 @@
class GreetingCardSafeEmail
include Mongoid::Document
field :email, type: String
index({email: 1}, { unique: false, background: true })
end

View File

@ -0,0 +1,295 @@
class GreetingCardSetting
include Mongoid::Document
include Mongoid::Timestamps
require_relative'concerns/greeting_card_setting_concern'
include ::GreetingCardSettingConcern
All_default_fields = ['greeting_card_category_id','name','sender_mail','recipients','greetings','card','sending_time','recaptcha','usage_rule','agree_show','agree_usage']
No_prompt_word = ['greeting_card_category_id', 'recaptcha']
No_required = ['agree_show']
Required = ['sender_mail', 'recipients','card']
field :last_ticket_key, type: Integer, default: 0
field :last_serial_number, type: Integer, default: 0
before_save do
@email_regex_enable_changed = self.email_regex_enable_changed?
@email_regex_changed = self.email_regex_changed?
@default_setting_prompt_word_changed = self.default_setting_prompt_word_changed?
@default_setting_field_name_changed = self.default_setting_field_name_changed?
true
end
after_save do
update_all_hash = {}
if @email_regex_enable_changed || @email_regex_changed
update_all_hash[:email_regex_enable] = self.email_regex_enable
update_all_hash[:email_regex] = self.email_regex
end
if @default_setting_prompt_word_changed
update_all_hash[:default_setting_prompt_word] = self.default_setting_prompt_word
end
if @default_setting_field_name_changed
update_all_hash[:default_setting_field_name] = self.default_setting_field_name
end
if update_all_hash.present?
GreetingCardCategorySetting.all.update_all(update_all_hash)
end
if @custom_fields_changed
GreetingCardCategorySetting.all.each do |a|
a.delete_customs_func(@delete_custom_fields)
a.update_need_check_customs(self.custom_fields)
end
end
end
def use_default
false
end
def category_id
nil
end
def get_attrs
attrs = self.attributes.clone
self.fields.each do |k, v|
if (v.options[:localize] rescue false)
attrs["#{k}_translations"] = attrs[k]
attrs.delete(k)
end
end
attrs.except("_type","_id","uid","updated_at", "created_at", "email_regex", "last_ticket_key", "default_setting_required", "last_serial_number")
end
def self.update_last_serial_number(last_serial_number=nil)
can_update_shared_hash = (defined?(OrbitHelper::SharedHash) && OrbitHelper::SharedHash)
if last_serial_number.nil?
last_serial_number = (can_update_shared_hash ? OrbitHelper::SharedHash["greeting_card"][:last_serial_number] : self.pluck(:last_serial_number)[0].to_i)
self.all.inc({'last_serial_number'=>1})
last_serial_number += 1
else
self.all.update_all(:last_serial_number=>last_serial_number)
end
if can_update_shared_hash
OrbitHelper::SharedHash["greeting_card"][:last_serial_number] = last_serial_number
end
last_serial_number
end
def self.get_sort_number_only(only_display=true, cat=nil, cat_is_record=false, override_sort_number=nil, use_cache=false)
greeting_card_setting = nil
if cat_is_record
greeting_card_setting = cat
is_cat_record = (cat.class == GreetingCardCategorySetting)
is_cat_record2 = is_cat_record || !(override_sort_number.nil?)
else
if cat.present?
greeting_card_setting = GreetingCardCategorySetting.enabled.where(:category_id=>cat).first
is_cat_record = true
end
greeting_card_setting = self.first if greeting_card_setting.nil?
greeting_card_setting = self.create() if greeting_card_setting.nil?
end
if only_display && use_cache
if override_sort_number
sort_number = override_sort_number
else
sort_number = greeting_card_setting.get_cache_sort_number
end
return sort_number
end
is_default_setting = (greeting_card_setting.class == self)
if override_sort_number.present?
sort_number = override_sort_number
else
sort_number = greeting_card_setting.sort_number
if greeting_card_setting.use_default
if greeting_card_setting.default_sort_number.blank?
sort_number = (is_default_setting ? sort_number : self.first.sort_number)
else
sort_number = greeting_card_setting.default_sort_number
end
override_sort_number = sort_number
greeting_card_setting = self.first
end
end
default_greeting_card_setting = is_default_setting ? greeting_card_setting : self.first
disp_fields = self::All_default_fields
disp_fields_infos = {}
locale = I18n.locale.to_s
if !only_display || greeting_card_setting.default_setting['title'] != false
disp_fields_infos['title'] = sort_number['title'].to_i
end
tmp = disp_fields[0...-4]
if only_display
tmp = tmp.select{|f| greeting_card_setting.default_setting[f]}
end
tmp.each do |f|
disp_fields_infos[f] = sort_number[f]
end
tmp_locales = I18n.available_locales.map{|l| l.to_s}
tmp_locales = [locale] + (tmp_locales - [locale])
greeting_card_setting.custom_fields.each do |k,v|
tmp_k = k
if !k.start_with?('default@')
prefix = is_cat_record ? "custom@#{cat.id}@" : 'default@'
tmp_k = "#{prefix}#{k}"
end
disp_fields_infos[tmp_k] = sort_number[tmp_k]
end
greeting_card_category_settings = []
if is_cat_record2
greeting_card_category_settings = []
else
greeting_card_category_settings = GreetingCardCategorySetting.custom_enabled.to_a
end
greeting_card_category_settings.each do |c|
category = Category.find(c.category_id) rescue nil
if category.nil?
c.destroy
next
end
c.custom_fields.each do |k,v|
next if k.start_with?('default@')
tmp_k = "custom@#{c.id}@#{k}"
cat_title = category.title rescue ""
disp_fields_infos[tmp_k] = sort_number[tmp_k]
end
end
tmp = disp_fields[-4..-1]
if only_display
tmp = tmp.select{|f| greeting_card_setting.default_setting[f] || f == 'usage_rule'}
end
tmp.each do |f|
disp_fields_infos[f] = sort_number[f]
end
max_sort_number = disp_fields_infos.values.map{|v| v}.compact.max
if max_sort_number
if !use_cache || (is_default_setting && override_sort_number.nil?)
max_sort_number = max_sort_number + 1
disp_fields_infos.each_with_index do |(k,v), i|
if v.blank?
disp_fields_infos[k] = max_sort_number + i
end
end
end
disp_fields_infos = disp_fields_infos.sort_by {|_key, value| value}.to_h
end
disp_fields_infos
end
def self.get_disp_fields_infos(only_display=true, cat=nil, cat_is_record=false, override_sort_number=nil, use_cache=false)
greeting_card_setting = nil
if cat_is_record
greeting_card_setting = cat
is_cat_record = (cat.class == GreetingCardCategorySetting)
is_cat_record2 = is_cat_record || !(override_sort_number.nil?)
else
if cat.present?
greeting_card_setting = GreetingCardCategorySetting.enabled.where(:category_id=>cat).first
is_cat_record = true
end
greeting_card_setting = self.first if greeting_card_setting.nil?
greeting_card_setting = self.create() if greeting_card_setting.nil?
end
is_default_setting = (greeting_card_setting.class == self)
sort_number = nil
if only_display && use_cache
if override_sort_number
sort_number = override_sort_number
else
sort_number = greeting_card_setting.get_cache_sort_number
end
else
use_cache = false
sort_number = greeting_card_setting.sort_number
if override_sort_number.present?
sort_number = override_sort_number
elsif greeting_card_setting.use_default
if greeting_card_setting.default_sort_number.blank?
sort_number = (is_default_setting ? sort_number : self.first.sort_number)
else
sort_number = greeting_card_setting.default_sort_number
end
override_sort_number = sort_number
greeting_card_setting = self.first
end
end
default_greeting_card_setting = is_default_setting ? greeting_card_setting : self.first
disp_fields = self::All_default_fields
disp_fields_infos = {}
locale = I18n.locale.to_s
if !only_display || greeting_card_setting.default_setting['title'] != false
disp_fields_infos['title'] = {"trans"=>greeting_card_setting.field_name('title'), "sort_number"=>sort_number['title'].to_i}
end
tmp = disp_fields[0...-4]
if only_display
tmp = tmp.select{|f| greeting_card_setting.default_setting[f]}
end
tmp.each do |f|
disp_fields_infos[f] = {"trans"=>default_greeting_card_setting.field_name(f,locale),"sort_number"=>sort_number[f]}
end
tmp_locales = I18n.available_locales.map{|l| l.to_s}
tmp_locales = [locale] + (tmp_locales - [locale])
greeting_card_setting.custom_fields.each do |k,v|
trans = v["field"]
tmp_locales.each do |l|
if trans[l].present?
trans = trans[l]
break
end
end
next if trans.class != String
tmp_k = k
if !k.start_with?('default@')
prefix = is_cat_record ? "custom@#{cat.id}@" : 'default@'
tmp_k = "#{prefix}#{k}"
end
disp_fields_infos[tmp_k] = {"trans"=>trans,"sort_number"=>sort_number[tmp_k],"key"=>k,"type"=>v["type"],"options"=>v["options"],"instructions"=>v["instructions"]}
end
greeting_card_category_settings = []
if is_cat_record2
greeting_card_category_settings = []
else
greeting_card_category_settings = GreetingCardCategorySetting.custom_enabled.to_a
end
greeting_card_category_settings.each do |c|
category = Category.find(c.category_id) rescue nil
if category.nil?
c.destroy
next
end
c.custom_fields.each do |k,v|
trans = v["field"]
tmp_locales.each do |l|
if trans[l].present?
trans = trans[l]
break
end
end
next if trans.class != String
next if k.start_with?('default@')
tmp_k = "custom@#{c.id}@#{k}"
cat_title = category.title rescue ""
disp_fields_infos[tmp_k] = {"trans"=>"#{cat_title}-#{trans}","sort_number"=>sort_number[tmp_k],"key"=>k,"type"=>v["type"],"options"=>v["options"],"instructions"=>v["instructions"]}
end
end
tmp = disp_fields[-4..-1]
if only_display
tmp = tmp.select{|f| greeting_card_setting.default_setting[f] || f == 'usage_rule'}
end
tmp.each do |f|
disp_fields_infos[f] = {"trans"=>default_greeting_card_setting.field_name(f,locale),"sort_number"=>sort_number[f]}
end
max_sort_number = disp_fields_infos.values.map{|h| h["sort_number"]}.compact.max
if max_sort_number
if !use_cache || (is_default_setting && override_sort_number.nil?)
max_sort_number = max_sort_number + 1
disp_fields_infos.each_with_index do |(k,h), i|
if h["sort_number"].blank?
h["sort_number"] = max_sort_number + i
end
end
end
disp_fields_infos = disp_fields_infos.sort_by {|_key, value| value["sort_number"]}.to_h
end
disp_fields_infos
end
end

View File

@ -0,0 +1,5 @@
class GreetingCardSettingIndex
include Mongoid::Document
include Mongoid::Timestamps
field :key,type: Integer,default: 0
end

View File

@ -0,0 +1,17 @@
class GreetingCardStatusHistory
include Mongoid::Document
include Mongoid::Timestamps
field :status, type: String
field :comment, type: String
belongs_to :user
belongs_to :greeting_card_record
mount_uploader :file, AssetUploader
def modified_by_name
if user.present? && user.member_profile.present?
user.member_profile.name
end
end
end

View File

@ -0,0 +1,46 @@
class GreetingCardTicketStatus
include Mongoid::Document
include Mongoid::Timestamps
DefaultKeys = ["is_email_not_confirmed" , "is_waiting", "is_processed", "is_referral", "is_published"]
field :title, type: String, localize: true
field :is_default, type: Boolean, default: false # if true => cannot delete
field :key, type: String
before_create do
if self.key.blank?
can_update_shared_hash = (defined?(OrbitHelper::SharedHash) && OrbitHelper::SharedHash)
last_ticket_key = can_update_shared_hash ? OrbitHelper::SharedHash["greeting_card"][:last_ticket_key] : GreetingCardSetting.pluck(:last_ticket_key)[0].to_i
self.key = last_ticket_key.to_s
GreetingCardSetting.all.inc({'last_ticket_key'=>1})
if can_update_shared_hash
OrbitHelper::SharedHash["greeting_card"][:last_ticket_key] = last_ticket_key + 1
end
end
true
end
after_destroy do
# can_update_shared_hash = (defined?(OrbitHelper::SharedHash) && OrbitHelper::SharedHash)
# GreetingCardSetting.all.inc({'last_ticket_key'=>-1})
# if can_update_shared_hash
# OrbitHelper::SharedHash["greeting_card"][:last_ticket_key] = OrbitHelper::SharedHash["greeting_card"][:last_ticket_key] - 1
# end
end
def title
tmp = super
if self.is_default
tmp = I18n.t("greeting_card.#{self.key}") if tmp.blank?
end
tmp
end
def get_title_translations(locales=nil)
locales = I18n.available_locales if locales.nil?
trans = {}
locales.each do |locale|
trans[locale] = I18n.with_locale(locale){self.title}
end
trans
end
def self.default_sorting
self.all.sort_by{|a| [a.is_default ? 0 : 1, DefaultKeys.index(a.key)] }
end
end

View File

@ -0,0 +1,71 @@
# encoding: utf-8
module CarrierWave
module Uploader
module Versions
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
end
end
class GreetingCardImageUploader < CarrierWave::Uploader::Base
# Include RMagick or ImageScience support:
# include CarrierWave::RMagick
# include CarrierWave::ImageScience
include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
# storage :file
# storage :s3
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def get_org_url
if have_crop?
model.file.resized.url
else
model.file.url
end
end
def fix_exif_rotation
manipulate! do |img|
img.tap(&:auto_orient)
end
end
process :optimize
version :thumb do
process :pad_process => [200,200]
end
version :theater do
process :limit_process => [1920, 1080]
end
version :mobile do
process :limit_process => [1152, 768]
end
def optimize (*arg)
manipulate! do |img|
return img unless img.mime_type.match /image\/jpeg/
img.strip
img.combine_options do |c|
c.quality "90"
c.depth "24"
c.interlace "plane"
end
img
end
end
def limit_process(w,h)
resize_to_limit(w,h)
end
def pad_process (w,h)
resize_and_pad(w, h, :transparent, 'Center')
end
end

View File

@ -0,0 +1,24 @@
<%
set_input_name_for_greeting_card('greeting_card_acknowledgement')
%>
<style type="text/css">
.tab-content{
display: none;
}
.tab-content.active{
display: block;
}
</style>
<div id="greeting_card-acknowledgements">
<%= form_for @greeting_card_acknowledgements, url: @url, html: { class: 'form-horizontal' } do |f| %>
<div class="control-group">
<%= f.label :content, t('greeting_card.acknowledgements'), class: 'control-label' %>
<%= multiple_lang_tag_for_greeting_card(nil,'text_area','content',@greeting_card_acknowledgements.content,{:class=>'ckeditor',placeholder: t('greeting_card.acknowledgements'),rows:10},nil,{'class' => 'controls','style'=>'display: flex;flex-direction: column-reverse;'})
%>
</div>
<div class="form-actions">
<%= f.submit t('submit'), class: 'btn btn-primary' %>
<%= f.button t('cancel'), type: 'reset', class: 'btn' %>
</div>
<% end %>
</div>

View File

@ -0,0 +1,42 @@
<h2><%= @greeting_card_admin.new_record? ? t(:add) : t(:edit) %></h2>
<div id="widget-title">
<div class="control-group">
<%= f.label :email, class: 'control-label' %>
<div class="controls">
<%= f.text_field :email, class: 'input-xxlarge', data: {"fv-validation" => "required;check_email;", "fv-messages" => "必填欄位;Email不正確;"} %>
</div>
</div>
<div class="control-group">
<%= f.label :category, class: 'control-label' %>
<div class="controls">
<label>
<%= check_box f.object_name,"category_ids", {checked: f.object.category_ids.empty?, multiple: true}, "", nil %>
<%= t(:all) %>
</label>
<% @module_app.categories.each do |category| %>
<label>
<%= check_box f.object_name,"category_ids", {checked: f.object.category_ids.include?(category.id), multiple: true}, category.id, nil %>
<%= category.title %>
</label>
<% end %>
</div>
</div>
</div>
<div class="form-actions">
<%= f.submit t(:submit), class: 'btn btn-primary' %>
</div>
<script type='text/javascript'>
$(function(){
var fv = new FormValidator($("#greeting_card_admin_email"));
fv.validate_functions.check_email = function(value){
reg = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9])+$/;
if (reg.test(value)) {
return true;
}else{
return false;
}
}
})
</script>

View File

@ -0,0 +1,32 @@
<%= render 'layouts/delete_modal', delete_options: @delete_options %>
<table class="table main-list">
<thead>
<tr class="sort-header">
<% @table_fields.each do |f| %>
<%= thead(f) %>
<% end %>
</tr>
</thead>
<tbody>
<% @greeting_card_admins.each do |a| %>
<tr>
<td>
<%= a.email %>
<div class="quick-edit">
<ul class="nav nav-pills">
<% if can_edit_or_delete?(a) %>
<li><a href="/admin/greeting_card_admins/<%=a.id.to_s%>/edit"><%= t(:edit) %></a></li>
<li><a href="#" class="delete text-error" rel="/admin/greeting_card_admins/<%=a.id.to_s%>"><%= t(:delete_) %></a></li>
<% end %>
</ul>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
<%= form_for @greeting_card_admin, url: @url, html: { class: 'form-horizontal' } do |f| %>
<%= render :partial => 'greeting_card_admin_form', locals: {f: f} %>
<% end %>

View File

@ -0,0 +1,33 @@
<%= render 'layouts/delete_modal', delete_options: @delete_options %>
<table class="table main-list">
<thead>
<tr class="sort-header">
<% @table_fields.each do |f| %>
<%= thead(f) %>
<% end %>
</tr>
</thead>
<tbody>
<% @greeting_card_admins.each do |a| %>
<tr>
<td>
<%= a.email %>
<div class="quick-edit">
<ul class="nav nav-pills">
<% if can_edit_or_delete?(a) %>
<li><a href="/admin/greeting_card_admins/<%=a.id.to_s%>/edit"><%= t(:edit) %></a></li>
<li><a href="#" class="delete text-error" rel="/admin/greeting_card_admins/<%=a.id.to_s%>"><%= t(:delete_) %></a></li>
<% end %>
</ul>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
<%= javascript_include_tag 'validator' %>
<%= form_for @greeting_card_admin, url: admin_greeting_card_admins_path, html: {class: "form-horizontal main-forms previewable"} do |f| %>
<%= render :partial => 'greeting_card_admin_form', locals: {f: f} %>
<% end %>

View File

@ -0,0 +1,83 @@
<%#= javascript_include_tag "lib/bootstrap-datetimepicker" %>
<%#= javascript_include_tag "lib/datetimepicker/datetimepicker.js" %>
<div class="auto_send_setting">
<% id_postfix = f.object.category_id %>
<%
if @_idx.nil?
@_idx = 0
else
@_idx += 1
end
id_postfix += @_idx.to_s
%>
<div class="control-group">
<div class="control-label">
<label><%= t("greeting_card.automatically_send") %></label>
</div>
<div class="controls">
<%= f.check_box :automatically_send, {class: "automatically_send_enable toggle-check", title: t("greeting_card.enable"), "data-disabled": !(f.object.automatically_send), id: "automatically_send_#{id_postfix}"} %>
<div class="auto-send-block <%= 'hide' unless f.object.automatically_send %>">
<%= f.hidden_field_tag "#{f.object_name}[auto_send_date_type]", "-1" %>
<h5><%= t('mongoid.attributes.greeting_card_record.image') %></h5>
<div class="card_images_wrapper row-fluid">
<%
greeting_card_images = @default_greeting_card_setting.greeting_card_images.to_a
if f.object.class == GreetingCardCategorySetting
greeting_card_images += f.object.greeting_card_images.to_a
end
%>
<% greeting_card_images.each do |image| %>
<%
img_url = image.file.url
next if img_url.blank?
%>
<div class="col-md-4 span3">
<img src="<%= img_url %>\" title="<%= image.description %>" />
<%= f.radio_button :auto_send_image_id, image.id %>
</div>
<% end %>
</div>
<% f.object.class::DateTypes.each_with_index do |date_type, i| %>
<label class="radio inline"><%= f.radio_button :auto_send_date_type, i, {class: "auto_send_date_type idx_#{i}"} %><%= t("greeting_card.#{date_type}") %></label>
<% end %>
<%#= f.datetime_picker(:regular_date, no_label: true, new_record: f.object.new_record?, :class => "regular_date #{'hide' unless f.object.auto_send_date_type == 0}", 'id' => "regular_date_#{id_postfix}") %>
<div>
<%= f.text_field(:regular_date, :class => "regular_date #{'hide' unless f.object.auto_send_date_type == 0}", 'id' => "regular_date_#{id_postfix}") %>
</div>
<div>
<%= f.text_field :sender_mail, {placeholder: t('greeting_card.sender_mail')} %>
<h4><%= t('greeting_card._recipients') %></h4>
<div class="content-box">
<%= render partial: 'admin/member_selects/email_selection_box', locals: {field: "#{f.object_name}[recipient_ids][]", email_members: f.object.recipients, index: id_postfix, select_name: id_postfix} %>
</div>
</div>
</div>
</div>
</div>
<script>
$('.automatically_send_enable').on('change', function() {
$(this).parents('.auto_send_setting').find('.auto-send-block').toggleClass('hide');
});
$('.auto_send_date_type').on('change', function() {
var auto_send_block = $(this).parents('.auto-send-block'),
regular_date_block = auto_send_block.find('.regular_date');
if (auto_send_block.find('.auto_send_date_type.idx_0').prop('checked'))
{
regular_date_block.removeClass('hide');
}
else
{
regular_date_block.addClass('hide');
}
});
// Ensure tab-content not hide by css
$(document).on('show.bs.modal', '#member-filter', function(){
$(this).find('.tab-content').addClass('active');
});
$('#regular_date_<%=id_postfix%>').ui_datepicker({
minDate: new Date((new Date()).getFullYear(), 0, 1),
maxDate: new Date((new Date()).getFullYear(), 11, 31),
hideIfNoPrevNext: true,
dateFormat: 'mm/dd'});
</script>
</div>

View File

@ -0,0 +1,7 @@
<%
set_input_name_for_greeting_card('greeting_card_category_setting[custom_fields]')
%>
<%= form_for greeting_card_setting,method: 'post',url: category_setting_save_admin_greeting_cards_path ,html: { class: "form-horizontal fade-in active detail",id: greeting_card_setting.id} do |f| %>
<%= render partial: 'greeting_card_setting',locals:{greeting_card_setting: greeting_card_setting, f: f, submit_text: t('greeting_card.modify'), is_default: is_default} %>
<%= hidden_field_tag "category_id",greeting_card_setting.category_id %>
<% end %>

View File

@ -0,0 +1,11 @@
<%
if f.nil?
form_for greeting_card_setting, method: 'post', url: category_setting_save_admin_greeting_cards_path do |_f|
f = _f
end
end
%>
<div id="background_setting_form">
<%= render :partial=> "form_images", locals: {f: f, greeting_card_setting: greeting_card_setting, is_default: is_default} %>
<%= render :partial=> "auto_send_setting", locals: {f: f} %>
</div>

View File

@ -0,0 +1,27 @@
<div id="default_greeting_card_setting" class="<%= 'hide' if @is_hidden %>">
<div class="show_default_greeting_card_setting">
<%= render :partial => 'show_default_greeting_card_setting' %>
</div>
<div class="default_greeting_card_setting hide">
<%= form_for @default_greeting_card_setting, method: 'post',url: @url,html: { class: 'form-horizontal main-forms previewable fix_diabled_form' } do |f| %>
<% f.object_name = 'greeting_card_category_setting' %>
<%= hidden_field_tag "not_clone_attrs", true , :class=> 'not_clone_attrs' %>
<%= hidden_field_tag "category_id", @first_category_id , :class=> 'hidden_category_id' %>
<%
@has_email_regex = false
@has_switch_button = true
@default_custom_fields = true
%>
<%= render partial: 'greeting_card_setting',locals:{greeting_card_setting: @default_greeting_card_setting,f: f,submit_text: t('submit'), is_default: true } %>
<%
@has_switch_button = false
@default_custom_fields = false
%>
<% end %>
<script>
$('.fix_diabled_form').on('submit', function(){
$(this).find('input[disabled]').removeAttr('disabled');
})
</script>
</div>
</div>

View File

@ -0,0 +1,8 @@
<div class="quick-edit">
<ul class="nav nav-pills">
<% if is_editable %>
<!-- <li><a href="/<%= I18n.locale %>/admin/greeting_cards/<%=b.id.to_s%>/edit"><%= t(:edit) %></a></li> -->
<li><a href="#" class="delete text-error" rel="/admin/greeting_cards/<%=b.id.to_s%>"><%= t(:delete_) %></a></li>
<% end %>
</ul>
</div>

View File

@ -0,0 +1,231 @@
<%
greeting_card_setting = @greeting_card_setting
set_input_name_for_greeting_card('greeting_card_record')
%>
<% content_for :page_specific_css do %>
<%= stylesheet_link_tag "lib/main-forms" %>
<%= stylesheet_link_tag "lib/main-list" %>
<%= stylesheet_link_tag "custom_field" %>
<% end %>
<%# javascript_include_tag "lib/bootstrap-datetimepicker.js" %>
<%# javascript_include_tag "//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"%>
<%# javascript_include_tag "/assets/lib/jquery-ui-1.12.1/jquery-ui.min" %>
<%# javascript_include_tag "lib/module-area" %>
<%# javascript_include_tag "jquery.ui.datepicker.monthyearpicker" %>
<%# javascript_include_tag "lib/bootstrap-datetimepicker" %>
<style type="text/css">
.input-area tr td {
text-align: center;
}
.form-horizontal .control-label {
padding-top: 0;
}
</style>
<script type="text/javascript">
$(document).ready(function(){
$('input:file').change(function(e){
var fileName = e.target.files[0].name;
$(this).parents(".file-selector").eq(0).find('.filename').html(fileName);
})
$('input:file').each(function(i,v){
var filename = $(v).attr('value')
if (filename){
if ($(v).attr('data-image-src')){
$(v).parents(".file-selector").eq(0).find('.filename').html("<img src=\""+$(v).attr('data-image-src')+"\">"+filename);
}
else{
$(v).parents(".file-selector").eq(0).find('.filename').html("<a href=\""+$(v).attr('data-src')+"\">"+filename);
}
}
})
})
</script>
<div class="input-area">
<div class="row-fluid">
<div id="greeting_card-greeting_cards" class="span8">
<div class="row-fluid">
<div class="span4"><%= GreetingCardRecord.human_attribute_name(:name) %><%= @greeting_card_record.name %></div>
<div class="span4"><%= GreetingCardRecord.human_attribute_name(:mail) %><%= @greeting_card_record.mail %></div>
<div class="span4"><%= GreetingCardRecord.human_attribute_name(:phone) %><%= @greeting_card_record.phone %></div>
</div>
<% greeting_card_setting.custom_fields.each do |k,v| %>
<%
required_pattern = v['required']=='true' ? '*' : ''
%>
<div class="control-group">
<label class="control-label">
<%= required_pattern %>
<%= v['field'][I18n.locale] %>
</label>
<div class="controls">
<%= show_on_front(k,v,@greeting_card_record,true) %>
</div>
</div>
<% end %>
<div>
<div class="control-group">
<label class="control-label muted"><%= t('greeting_card.serial_number') %></label>
<div class="controls">
<%= @greeting_card_record.get_serial_number %>
</div>
</div>
<div class="control-group">
<label class="control-label muted"><%= t('greeting_card.ip') %></label>
<div class="controls">
<%= @greeting_card_record.ip %>
</div>
</div>
<div class="control-group">
<label class="control-label muted"><%= t('title') %></label>
<div class="controls">
<%= @greeting_card_record.title %>
</div>
</div>
<% if greeting_card_setting.default_setting['appointment'] %>
<div class="control-group">
<label class="control-label muted">
<%= GreetingCardRecord.human_attribute_name(:appointment) %>
</label>
<div class="controls">
<%= @greeting_card_record.appointment.strftime("%Y-%m-%d %H:%M") if @greeting_card_record.appointment %>
</div>
</div>
<% end %>
<% if !@greeting_card_record.comment.blank? %>
<div class="control-group">
<%= f.label :comment, class: "control-label muted" %>
<div class="controls">
<%= @greeting_card_record.comment %>
</div>
</div>
<% end %>
<div class="control-group">
<%= f.label :agree_show, class: "control-label muted" %>
<div class="controls">
<%= @greeting_card_record.agree_show ? t('greeting_card.yes') : t('greeting_card.no') %>
</div>
</div>
<div>
<%= f.label t('situation'), class: "control-label muted" %>
<div class="controls">
<%= f.select :situation, GreetingCardTicketStatus.default_sorting.map{|a| [a.title, a.key] } %>
</div>
</div>
<div class="control-group">
<label class="control-label muted"><%= t(:tags) %></label>
<%= select_tags(f, @module_app) %>
</div>
<div class="control-group">
<%= f.label :send_email, class: "control-label muted" %>
<div class="controls">
<label class="radio inline">
<%= f.radio_button :send_email, 1 %>
<%= t('greeting_card.system_Email') %>
</label>
<label class="radio inline">
<%= f.radio_button :send_email, 0 %>
<%= t('greeting_card.no') %>
</label>
<label class="radio inline">
<%= f.radio_button :send_email, 2 %>
<%= t('greeting_card.phone') %>
</label>
<label class="radio inline">
<%= f.radio_button :send_email, 3 %>
<%= t('greeting_card.fax') %>
</label>
<label class="radio inline">
<%= f.radio_button :send_email, 4 %>
<%= t('greeting_card.paper') %>
</label>
</div>
</div>
<div class="control-group">
<%= f.label :reply, class: "control-label muted" %>
<div class="controls">
<%= f.text_area :reply, rows: 10, style: 'max-width: 500px; width: 100%;' %>
</div>
</div>
<div class="control-group">
<label class="control-label muted"><%= f.label :comment %></label>
<div class="controls">
<%= f.text_area :release_comment, :id => "#{f.object_name}_comment" %>
</div>
</div>
<div class="control-group">
<label class="control-label muted"><%= t(:file_) %></label>
<div class="controls">
<%= f.file_field :release_file %>
</div>
</div>
</div>
</div>
<div class="span4">
<!-- 顯示歷史紀錄 -->
<div class="history-records">
<h3><%= t('history') %></h3>
<% if f.object.greeting_card_status_histories.present? %>
<% status_mapping = GreetingCardTicketStatus.default_sorting.map{|a| [a.key, a.title]}.to_h %>
<table class="table">
<thead>
<tr>
<th><%= t('status') %></th>
<th><%= t('greeting_card.modified_by') %></th>
<th><%= t('greeting_card.remark') %></th>
<th><%= t('greeting_card.attachment') %></th>
<th><%= t('greeting_card.updated_at') %></th>
</tr>
</thead>
<tbody>
<% f.object.greeting_card_status_histories.each do |greeting_card_status_history| %>
<tr>
<td>
<%= status_mapping[greeting_card_status_history.status] %>
</td>
<td>
<%= greeting_card_status_history.modified_by_name %>
</td>
<td>
<%= greeting_card_status_history.comment %>
</td>
<td>
<%= link_to(greeting_card_status_history[:file], greeting_card_status_history.file.url) if greeting_card_status_history.file.present? %>
</td>
<td>
<%= greeting_card_status_history.created_at.strftime("%Y-%m-%d %H:%M:%S") %>
</td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<p><%= t('no_history_records') %></p>
<% end %>
</div>
</div>
</div>
</div>
<%
cancel_href = url_for(:back)
if cancel_href == 'javascript:history.back()'
now_greeting_card_page = GreetingCardRecord.order_by(:id).map(&:id).map.with_index.select{|v,i| v==@greeting_card_record.id}[0][1] rescue nil
now_greeting_card_page = now_greeting_card_page.nil? ? 1 : ((now_greeting_card_page+1).to_f/10).ceil
cancel_href = "/#{I18n.locale}/admin/greeting_cards?page=#{now_greeting_card_page}"
end
%>
<div class="form-actions">
<%= f.submit t('submit'), class: 'btn btn-primary' %>
<%= link_to t('cancel'),cancel_href,title: t('cancel'),:class=> 'btn' %>
</div>

View File

@ -0,0 +1,48 @@
<!-- Images Upload -->
<div class="image_group">
<label class="checkbox inline btn btn-danger image-form-remove">
<% if f.object.new_record? %>
<span class="delete_form" title="<%= t(:delete_) %>">
X
</span>
<% else %>
<span class="remove_existing_record" title="<%= t(:remove) %>">
<%= f.hidden_field :id %>
<%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %>
X
</span>
<% end %>
</label>
<% form_image = f.object if form_image.nil? %>
<div class="control-group">
<label class="control-label muted"><%= t(:image) %></label>
<div class="controls">
<div class="fileupload fileupload-new clearfix <%= 'fileupload-edit' if form_image.file.present? %>" data-provides="fileupload">
<div class="fileupload-new thumbnail pull-left">
<% if form_image.file.file %>
<%= image_tag form_image.file %>
<% else %>
<img src="/assets/bulletin/AAAAAA" />
<% end %>
</div>
<div class="fileupload-preview fileupload-exists thumbnail pull-left"></div>
<span class="btn btn-file">
<span class="fileupload-new"><%= t(:select_image) %></span>
<span class="fileupload-exists"><%= t(:change) %></span>
<%= f.file_field :file %>
</span>
<a href="#" class="btn fileupload-exists" data-dismiss="fileupload"><%= t(:cancel) %></a>
</div>
</div>
</div>
<% @site_in_use_locales.each do |locale| %>
<%= f.fields_for :description_translations do |f| %>
<div class="control-group">
<label class="control-label muted" for="image_description_<%= locale.to_s %>"><%= t(:description) + " (#{t(locale.to_s)})" %></label>
<div class="controls">
<%= f.text_field locale, value: (form_image.description_translations[locale.to_s] rescue nil) %>
</div>
</div>
<% end %>
<% end %>
</div>

View File

@ -0,0 +1,29 @@
<div class="control-group background_upload_block">
<div class="control-label">
<label><%= t("greeting_card.card_background") %></label>
</div>
<div class="controls">
<div class="card_background_upload">
<% greeting_card_images = greeting_card_setting.greeting_card_images %>
<% if greeting_card_images.present? && !is_default %>
<div class="exist">
<% greeting_card_images.each_with_index do |greeting_card_image, i| %>
<%= f.fields_for :greeting_card_images_attributes, greeting_card_image do |f| %>
<%= f.fields_for i.to_s, greeting_card_image do |f| %>
<%= render :partial => 'form_image', :object => greeting_card_image, :locals => {:f => f, :i => i} %>
<% end %>
<% end %>
<% end %>
<hr>
</div>
<% end %>
<!-- Add -->
<div class="add-target">
</div>
<p class="add-btn controls">
<%= hidden_field_tag 'greeting_card_image_count', f.object.greeting_card_images.count %>
<a class="add_card_background trigger btn btn-small btn-primary"><i class="icons-plus"></i> <%= t(:add) %></a>
</p>
</div>
</div>
</div>

View File

@ -0,0 +1,499 @@
<% if !@include_css_js %>
<% @include_css_js = true %>
<% content_for :page_specific_css do %>
<%= stylesheet_link_tag "lib/main-forms" %>
<%= stylesheet_link_tag "lib/fileupload" %>
<%= stylesheet_link_tag "lib/main-list" %>
<% end %>
<% content_for :page_specific_javascript do %>
<%= javascript_include_tag "lib/bootstrap-fileupload" %>
<%= javascript_include_tag "lib/bootstrap-datetimepicker" %>
<%= javascript_include_tag "lib/datetimepicker/datetimepicker.js" %>
<%= javascript_include_tag "lib/file-type" %>
<%= javascript_include_tag "lib/module-area" %>
<%= javascript_include_tag "form" %>
<% end %>
<style type="text/css">
.layoutfix_table thead th {
text-align: center;
color: blueviolet;
}
.add_new_options,.prompt_word,.default_option,.time_setting_block{
display: none;
}
.add_new_options.active,.prompt_word.active,.default_option.active,.time_setting_block.active{
display: block;
}
.layoutfix_table tr td {
text-align: center;
}
.layoutfix_table tr.custom_field td:nth-child(1){
text-align: left;
}
.layoutfix_table thead th:last-child{
text-align: left;
padding-left: 10em;
}
.layoutfix_table td.center:last-child {
padding-left: 0;
}
.layoutfix_table td:last-child {
text-align: left;
padding-left: 2.5em;
}
.layoutfix_table td{
padding: 0.5em;
}
.tab-content{
display: none;
}
.tab-content.active{
display: block;
}
.tab-panel{
display: flex;
flex-wrap: wrap;
}
.center .tab-panel{
justify-content: start;
}
tr.custom_field, tbody.custom_field {
border: 0.1em solid #8e00ff;
}
tr.custom_field > td >div {
padding: 0.5em 0;
}
.layoutfix_table input[type=text] {
height: 30px;
}
.small_sort_number{
width: 4em;
}
.image_group{
border: 0.2em solid #333;
padding-top: 0;
}
.image_group:last-child {
margin-bottom: 1em;
}
.yes-label {
font-size: 1.3em;
padding-left: 0.6em;
}
.layoutfix_table select {
max-width: 100%;
}
.border {
padding: 0.5em 0;
border-top: 0.1em solid #099700;
}
</style>
<% end %>
<script type="text/javascript">
<%
option_multi_lang_tag = multiple_lang_tag_for_greeting_card(-1,'text_field','options][-2',nil,{ placeholder: t('greeting_card.option_name'), class: 'option_name_field', title: t('greeting_card.option_name'), data: {locale: I18n.locale.to_s}},create_delete_button_for_greeting_card('delete_added_select_option').html_safe+hidden_field_tag("#{get_input_name_for_greeting_card}[-1][options][-2][disabled]",nil,{'class' => 'disabled_field'}),{},true)
%>
function check_available_setting_block(ele){
var tmp = $(ele).val()
var parent_div = $(ele).parents('.custom_field').eq(0)
if (tmp == 'select' || tmp == 'radio_button' || tmp=='checkbox'){
parent_div.find('.add_new_options, .default_option').addClass('active');
}else{
parent_div.find('.add_new_options, .default_option').removeClass('active');
}
if (tmp == 'instructions'){
parent_div.find('.instructions_text_area').removeClass('hide');
parent_div.find('.prompt_word').removeClass('active');
}else{
parent_div.find('.instructions_text_area').addClass('hide');
parent_div.find('.prompt_word').addClass('active');
}
if (tmp == 'date'){
parent_div.find('.time_setting_block').addClass('active');
}else{
parent_div.find('.time_setting_block').removeClass('active');
}
}
function delete_field_func(ele){
$(ele).parents('tr').hide()
var all_delete_field = $('.delete_field').val()
all_delete_field = all_delete_field + ',' + $(ele).parents('tr').find('.key').val()
$('.delete_field').val(all_delete_field)
}
function add_new_options_for_field(ele,key){
var add_html = "<%= option_multi_lang_tag.inspect %>"
add_html = add_html.replace(/-1/g,key)
var parent_div = $(ele).parents('.add_new_options')
var tab_panel = parent_div.eq(0).find('.tab-panel')
var tab_panel_length = tab_panel.length
add_html = add_html.replace(/icons-list-2/g,'icons-list-3')
add_html = add_html.replace(/-2/g,tab_panel_length)
add_html = add_html.replace(/icons-list-3/g,'icons-list-2')
parent_div.find('input[type="button"]').eq(-1).before($('<div/>').html(add_html).text().slice(1,-2))
parent_div.siblings('.default_option').find('.default_option_select').append(new Option('',tab_panel_length));
}
function delete_added_select_option(ele){
var parent_div = $(ele).parents('.tab-panel');
var select_box = parent_div.parent().siblings('.default_option').find('>.default_option_select');
console.log(select_box)
var idx = parent_div.index();
var selected_val = parseInt(select_box.val());
if(selected_val == idx){
select_box.val('0');
}else if(selected_val > idx){
select_box.val(selected_val - 1);
}
var idx_offset = 1;
select_box.find('option').eq(idx+idx_offset).remove();
select_box.find('option').slice(idx+idx_offset).each(function(i,v){
$(v).attr('value', i + idx);
})
parent_div.remove();
}
$(document).on('input', '.option_name_field', function(){
var _this = $(this);
var idx_offset = 1;
var select_box = _this.parents('.add_new_options').siblings('.default_option').find('>.default_option_select');
if(_this.attr('name').match(new RegExp(select_box.data('locale')+'\\]$'))){
select_box.find('option').eq(_this.parents('.tab-panel:eq(0)').index()+idx_offset).text(_this.val());
}
})
</script>
<% tmp_get_input_name = get_input_name_for_greeting_card
form_type = tmp_get_input_name.split('[')[0]
set_input_name_for_greeting_card("#{form_type}")
%>
<fieldset>
<% if @has_switch_button %>
<div class="control-group">
<div class="control-label">
<a href="#" class="btn btn-danger cancel_edit" data-parent=".default_greeting_card_setting"><%= t("greeting_card.cancel_edit") %></a>
</div>
<div class="controls">
</div>
</div>
<% elsif form_type!= 'greeting_card_setting' %>
<div class="control-group">
<div class="control-label">
<a href="#" class="btn btn-success switch_to_default" data-id="<%=f.object.id%>" data-use-default="true"><%= t("greeting_card.use_default") %></a>
<%= hidden_field_tag "#{f.object_name}[use_default]", false %>
</div>
<div class="controls">
</div>
</div>
<% end %>
<!-- Images Module -->
<%= render :partial=> "form_images", locals: {f: f, greeting_card_setting: greeting_card_setting, is_default: is_default} %>
<% if !is_default %>
<!-- Auto Send Setting -->
<%= render :partial=> "auto_send_setting", locals: {f: f} %>
<% end %>
<div class="control-group">
<div class="control-label">
<label for="only_logged_in_users"><%= t("greeting_card.only_logged_in_users") %>:</label>
</div>
<div class="controls">
<%= f.check_box :only_logged_in_users, {:id=>"only_logged_in_users"} %><%= t("greeting_card.enable") %>
</div>
</div>
<% if @has_email_regex %>
<div class="control-group">
<div class="control-label">
<label for="greeting_card_email_regex"><%= t("greeting_card.email_regex") %>:</label>
</div>
<div class="controls">
<%= f.check_box :email_regex_enable, {:id=>"email_regex_enable"} %><%= t("greeting_card.enable") %>
<div style="clear: both;"></div>
<%= f.text_field :email_regex, {:id=>"greeting_card_email_regex", :style => "width: 30em;"}.merge(f.object.email_regex_enable ? {} : {:disabled=>"disabled"}) %>
</div>
</div>
<div class="control-group">
<div class="control-label">
<label for="greeting_card_email_regex"><%= t("greeting_card.validation_email_content") %>:</label>
</div>
<div class="controls">
<label class="pull-left" id="<%= "#{f.object_name}_validate_enable" %>"><%= f.check_box :validate_enable %><%= t('greeting_card.enable') %></label>
<label id="<%= "#{f.object_name}_must_verify_email" %>"><%= f.check_box :must_verify_email %><%= t('greeting_card.must_verify_email') %></label>
<div style="clear: both;"></div>
<%= multiple_lang_tag_for_greeting_card(
nil,
'text_area',
'validation_email_content_translations',
f.object.validation_email_content_translations,
{
class: 'ckeditor'
}) %>
</div>
</div>
<% else %>
<div class="control-group">
<div class="control-label">
<%= t("greeting_card.email_regex") %>:
</div>
<div class="controls">
<%= check_box_tag :email_regex_enable, @default_greeting_card_setting.email_regex_enable , @default_greeting_card_setting.email_regex_enable , {:id=>"",:disabled=>'disabled'} %><%= t("greeting_card.enable") %>
<div style="clear: both;"></div>
<div class="show_field">
<%= @default_greeting_card_setting.email_regex %>
</div>
</div>
</div>
<div class="control-group">
<div class="control-label">
<label for="greeting_card_email_regex"><%= t("greeting_card.validation_email_content") %>:</label>
</div>
<div class="controls">
<label class="pull-left" id="<%= "#{f.object_name}_validate_enable" %>"><%= f.check_box :validate_enable %><%= t('greeting_card.enable') %></label>
<label id="<%= "#{f.object_name}_must_verify_email" %>"><%= f.check_box :must_verify_email %><%= t('greeting_card.must_verify_email') %></label>
<%= multiple_lang_tag_for_greeting_card(
nil,
'text_area',
'validation_email_content_translations',
f.object.validation_email_content_translations,
{
class: 'ckeditor'
}) %>
</div>
</div>
<% end %>
<script>
if (!window.custom_js_inited)
{
window.custom_js_inited = true;
$(document).on('click', '.add_card_background', function(){
var new_id = $(this).prev().attr('value');
var old_id = new RegExp("new_greeting_card_images", "g");
var on = $('.language-nav li.active').index();
var le = $(this).parent('.add-btn').prev('.add-target').children('.start-line').length;
$(this).prev().attr('value', parseInt(new_id) + 1);
$(this).parent().siblings('.add-target').append(("<%= escape_javascript(add_attribute 'form_image', f, :greeting_card_images) %>").replace(old_id, new_id));
$(this).parent('.add-btn').prev('.add-target').children('.start-line').eq(le).children('.input-append').find('.tab-content').each(function() {
$(this).children('.tab-pane').eq(on).addClass('in active').siblings().removeClass('in active');
});
});
$(document).on('click', '#email_regex_enable', function(){
if($(this).prop("checked")){
$("#greeting_card_email_regex").removeAttr("disabled");
}else{
$("#greeting_card_email_regex").attr("disabled","disabled");
}
})
}
</script>
<table class="table layoutfix_table">
<thead>
<tr>
<th>
<%= t('greeting_card.field') %>
</th>
<th>
<%= t('greeting_card.whether_open') %>
</th>
<% if form_type=='greeting_card_setting' %>
<th>
<%= t('greeting_card.field_name') %>
</th>
<th>
<%= t('greeting_card.prompt_word') %>
</th>
<% end %>
<th>
<%= t('greeting_card.required') %>
</th>
</tr>
</thead>
<tbody>
<% locale = I18n.locale.to_s %>
<%
default_setting = greeting_card_setting.default_setting
if default_setting.keys[0].to_s != 'title'
default_setting = {title: true}.merge(default_setting)
end
%>
<% default_setting.each do |k,v| %>
<tr>
<td>
<%= tmp = (form_type=='greeting_card_setting' ? greeting_card_setting.default_field_name(k,locale, true) : @default_greeting_card_setting.field_name(k,locale, true)) %>
</td>
<td>
<%= select_tag "#{get_input_name_for_greeting_card}[default_setting][#{k}]",options_for_select([[t('yes'),'true'],[t('no'),false]],v) %>
</td>
<% if form_type=='greeting_card_setting' %>
<td class="center">
<%= multiple_lang_tag_for_greeting_card(nil,'text_field',"default_setting_field_name][#{k}",greeting_card_setting.field_name_translations(k),{placeholder: tmp}) %>
</td>
<td class="center">
<% if GreetingCardSetting::No_prompt_word.include?(k) %>
<%= t('greeting_card.the_same_as_field_name') %>
<% else %>
<%= multiple_lang_tag_for_greeting_card(nil,'text_field',"default_setting_prompt_word][#{k}",greeting_card_setting.prompt_word_translations(k),{placeholder: tmp}) %>
<% end %>
</td>
<% end %>
<% v = greeting_card_setting.default_setting_required[k] %>
<td>
<% if GreetingCardSetting::Required.include?(k) %>
<div class="yes-label"><%= t('yes') %></div>
<% else %>
<%= select_tag "#{get_input_name_for_greeting_card}[default_setting_required][#{k}]",options_for_select([[t('yes'),'true'],[t('no'),false]],v) %>
<% end %>
</td>
</tr>
<% end %>
<% set_input_name_for_greeting_card(tmp_get_input_name) %>
<tr>
<td>
<%= t("greeting_card.usage_rule") %>
</td>
<td colspan="2">
<%= f.text_area "usage_rule",class: 'ckeditor' %>
</td>
</tr>
<% if @default_custom_fields %>
<% greeting_card_setting.custom_fields.each do |k,v| %>
<%= custom_field_block_for_greeting_card("default@#{k}",v, false, (hidden_field_tag("#{f.object_name}[agree_customs][]", k))).html_safe %>
<% end %>
<%= f.hidden_field :use_default, :value => false %>
<% else %>
<% greeting_card_setting.custom_fields.each do |k,v| %>
<%= custom_field_block_for_greeting_card(k,v).html_safe %>
<% end %>
<% end %>
<tr class="add_field">
<td colspan="2" style="text-align: center;">
<input class="btn btn-info" type="button" value="<%= t('add')%>" onclick="add_new_field(this)">
</td>
</tr>
<tr>
<td colspan="2" style="text-align: center;">
<%= hidden_field_tag :delete_field, nil,{'class'=> 'delete_field' } %>
<% if !greeting_card_setting.new_record? %>
<%= f.hidden_field :id, value: greeting_card_setting.id %>
<% end %>
<input class="btn btn-primary" type="submit" value="<%= submit_text %>">
</td>
</tr>
<% has_need_check_customs = (greeting_card_setting.class == GreetingCardCategorySetting && (greeting_card_setting.need_check_customs.count + greeting_card_setting.reject_customs.count) != 0)
org_hide = greeting_card_setting.class == GreetingCardCategorySetting ? (greeting_card_setting.need_check_customs.count == 0) : true;
%>
<% if has_need_check_customs %>
<tr class="greeting_card_setting_clone_fields">
<td colspan="2" style="text-align: center;">
<%= t('greeting_card.default_custom_fields') %>
</td>
<td>
<span style="margin-right: 1em; font-weight: bold;" class="<%='hide' if greeting_card_setting.reject_customs.count == 0 %>" id="display_discard_fields_block">
<input type="checkbox" id="display_discard_fields" style="float: left;">
<label for="display_discard_fields" style="float: left;"><%= t('greeting_card.display_discard_fields') %></label>
</span>
<a class="apply_default_customs btn btn-success <%= 'hide' if org_hide %>" title="<%=t('greeting_card.apply_all')%>" data-category="<%=greeting_card_setting.category_id%>" data-apply-all="true"><%=t('greeting_card.apply_all')%></a>
<a class="discard_default_customs btn btn-danger <%= 'hide' if org_hide %>" title="<%=t('greeting_card.discard_changes')%>" data-category="<%=greeting_card_setting.category_id%>" data-apply-all="true"><%=t('greeting_card.discard_changes')%></a>
</td>
</tr>
<% end %>
</tbody>
<% if has_need_check_customs %>
<% (greeting_card_setting.need_check_customs + greeting_card_setting.reject_customs).sort_by{|k| k.to_i}.each do |k| %>
<% if greeting_card_setting.reject_customs.include?(k) %>
<% other_first_rows = "<tr><td colspan=\"2\"><a class=\"apply_default_customs btn btn-success\" title=\"#{t('greeting_card.apply')}\" data-category=\"#{greeting_card_setting.category_id}\" data-apply-field=\"#{k}\">#{t('greeting_card.apply')}</a></td></tr>" %>
<%= custom_field_block_for_greeting_card(k, @default_greeting_card_setting.custom_fields[k], true, other_first_rows, "discard_fields hide").html_safe %>
<% else %>
<% other_first_rows = "<tr><td colspan=\"2\"><a class=\"apply_default_customs btn btn-success\" title=\"#{t('greeting_card.apply')}\" data-category=\"#{greeting_card_setting.category_id}\" data-apply-field=\"#{k}\">#{t('greeting_card.apply')}</a><a class=\"discard_default_customs btn btn-danger\" title=\"#{t('greeting_card.discard')}\" data-category=\"#{greeting_card_setting.category_id}\" data-apply-field=\"#{k}\">#{t('greeting_card.discard')}</a></td></tr>" %>
<%= custom_field_block_for_greeting_card(k, @default_greeting_card_setting.custom_fields[k], true, other_first_rows).html_safe %>
<% end %>
<% end %>
<script>
var show_customs_count = <%= greeting_card_setting.need_check_customs.count %>;
$(".apply_default_customs, .discard_default_customs").off('click').on('click', function(){
var _this = $(this);
var category = _this.data('category');
var apply_all = _this.attr('data-apply-all') == 'true';
var apply_fields = _this.data('apply-field');
apply_fields = apply_fields ? [apply_fields] : [];
var agree = _this.hasClass('apply_default_customs');
var hint_text = "";
if(agree){
hint_text = '<%=t("greeting_card.are_you_sure_to_apply")%>';
}else{
hint_text = '<%=t("greeting_card.are_you_sure_to_discard")%>';
}
var display_discard_fields = $('#display_discard_fields').prop('checked');
if(window.confirm(hint_text)){
$.post('<%=apply_default_custom_fields_admin_greeting_cards_path%>', {
category: category, apply_all: apply_all,
apply_fields: apply_fields, agree: agree,
include_reject: display_discard_fields
}).done(function(data){
var table = _this.parents('table.layoutfix_table');
if(data["success"]){
if(!agree){
$('#display_discard_fields_block').removeClass('hide');
}
table.find('tr.add_field').before(data['html']);
if(apply_all){
show_customs_count = 0;
var find_target = 'tbody.custom_field';
if(!display_discard_fields){
find_target += ":not(.discard_default_customs)";
}
if(agree){
table.find(find_target).remove();
_this.parents('tr.greeting_card_setting_clone_fields').remove();
}else{
var tmp = 'discard_fields';
if(!display_discard_fields){
tmp += ' hide';
}
table.find(find_target).addClass(tmp);
table.find('.discard_default_customs').remove();
}
}else{
show_customs_count -= 1;
if(agree){
_this.parents('tbody.custom_field').remove();
if(table.find('tbody.custom_field').length == 0)
table.find('.greeting_card_setting_clone_fields').remove();
}else{
var tmp = 'discard_fields';
if(!display_discard_fields){
tmp += ' hide';
}
_this.parents('tbody.custom_field').addClass(tmp);
_this.remove();
}
}
}
})
}
})
$('#display_discard_fields').off('click').on('click', function(){
if($(this).prop('checked')){
$('tbody.custom_field.discard_fields').removeClass('hide');
var can_display = '.apply_default_customs';
if(show_customs_count > 0){
can_display += ', .discard_default_customs';
}
$('tr.greeting_card_setting_clone_fields').find(can_display).removeClass('hide');
}else{
$('tbody.custom_field.discard_fields').addClass('hide');
if(show_customs_count > 0){
$('tr.greeting_card_setting_clone_fields').find('.apply_default_customs, .discard_default_customs').removeClass('hide');
}else{
$('tr.greeting_card_setting_clone_fields').find('.apply_default_customs, .discard_default_customs').addClass('hide');
}
}
})
</script>
<% end %>
</table>
<style>
.layoutfix_table{
table-layout: fixed;
}
.layoutfix_table th,.layoutfix_table td {
word-wrap: break-word;
}
</style>
</fieldset>

View File

@ -0,0 +1,256 @@
<script>
if(document.querySelectorAll("#orbit-bar").length==0) location.reload();
if( Array.prototype.delete == undefined ){
Array.prototype.delete = function(v){
var idx = this.indexOf(v);
if(idx != -1){
return this.splice(idx, 1)[0];
}else{
return null;
}
}
}
function reload_tbody(url){
console.log("done");
if(url == undefined){
url = window.location.href;
}
$.get(url).done(function(data){
$('#index_table tbody').replaceWith($(data).find('tbody'));
if(window.scroll_top){
$(window).scrollTop(window.scroll_top);
}
window.batch_select_greeting_cards = [];
$(".delete_greeting_cards_btn, .batch_modify_status_btn").addClass('hide');
});
}
$(document).on("click", ".batch_select", function(){
var that = $(this);
var id = that.data("id");
if(window.batch_select_greeting_cards == undefined){
window.batch_select_greeting_cards = [];
}
if(that.prop("checked")){
window.batch_select_greeting_cards.push(id);
}else{
window.batch_select_greeting_cards.delete(id);
}
if(window.batch_select_greeting_cards.length == 0){
$(".delete_greeting_cards_btn, .batch_modify_status_btn").addClass('hide');
}else{
$(".delete_greeting_cards_btn, .batch_modify_status_btn").removeClass('hide');
}
})
function batch_delete_greeting_cards(){
if(!window.batch_select_greeting_cards || window.batch_select_greeting_cards.length == 0){
return null;
}
var data = new FormData();
var csrf_token = document
.querySelector("meta[name='csrf-token']")
.getAttribute("content");
var csrf_param = document
.querySelector("meta[name='csrf-param']")
.getAttribute("content");
if (csrf_token && csrf_param) {
data.append(csrf_param, csrf_token);
}
window.batch_select_greeting_cards.forEach(function(val){
data.append('ids[]', val);
});
$.ajax({
url: "<%=delete_admin_greeting_cards_path%>",
method: 'DELETE',
data: data,
headers: {
// 'Content-Type': 'multipart/form-data',
// 使用 multipart/form-data 在此不需要設定 Content-Type。
'X-Requested-With': 'XMLHttpRequest',
'Authorization': `Bearer ${ csrf_token }`,
},
contentType: false, //required
processData: false, // required
statusCode: {
204: reload_tbody,
403: function() {
alert( "Delete failed!" );
}
}
})
}
function batch_edit_status_greeting_cards(){
if($('#dialog-batch-modify-status').length == 0){
var li_statuses = "";
<% GreetingCardTicketStatus.all.each do |s| %>
li_statuses += "<li style=\"list-style: none;\"><label><input type=\"radio\" name=\"status_key\" value=\"<%=s.key%>\"><%=s.title%></label></li>"
<% end%>
$("#main-wrap").before("<div id='dialog-batch-modify-status' title='"+"<%= t('greeting_card.batch_modify_status') %>'>"+
"<div style='clear:both;'></div><div><ul>"+ li_statuses +"</ul></div>"+
"</div>");
}else{
$('[name="status_key"]').prop('checked',false);
}
$( "#dialog-batch-modify-status" ).dialog({
resizable: true,
minHeight: 100,
maxHeight: 400,
modal: true,
buttons: {
"<%= t(:confirm) %>": function(){
var status_key = $('[name="status_key"]:checked').val();
if(status_key){
if(window.confirm("<%=t(:sure?)%>")){
var data = new FormData();
var csrf_token = document
.querySelector("meta[name='csrf-token']")
.getAttribute("content");
var csrf_param = document
.querySelector("meta[name='csrf-param']")
.getAttribute("content");
if (csrf_token && csrf_param) {
data.append(csrf_param, csrf_token);
}
window.batch_select_greeting_cards.forEach(function(val){
data.append('ids[]', val);
});
data.append("status_key", status_key);
$.ajax({
url: "<%=batch_modify_status_admin_greeting_cards_path%>",
method: 'POST',
data: data,
headers: {
// 'Content-Type': 'multipart/form-data',
// 使用 multipart/form-data 在此不需要設定 Content-Type。
'X-Requested-With': 'XMLHttpRequest',
'Authorization': `Bearer ${ csrf_token }`,
},
contentType: false, //required
processData: false, // required
statusCode: {
204: reload_tbody,
403: function() {
alert( "Edit status failed!" );
}
}
})
}
}
$( this ).dialog( "close" );
},
"<%= t(:cancel) %>": function() {
$( this ).dialog( "close" );
$( this ).remove();
}
}
});
}
$(document).on("click", ".delete_greeting_cards_btn", function(){
if(window.confirm("<%=t(:sure?)%>")){
if(window.confirm("<%=t(:sure?)%>")){
batch_delete_greeting_cards();
}
}
})
$(document).on("click", ".batch_modify_status_btn", function(){
batch_edit_status_greeting_cards();
})
</script>
<div>
<form>
<h4><%= t(:category) %></h4>
<select name="category" id="submit_when_change">
<% @cats_relations.each do |id, title| %>
<option value="<%=id%>" <%= @category_id == id ? 'selected' : '' %>><%= title %></option>
<% end %>
</select>
</form>
</div>
<table class="table main-list">
<thead>
<tr class="sort-header">
<th style="width: 1em;"></th>
<% @table_fields.each do |f| %>
<%= greeting_card_thead(f, @greeting_card_setting.field_name(f)) %>
<% end %>
<% @table_ext_fields.each do |f, v| %>
<%= greeting_card_thead(f, v['field'][I18n.locale.to_s]) %>
<% end %>
</tr>
</thead>
<tbody>
<%
situation_class_relation = {
"is_waiting"=>"label-important",
"is_processed"=>"label-warning",
"is_published"=>"label-success"
}
situation_trans = GreetingCardTicketStatus.all.map{|a| [a.key, a.title]}.to_h
last_serial_number = @greeting_card_setting.last_serial_number
display_length = [last_serial_number.to_s.length + 1, 4].max
edit_box_display_index = @table_fields.count > 3 ? 2 : @table_fields.count
%>
<% @greeting_cards.each do |b| %>
<tr>
<% is_editable = can_edit_or_delete?(b)
greeting_card_show_url = Page.where(:module=>'greeting_card').first.url rescue nil
edit_button_can_show = true
%>
<td><% if is_editable %><input type="checkbox" class="batch_select" data-id="<%= b.id %>"><% end %></td>
<% @table_fields.each_with_index do |f,i| %>
<td>
<% case f %>
<% when 'serial_number' %>
<%= b.get_serial_number(last_serial_number, display_length) %>
<% when 'greeting_card_category_id' %>
<%= b.category.title rescue 'category not set' %>
<% when 'image' %>
<img src="<%= b.image.url %>">
<% when 'sender_mail' %>
<%= b.sender_mail %>
<% when 'recipients' %>
<%= b.recipients %>
<% when 'title' %>
<% if b.situation == 'is_published' %>
<%= link_to b.title, (greeting_card_show_url ? (greeting_card_show_url+"?item=#{b.id}") : "javascript:alert('#{t('greeting_card.no_index_page')}')") %>
<% else %>
<%= b.title %>
<% end %>
<% when 'name' %>
<%= b.name %>
<% when 'appointment' %>
<%= b.appointment.strftime("%Y-%m-%d %H:%M") rescue nil %>
<% when 'created_at' %>
<%= b.created_at.strftime("%Y-%m-%d %H:%M") rescue nil %>
<% when 'ip' %>
<%= b.ip %>
<% end %>
<% if edit_box_display_index == i %>
<%= render partial: 'edit_box_for_index', :locals => {is_editable: is_editable, b: b} %>
<% end %>
</td>
<% end %>
<% @table_ext_fields.each do |f, v| %>
<td>
<%= show_on_front(f,v,b,true) %>
</td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<%= content_tag :div, class: "bottomnav clearfix" do %>
<%= content_tag :div, class: "pagination pagination-centered" do
paginate(@greeting_cards)
end %>
<%= content_tag :div, link_to(I18n.t('greeting_card.display_fields_setting'), backend_table_setting_admin_greeting_cards_path + (@category_id.present? ? "?category_id=#{@category_id}" : ''), :class=>'btn btn-primary' ) + link_to(t("greeting_card.delete_selected"), "javascript:void(0)", :class=>"btn btn-danger delete_greeting_cards_btn hide", :style=>'margin-left: 0.5em;') + link_to(t("greeting_card.batch_modify_status"), "javascript:void(0)", :class=>"btn btn-success batch_modify_status_btn hide", :style=>'margin-left: 0.5em;'), class: 'pull-right' %>
<% end %>
<script>
$(document).ready(function(){
$("#submit_when_change").on("change",function(){
$(this)[0].form.submit();
})
})
</script>

View File

@ -0,0 +1,131 @@
<% trans = 'mongoid.attributes.greeting_card_record' %>
<div style="font-size: 1.5em;">
<%= t('greeting_card.explanation') %>:
<br>
{title} -> <%= t('title') %>
<br>
{created_at} -> <%= t('greeting_card.created_at') %>
<br>
{category} -> <%= t("#{trans}.greeting_card_category_id") %>
<br>
{name} -> <%= t("#{trans}.name") %>
<br>
{greetings} -> <%= t("#{trans}.greetings") %>
<br>
{sender_mail} -> <%= t("#{trans}.sender_mail") %>
<br>
{recipients} -> <%= t("#{trans}.recipients") %>
<br>
{custom1} -> <%= t("greeting_card.custom1") %>
<br>
{custom2} -> <%= t("greeting_card.custom2") %>
<br>
{custom3} -> <%= t("greeting_card.custom3") %>
<br>
<%= t("greeting_card.and_so_on") %>
<br>
{custom} -><%= t("greeting_card.custom_explain") %>
<br>
{custom|format} -><%= t("greeting_card.custom_format_explain") %>
<br>
{?_title} -> ?<%= t("greeting_card.can_be_filled_with") %>title、created_at、category、name、greetings、sender_mail、recipients、custom、custom1、custom2、custom3 ...,<%= t("greeting_card.show_title_trans") %>, <%= t("greeting_card.like") %>{created_at_title}-><%= t("#{trans}.created_at") %>
<br>
<br>
<%= t("greeting_card.example") %>:
<br>
<%= t("greeting_card.example_explain") %>
<br>
<%= t('greeting_card.print_format') %>:
<br>
<table border="1" cellpadding="1" cellspacing="1" style="width:500px;">
<tbody>
<tr>
<td style="text-align: center;"><%= t("greeting_card.example") %></td>
</tr>
</tbody>
</table>
<table border="1" cellpadding="1" cellspacing="1" style="width:500px;">
<tbody>
<tr>
<td>{title_title}</td>
<td>{title}</td>
</tr>
<tr>
<td>{category_title}</td>
<td>{category}</td>
</tr>
<tr>
<td>{name_title}</td>
<td>{name}</td>
</tr>
<tr>
<td>{greetings_title}</td>
<td>{greetings}</td>
</tr>
<tr>
<td>{sender_mail_title}</td>
<td>{sender_mail}</td>
</tr>
<tr>
<td>{recipients_title}</td>
<td>{recipients}</td>
</tr>
<tr>
<td>{custom1_title}</td>
<td>{custom1}</td>
</tr>
<tr>
<td>{custom2_title}</td>
<td>{custom2}</td>
</tr>
</tbody>
</table>
<br>
<br>
<%= t('greeting_card.output_result') %>:
<br>
<table border="1" cellpadding="1" cellspacing="1" style="width:500px;">
<tbody>
<tr>
<td style="text-align: center;"><%= t("greeting_card.example") %></td>
</tr>
</tbody>
</table>
<table border="1" cellpadding="1" cellspacing="1" style="width:500px;">
<tbody>
<tr>
<td><%= t('title') %></td>
<td>example</td>
</tr>
<tr>
<td><%= t("#{trans}.greeting_card_category_id") %></td>
<td>測試</td>
</tr>
<tr>
<td><%= t("#{trans}.name") %></td>
<td>工程師1號</td>
</tr>
<tr>
<td><%= t("#{trans}.greetings") %></td>
<td>新的一年,祝您事事順利</td>
</tr>
<tr>
<td><%= t("#{trans}.sender_mail") %></td>
<td>test@rulingcom.com</td>
</tr>
<tr>
<td><%= t("#{trans}.recipients") %></td>
<td>test2@rulingcom.com</td>
</tr>
<tr>
<td>test1</td>
<td>a</td>
</tr>
<tr>
<td>test2</td>
<td>b</td>
</tr>
</tbody>
</table>
</div>

View File

@ -0,0 +1,83 @@
<fieldset>
<style>
.show_field {
border: 1px solid black;
padding: 3px;
min-width: 1em;
height: 20px;
overflow-y: auto;
}
</style>
<table class="table">
<tbody>
<tr>
<td>
<a href="#" class="btn btn-primary clone_default_setting" data-parent=".show_default_greeting_card_setting"><%= t('greeting_card.clone_default_setting') %></a>
<a href="#" class="btn btn-success recover_data switch_to_default <%= 'hide' if @first_setting.nil? %>" data-parent=".show_default_greeting_card_setting" data-id="<%= @first_setting.id if @first_setting%>" data-use-default="false"><%= t('greeting_card.recover_data') %></a>
</td>
<td></td>
</tr>
<tr>
<td><%= t("greeting_card.email_regex") %>:</td>
<td>
<%= check_box_tag :email_regex_enable, @default_greeting_card_setting.email_regex_enable , nil, {:id=>"",:disabled=>'disabled'} %><%= t("greeting_card.enable") %>
<div style="clear: both;"></div>
<div class="show_field">
<%= @default_greeting_card_setting.email_regex %>
</div>
</td>
</tr>
<tr>
<td><%= t("greeting_card.validation_email_content") %>:</td>
<td>
<%= check_box_tag :validate_enable, @default_greeting_card_setting.validate_enable , nil, {:id=>"",:disabled=>'disabled'} %><%= t("greeting_card.enable") %>
<div style="clear: both;"></div>
<div class="show_field">
<%= @default_greeting_card_setting.validation_email_content %>
</div>
</td>
</tr>
<tr>
<td>
<%= t('greeting_card.field') %>
</td>
<td>
<%= t('greeting_card.whether_open') %>
</td>
</tr>
<% locale = I18n.locale.to_s %>
<% true_false_trans = {'true'=> t('yes'), 'false'=>t('no')} %>
<%
default_setting = @default_greeting_card_setting.default_setting
if default_setting.keys[0].to_s != 'title'
default_setting = {title: true}.merge(default_setting)
end
%>
<% default_setting.each do |k,v| %>
<tr>
<td>
<%= tmp = @default_greeting_card_setting.field_name(k,locale, true) %>
</td>
<td>
<%=
tmp2 = true_false_trans[v]
tmp2 = true_false_trans.values[0] if tmp2.nil?
tmp2
%>
</td>
</tr>
<% end %>
<tr>
<td>
<%= t("greeting_card.usage_rule") %>
</td>
<td colspan="2">
<%= @default_greeting_card_setting.usage_rule.to_s.html_safe %>
</td>
</tr>
</tbody>
<% @default_greeting_card_setting.custom_fields.each do |k,v| %>
<%= custom_field_block_for_greeting_card(k,v,true).html_safe %>
<% end %>
</table>
</fieldset>

View File

@ -0,0 +1,47 @@
<% cat = Category.where(:id=>params[:category_id]).first %>
<%= form_for @greeting_card_list_setting,method: 'post',url: @url,html: { class: 'form-horizontal main-forms prekiewable' } do |f| %>
<fieldset>
<h3><%= t('greeting_card.backend_table_setting') %> - <%= cat ? cat.title : t(:all) %></h3>
<h4>
<%= I18n.t("greeting_card.default_head_for_table") %>
</h4>
<% tmp = GreetingCardListSetting::DefaultFields
%>
<% tmp.each do |k| %>
<dik class="control-group">
<dik class="control-label">
<%= f.label "default_fields_#{k}", I18n.t("greeting_card.#{k}",default: I18n.t("mongoid.attributes.greeting_card_record.#{k}")) %>
</dik>
<dik class="controls">
<%= f.check_box :default_fields, {:checked=> @greeting_card_list_setting.default_fields.include?(k), :multiple=> true}, k, nil %>
<%= f.label "default_fields_#{k}", I18n.t(:enable), {:style=> 'display: inline-block'} %>
</dik>
</dik>
<% end %>
<% @greeting_card_list_setting.custom_fields_list.each do |title, data| %>
<h4>
<%= title %>
</h4>
<% data.each do |k,name| %>
<dik class="control-group">
<dik class="control-label">
<%= f.label "custom_fields#{k}", name %>
</dik>
<dik class="controls">
<%= f.check_box :custom_fields, {:checked=> @greeting_card_list_setting.custom_fields.include?(k), :multiple=> true}, k, nil %>
<%= f.label "custom_fields_#{k}", I18n.t(:enable), {:style=> 'display: inline-block'} %>
</dik>
</dik>
<% end %>
<% end %>
<%= hidden_field_tag :id, @greeting_card_list_setting.id %>
<dik class="control-group">
<%= f.submit t(:submit), class: 'btn btn-primary' %>
</dik>
</fieldset>
<style type="text/css">
form.form-horizontal .controls{
margin-left: 1em;
}
</style>
<% end %>

View File

@ -0,0 +1,338 @@
<%= stylesheet_link_tag "lib/togglebox", media: "all" %>
<% if current_user.is_admin? || current_user.is_manager?(module_app) %>
<button class="btn" data-toggle="modal" data-target="#categoryModal" type="button">
<i class='icon-plus'></i> <%= t(:new_category) %>
</button>
<% end %>
<div class="modal fade" id="categoryModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="myModalLabel"><%= t(:new_category) %></h4>
</div>
<div class="modal-body">
<% @site_in_use_locales.each do |locale| %>
<div class="control-group">
<label class="control-label"><%= "#{t(:name)} (#{t(locale)})" %></label>
<div class="controls">
<input class="input-large" id="<%=locale%>" name="category[title_translations][<%=locale%>]" placeholder="<%=t(:name)%>" type="text">
<span class="help-inline hide">Please enter category title</span>
</div>
</div>
<% end %>
<div class="control-group">
<label class="control-label"><%= "#{t(:sort_number)}" %></label>
<div class="controls">
<input class="input-large" id="sort_number" name="category[sort_number]" placeholder="<%=t(:sort_number)%>" type="number">
<span class="help-inline hide"><%= t('front_page.only_number') %></span>
</div>
</div>
<div class="text-error text-center"><%= t(:category_notice) %></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default pull-left" data-dismiss="modal"><%= t(:close) %></button>
<button type="button" class="btn btn-primary" id="add_category"><%= t(:add) %></button>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$(function(){
$("#categoryModal").hide();
$('#categoryModal').modal('<%= @categories.blank? ? "show" : "hide" %>');
$("#add_category").click(createCategory);
$("#categoryModal .modal-body").keypress(function(e) {
if(e.which == 13) {
createCategory();
return false;
}
});
$.each($('#categoryModal .input-large'),function(){
$(this).blur(function(){
if($(this).val()==""){
$(this).parent().parent().addClass('error');
$(this).next().removeClass('hide');
}else{
$(this).parent().parent().removeClass('error');
$(this).next().addClass('hide');
}
});
});
});
var createCategory = function(){
var valid = true;
$.each($('#categoryModal .input-large'),function(){
if($(this).val()==""){
$(this).parent().parent().addClass('error');
$(this).next().removeClass('hide');
valid = false;
}else{
$(this).parent().parent().removeClass('error');
$(this).next().addClass('hide');
}
});
if(valid){
$.ajax({
url : "<%= create_in_form_admin_module_app_categories_path(:module_app_id=>@module_app.id.to_s,:module_app_type=>@module_app.class.to_s.underscore) %>",
type : "post",
data: $("input[name^='category']").serialize(),
}).done(function(data){
$.each($('#categoryModal .input-large'),function(){
$(this).val("");
});
var active_class = '';
if($('.toggle_tag_group a.toggle_tag').length == 0){
active_class = ' active_in';
window.greeting_card_cateogry_id = data['id'];
$("#default_greeting_card_setting").removeClass('hide');
$("#category_greeting_card_setting").addClass('hide');
$("#default_greeting_card_setting").find('.default_greeting_card_setting .hidden_category_id').val(data['id']);
}
$('.toggle_tag_group').append('<a href="#'+ data['id'] +'" data-category-id="'+ data['id'] +'" data-toggle="tab" class="toggle_tag' + active_class + ' default_setting">' + data['title'] + ' (<%=t('greeting_card.default')%>)</a>');
$('#categoryModal').modal('hide');
});
}
}
</script>
<script type="text/javascript">
$(document).ready(function(){
$('.add_new_options').sortable({'handle':'.icons-list-2'});
$(document).on('show.bs.tab', '.field a[data-toggle="tab"]', function (e, force_flag) {
var _this = $(e.target);
if(_this.hasClass('active_in') && !force_flag){
return;
}
window.greeting_card_cateogry_id = _this.data('category-id');
_this.parents('.toggle_tag_group').eq(0).find('a').removeClass('active_in');
_this.addClass('active_in');
$('.cloned_setting_block').remove();
if(_this.hasClass('default_setting')){
var id = _this.attr('href').split('#')[1];
if(id.length){
$("#default_greeting_card_setting").find('.recover_data').removeClass('hide').data('id', id);
}else{
$("#default_greeting_card_setting").find('.recover_data').addClass('hide').data('id', '');
}
$("#default_greeting_card_setting").removeClass('hide');
$("#category_greeting_card_setting").addClass('hide');
$.ajax({
url : "<%= "/#{I18n.locale}/admin/greeting_cards/get_category_setting_partial" %>",
dataType : "text",
type : "post",
async: false,
data: {id: window.greeting_card_cateogry_id},
error: function(){
alert('get data failed, please try again later.')
},
success: function(data){
$('#background_setting_form').replaceWith(data);
$('#background_setting_form_wrapper .card_category_id').val(window.greeting_card_cateogry_id);
$("#background_setting_form_wrapper").addClass('active');
}
})
}else{
$("#background_setting_form_wrapper").removeClass('active');
$("#default_greeting_card_setting").addClass('hide');
$("#category_greeting_card_setting").removeClass('hide');
var id = _this.attr('href');
if ($(id).length==0){
$.ajax({
url : "<%= "/#{I18n.locale}/admin/greeting_cards/get_category_setting_field" %>",
dataType : "text",
type : "post",
async: false,
data: {id: id.replace(/#/g,'')},
error: function(){
alert('get data failed, please try again later.')
},
success: function(data){
$('#category_greeting_card_setting').html(data);
$('#category_greeting_card_setting').find('.ckeditor').each(function(i, item){
CKEDITOR.replace(item);
});
}
})
}
}
});
})
</script>
<div class="fade-in active" id="field">
<style type="text/css">
.category-set-page input[type="submit"],.category-set-page input[type="button"]{
visibility: hidden;
}
.fade-in{
display: none;
}
.fade-in.active{
display: block;
}
form.fade-in.active{
border: 0.3em solid #132e8b;
padding: 1em;
}
a.toggle_tag{
outline: 0;
background: #cad0da;
padding: 1em;
display: inline-block;
}
a.toggle_tag.active_in{
color: white;
background: #495c7a;
}
a.toggle_tag:not(:first-child){
border-left: 0.1em solid #9d3874;
}
.toggle_tag_group{
display: flex;
flex-wrap: wrap;
}
</style>
<%
set_input_name_for_greeting_card('greeting_card_category_setting[custom_fields]')
%>
<script type="text/javascript">
function add_new_field(ele){
var category_id = window.greeting_card_cateogry_id;
$.ajax({
url : "<%= "/#{I18n.locale}/admin/greeting_cards/get_new_category_setting_index" %>",
dataType : "json",
type : "post",
data: {category_id: category_id},
error: function(){
alert('init process failed, please try again later.')
},
success: function(data){
var add_field_html = "<%= custom_field_block_for_greeting_card(-1).inspect %>"
add_field_html = add_field_html.replace(/-1/g,data['key'])
var add_field = $(ele).parents('.add_field');
add_field.before($('<div/>').html(add_field_html).text().slice(1,-2))
var new_item = add_field.prev();
new_item.find('.add_new_options').sortable({'handle':'.icons-list-2'})
new_item.find('.ckeditor').each(function(i, item){
CKEDITOR.replace(item);
});
}
})
}
</script>
<%
first_category_html = ""
@first_category_id = nil
@first_setting = nil
%>
<div class="toggle_tag_group field">
<% @categories.each_with_index do |category, index1| %>
<%
category_id = category.id.to_s
has_category_setting = @category_added_ids.include?(category_id)
name1 = category.title
if name1.blank?
name1 = "No Name"
end
is_default = false
if has_category_setting
category_added = @category_added[category_id]
is_default = category_added.use_default
else
category_added = @default_greeting_card_setting
is_default = true
end
if index1 == 0
@first_category_id = category_id
@first_setting = category_added
if has_category_setting && !is_default
first_category_html = render(partial: 'category_setting_field',locals: {greeting_card_setting: category_added, is_default: is_default})
end
end
%>
<a href="#<%= has_category_setting ? category_added.id.to_s : '' %>" data-category-id="<%= category_id %>" data-toggle="tab" class="toggle_tag<%= ' active_in' if index1 == 0 %> <%= 'default_setting' unless has_category_setting && !is_default %>" data-default="<%=is_default%>"><%= name1 %><span class="default_text <%= 'hide' unless is_default%>">&nbsp;(<%=t('greeting_card.default')%>)</span></a>
<% end %>
</div>
<% if @first_setting %>
<%= form_for @first_setting, method: 'post', url: category_setting_save_admin_greeting_cards_path , html: { class: "form-horizontal fade-in detail #{(first_category_html.blank? ? 'active' : '')}", id: "background_setting_form_wrapper"} do |f| %>
<%= render :partial=> "category_setting_partial", locals: {f: f, greeting_card_setting: @first_setting, is_default: (@first_setting == @default_greeting_card_setting)} %>
<%= f.hidden_field :use_default, :value => true %>
<%= hidden_field_tag "category_id", @first_category_id, class: "card_category_id" %>
<div style="text-align: center;">
<input class="btn btn-primary" type="submit" value="<%= t('greeting_card.modify') %>">
</div>
<% end %>
<% end %>
<div id="category_greeting_card_setting">
<%= first_category_html %>
</div>
<%
@is_hidden = (first_category_html.present? || @categories.length == 0)
%>
<%= render(:partial=>"default_greeting_card_setting") %>
</div>
<script>
window.greeting_card_cateogry_id = "<%= @first_category_id %>";
$(document).on('click', '.switch_to_default', function(){
var _this = $(this);
var id = _this.data('id');
var use_default = _this.attr('data-use-default');
if(window.confirm(use_default == "true" ? "<%=t('greeting_card.are_you_sure_to_switch_to_default_setting')%>" : "<%=t('greeting_card.are_you_sure_to_recover_data')%>")){
$.post("<%=switch_to_default_setting_admin_greeting_cards_path%>", {id: id, use_default: use_default}).done(function(data){
if(data["success"]){
if(use_default == "true"){
$('#background_setting_form_wrapper').addClass('active');
$('a[data-category-id="'+window.greeting_card_cateogry_id+'"]').addClass('default_setting').find('.default_text').removeClass('hide');
var parent = _this.data('parent');
if(parent){
_this.parents(parent).addClass('hide').siblings().removeClass('hide');
}else{
var category_greeting_card_setting = _this.parents('#category_greeting_card_setting')
category_greeting_card_setting.addClass('hide');
var clone_block = $('#default_greeting_card_setting').clone();
clone_block.attr('id','').addClass('cloned_setting_block').removeClass('hide').find('.recover_data').removeClass('hide').data('id', id);
_this.siblings('input[type="hidden"]').val(true);
category_greeting_card_setting.after(clone_block);
}
}else{ //Recover data
$('#background_setting_form_wrapper').removeClass('active');
$('a[data-category-id="'+window.greeting_card_cateogry_id+'"]').find('.default_text').addClass('hide');
$('a[data-category-id="'+window.greeting_card_cateogry_id+'"]').removeClass('default_setting').trigger('show.bs.tab', true);
}
}else{
alert("Failed!");
window.location.reload();
}
})
}
})
$(document).on('click', '.cancel_edit', function(){
if(window.confirm('<%=t('greeting_card.are_you_sure_to_cancel_edit')%>')){
var _this = $(this);
var parent = _this.data('parent');
$('a[data-category-id="'+window.greeting_card_cateogry_id+'"]').find('.default_text').removeClass('hide');
if(parent){
var parent_block = _this.parents(parent);
parent_block.addClass('hide').siblings().removeClass('hide');
parent_block.replaceWith($('#default_greeting_card_setting').find(parent).clone());
}
}
})
$(document).on('click', '.clone_default_setting', function(){
$('a[data-category-id="'+window.greeting_card_cateogry_id+'"]').find('.default_text').addClass('hide');
var _this = $(this);
var parent_block = _this.parents('.show_default_greeting_card_setting');
var form_block;
$("#background_setting_form_wrapper").removeClass('active');
form_block = parent_block.addClass('hide').siblings();
form_block.find('.background_upload_block').replaceWith($("#background_setting_form_wrapper .background_upload_block").clone());
form_block.removeClass('hide').find('.hidden_category_id').val(window.greeting_card_cateogry_id);
})
</script>

View File

@ -0,0 +1,50 @@
# encoding: utf-8
wb = xlsx_package.workbook
wb.add_worksheet(name: "GreetingCard Question") do |sheet|
heading = sheet.styles.add_style(:b => true, :locked => true)
heads = []
fields_with_key_group.each do |cat_id, fields_with_key|
fields_with_key.each do |type, fs|
fs.each do |key, field|
heads << field if !heads.include?(field)
end
end
end
sheet.add_row heads, :style => heading
greeting_card_records.each do |greeting_card_record|
row = []
row_group = {}
s = greeting_card_category_settings[greeting_card_record.category_id]
fields_with_key_group[greeting_card_record.category_id]['default_values'].each do |key, field|
text = ''
case key
when 'created_at', 'sending_time'
text = greeting_card_record.send(key).strftime('%Y/%m/%d %H:%M')
when 'title','name','sender_mail',recipients','greetings'
text = greeting_card_record.send(key).to_s
when 'greeting_card_category_id'
text = categories[greeting_card_record.category_id].title rescue ''
when 'agree_show'
if greeting_card_record.agree_show
text = I18n.t('greeting_card.yes')
else
text = I18n.t('greeting_card.no')
end
when 'situation'
text = situations[greeting_card_record.situation].collect{|k,v| v}.join('/') rescue ''
end
row_group[field] = text
end
fields_with_key_group[greeting_card_record.category_id]['custom_values'].each do |key, field|
row_group[field] = Admin::GreetingCardsHelper.show_on_front(key, s.custom_fields[key], greeting_card_record, true)
end
row = heads.collect do |head|
row_group[head]
end
sheet.add_row row
end
end

View File

@ -0,0 +1,5 @@
<%= form_for @greeting_card_record, url: @url, html: { class: 'form-horizontal main-forms previewable',multipart: true } do |f| %>
<fieldset>
<%= render :partial => 'form', locals: {f: f} %>
</fieldset>
<% end %>

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
</head>
<body>
<p>
<%= @data['reply'].to_s.gsub(/[(\n)(\r)]/, "\n" => "<br/>", "\r" => "" ).html_safe %>
</p>
<% attachment = @data['attachment']
if attachment.present? %>
<% filename = File.basename(attachment) %>
<p>
<%= t('greeting_card.attachment') %>:
<a title="<%= filename %>" target="_blank" href="<%= @data['host_url'] + attachment %>"><%= filename %></a>
</p>
<% end %>
<br />
<p><%= t('greeting_card.email_automation_hint') %></p>
</body>
</html>

View File

@ -0,0 +1,21 @@
<div id="greeting_cards-export">
<%= form_tag export_admin_greeting_cards_path, method: 'post' do |f| %>
<table>
<tr>
<td><%= t('date_') %></td>
<td><%= date_select 'export', :start %> <%= t('greeting_card.to') %></td>
</tr>
<tr>
<td></td>
<td><%= date_select 'export', :end %></td>
</tr>
<tr>
<td colspan="2">
<div class="form-actions">
<%= submit_tag t('submit'), class: 'btn btn-primary' %>
</div>
</td>
</tr>
</table>
<% end %>
</div>

View File

@ -0,0 +1,6 @@
<%= render_filter @filter_fields, "index_table" %>
<span id="index_table">
<%= render 'index'%>
</span>
<%= render 'layouts/delete_modal', delete_options: @delete_options %>

View File

@ -0,0 +1,69 @@
<%= stylesheet_link_tag "greeting_card/konva_helper", media: "all" %>
<%= stylesheet_link_tag "select2-v4/select2", media: "all" %>
<%= javascript_include_tag "greeting_card/konva.min" %>
<%= javascript_include_tag "greeting_card/konva_helper" %>
<%= javascript_include_tag "select2-v4/select2.min" %>
<div id="search-bar">
<div>
<form>
<h4><%= t(:category) %></h4>
<select name="category" id="submit_when_change">
<% @cats_relations.each do |id, title| %>
<option value="<%=id%>" <%= @category_id == id ? 'selected' : '' %>><%= title %></option>
<% end %>
</select>
</form>
</div>
<%= form_for @set, as: :greeting_card_layout_design ,method: 'post',url: @url,html: { class: 'form-horizontal main-forms previewable' } do |f| %>
<%= hidden_field_tag "#{f.object_name}[category_id]", @category_id %>
<fieldset>
<div class="form-horizontal">
<div class="control-group">
<div class="control-label">
<%= label_tag t('greeting_card.save_name') %>
</div>
<div class="controls">
<%= f.text_field :save_name %>
</div>
</div>
<div class="control-group">
<div class="control-label">
<%= label_tag t('greeting_card.layout_design') %>
</div>
<div class="controls">
<%# https://konvajs.org/docs/sandbox/Canvas_Editor.html %>
<div id="container-wrapper">
</div>
<div id="container-hidden-field" data-name="<%= f.object_name %>[img_objs]">
<%= f.hidden_field_tag "#{f.object_name}[img_objs_changed]", "0", :id => "img_objs_changed" %>
</div>
<script>
var layer = create_konva($('#container-wrapper'), $('#container-hidden-field'), 'container', "<%= @images.first %>", <%= GreetingCardRecord.get_fonts.to_s.html_safe %>, {"lineheight": "<%= t('greeting_card.lineheight') %>", "stroke": ["<%= t('greeting_card.borderline') %>", "<%= t('greeting_card.word_art') %>"], "fill": ["<%= t('greeting_card.fill') %>", "<%= t('greeting_card.fill') %>"]});
<% f.object.img_objs.each do |i, obj| %>
create_text_box(layer, {x: <%= obj[:x].to_f %>, y: <%= obj[:y].to_f %>, w: <%= obj[:w].to_f %>, h: <%= obj[:h].to_f %>, l_h: <%= (obj[:l_h] ? obj[:l_h].to_f : 1.0) %>}, "<%= j(obj[:text]) %>", <%= obj[:fontSize] %>, "<%= obj[:fontFamily] %>", "<%= obj[:fontColor] %>", <%= obj[:is_stroke].nil? ? false : obj[:is_stroke] %>, "<%= obj[:stroke] %>", "<%= obj[:strokeWidth] %>", <%= obj[:is_fill].nil? ? true : obj[:is_fill] %>);
<% end %>
$('#container-hidden-field').one('change', function()
{
$('#img_objs_changed').val('1');
});
</script>
</div>
</div>
<div class="control-group" style="text-align: center;">
<input class="btn btn-primary" type="submit" value="<%= t('submit')%>">
</div>
</div>
</fieldset>
<% end %>
<%= render partial: 'print_format_explain' %>
<script>
$(document).ready(function(){
$("#submit_when_change").on("change",function(){
$(this)[0].form.submit();
})
})
</script>

View File

@ -0,0 +1,16 @@
<%= form_for @greeting_card_list_setting,method: 'post',url: @url,html: { class: 'form-horizontal main-forms previewable' } do |f| %>
<fieldset>
<% tmp = f.object.default_fields %>
<% tmp.each do |k| %>
<% f.fields_for :default_fields, tmp do |f| %>
<% f.fields_for k, tmp[k] do |f| %>
<%= f.label :key %>
<%= f.check_box :is_enabled %>
<% end %>
<% end %>
<% end %>
<div class="control-group">
<%= f.submit t(:submit), class: 'btn btn-primary' %>
</div>
</fieldset>
<% end %>

View File

@ -0,0 +1,209 @@
<style>
.icons-list-2 {
cursor: all-scroll;
}
.position-text-div {
cursor: text;
margin: -8px;
padding: 8px;
}
.position-text-div:hover {
background: aqua;
}
</style>
<div>
<form>
<h4><%= t(:category) %></h4>
<select name="category" id="submit_when_change">
<% @cats_relations.each do |id, title| %>
<option value="<%=id%>" <%= @category_id == id ? 'selected' : '' %>><%= title %></option>
<% end %>
</select>
</form>
</div>
<div class="order-edit-notification"><%= t("greeting_card.please_save") %></div>
<table width="100%" id="greeting_card_fields_order_table" class="table table-striped" class="greeting_card_fields_table">
<thead>
<tr>
<th></th>
<th><%= t("greeting_card.sort_number") %></th>
<th><%= t("greeting_card.field") %></th>
</thead>
<tbody>
<% @disp_fields_infos.each_with_index do |(k, info),i| %>
<tr data-index="<%=i%>">
<td><span class="brand"><i class="icons-list-2"></i></span></td>
<td class="position-text">
<div class="position-text-div" data-value="<%= (i + 1).to_s %>"><%= (i + 1).to_s %></div>
</td>
<td>
<div class="field-text-id" data-field-id="<%= k %>"><%= info["trans"] %></div>
</td>
</tr>
<% end %>
</tbody>
</table>
<div class="bottomnav clearfix" style="left: 81px;">
<div class="action pull-right">
<a class="btn btn-info disabled" id="save-order-button" href="#"><%= t("greeting_card.save_order") %></a>
</div>
<div class="pagination pagination-centered"></div>
</div>
<script type="text/javascript">
var makeEditable = function(){
var input_box = $("<input type='text'/>"),
el = $(this);
input_box.addClass("editable-input");
input_box.val(el.data("value"));
input_box.attr("data-old-id",el.data("value"));
input_box.on("blur",function(){
putBackdiv($(this));
});
input_box.on("keypress",function(e){
if(e.keyCode == 13 || e.keyCode == 27){
putBackdiv($(this),e.keyCode);
}
})
el.parent().html(input_box);
input_box.focus();
}
var putBackdiv = function(el,keyCode){
current_value = parseInt((el.val() == "" ? el.data("old-id") : el.val())),
old_value = parseInt(el.data("old-id"));
if(isNaN(current_value) || keyCode == 27){
current_value = old_value;
}
if(old_value != current_value){
var new_index_value = (current_value > old_value ? current_value + 1 : current_value - 1),
div = $("<div class='position-text-div' data-value='" + current_value + "'>" + new_index_value + "</div>");
div.on("click",makeEditable);
el.parent().html(div);
$("#save-order-button").removeClass("disabled");
$(".order-edit-notification").slideDown();
sortTable(el.data("old-id"),current_value);
}else{
var div = $("<div class='position-text-div' data-value='" + current_value + "'>" + current_value + "</div>");
div.on("click",makeEditable);
el.parent().html(div);
}
}
var sortTable = function(changed_index,changed_to){
var table_element = document.getElementById("greeting_card_fields_order_table"),
data = [],
allRows = table_element.rows;
for(i = 1; i < allRows.length; i++){
var thisRow = allRows[i],
text = thisRow.cells[1].textContent.trim(),
hash = {};
hash.index = parseInt(text);
text = thisRow.cells[2].innerHTML.trim();
if(text != "&nbsp;"){
hash.field_name = text;
}
data.push(hash);
}
data = data.sort(function(a,b){return a.index - b.index});
renderSortedTable(data,table_element);
}
var renderSortedTable = function(data,table_element){
var allRows = table_element.rows;
for(i = 0;i < data.length; i++){
var thisRow = allRows[i + 1],
current_value = i + 1;
thisRow.cells[1].innerHTML = "<div class='position-text-div' data-value='" + current_value + "'>" + current_value + "</div>";
thisRow.cells[2].innerHTML = data[i].field_name;
}
$("#greeting_card_fields_order_table div.position-text-div").on("click",makeEditable);
}
$("#save-order-button").on("click",function(){
var el = $(this);
if(!el.hasClass("disabled")){
var sort_number = {};
$("#greeting_card_fields_order_table .field-text-id").each(function(i, v){
sort_number[$(v).data("field-id")] = i + 1;
})
$.ajax({
url : "/admin/greeting_cards/update_order_fields",
data : {"sort_number" : sort_number,"category": "<%=@category_id%>"},
dataType : "json",
type : "post"
}).done(function(){
el.addClass("disabled");
$(".order-edit-notification").slideUp();
})
}
})
$("#greeting_card_fields_order_table div.position-text-div").on("click",makeEditable);
</script>
<script>
var th_width = {};
$(document).ready(function(){
$("#submit_when_change").on("change",function(){
$(this)[0].form.submit();
})
$( ".table tbody" ).each(function(i,tbody){
var table = $(tbody).parents("table").eq(0);
table.data("index",i);
th_width[i] = [];
table.find("thead th").each(function(j,th){
th_width[i].push($(th).outerWidth(true));
})
})
$( ".table tbody" ).sortable({
revert: true,
axis: "y",
handle: ".brand",
start: function(event, ui){
var item = ui.item;
var target = $(event.target);
var index = target.parents(".table").eq(0).data("index");
item.css("width",target.width());
item.find("td").each(function(i,td){
$(td).width(th_width[index][i]);
})
},
stop: function(event, ui) {
var item = ui.item;
item.css("width","");
item.find("td").css("width","");
},
update: function(event, ui) {
var item = ui.item;
var org_index = item.data("index");
console.log(org_index);
var new_index = item.index();
var indices = [org_index,new_index].sort();
var table = item.parents(".table").eq(0);
table.find("tbody tr").each(function(i,tr){
if(i >= indices[0] && i <= indices[1]){
var position_text_div = $(tr).find(".position-text-div");
position_text_div.text(i+1).data("value",i+1);
$(tr).data("index",i);
}
if(i > indices[1]){
return;
}
})
$("#save-order-button").removeClass("disabled");
$(".order-edit-notification").slideDown();
}
});
})
$(window).resize(function(){
th_width = {};
$( ".table tbody" ).each(function(i,tbody){
var table = $(tbody).parents("table").eq(0);
th_width[i] = [];
table.find("thead th").each(function(j,th){
th_width[i].push($(th).outerWidth(true));
})
})
})
</script>

View File

@ -0,0 +1,48 @@
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js">
</script>
<script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<%= javascript_include_tag "jspdf.min" %>
<style>
input[type="button"],button,input[type="submit"] {
outline: 0;
border-radius: 1.3em;
background: #d9e4f7;
font-weight: bold;
outline: 0;
}
input[type="button"]:hover,button:hover,input[type="submit"]:hover {
background: #be8a8a;
}
.print_text{
padding: 2em;
width: 650px;
margin: auto;
}
@media print
{
.no-print, .no-print *
{
display: none !important;
}
}
</style>
<script type="text/javascript">
function save_data(){
var filename = '<%= @save_name %>.pdf';
$('div.print_text').find('input[type=button]').hide()
html2canvas($('div.print_text')[0]).then(canvas => {
var pdf = new jsPDF('px', 'mm', 'a4');
var width = pdf.internal.pageSize.getWidth()-3;
var height = $('div.print_text').innerHeight()/$('div.print_text').innerWidth()*width;
pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, 0,width ,height );
pdf.save(filename);
});
$('div.print_text').find('input[type=button]').show()
}
</script>
<div class="no-print" style="text-align: center;">
<input onclick="save_data()" value="<%= I18n.t('greeting_card.save_data') %>" type="button">
</div>
<div class="print_text">
<%= @print_text.html_safe %>
</div>

View File

@ -0,0 +1,36 @@
<%
set_input_name_for_greeting_card('greeting_card_setting[custom_fields]')
%>
<script>
function add_new_field(ele){
$.ajax({
url : "<%= get_new_setting_index_admin_greeting_cards_path %>",
dataType : "json",
type : "post",
error: function(){
alert('init process failed, please try again later.')
},
success: function(data){
var add_field_html = "<%= custom_field_block_for_greeting_card(-1).inspect %>"
add_field_html = add_field_html.replace(/-1/g,data['key'])
$(ele).parents('.add_field').before($('<div/>').html(add_field_html).text().slice(1,-2))
var new_item = add_field.prev();
new_item.find('.add_new_options').sortable({'handle':'.icons-list-2'})
new_item.find('.ckeditor').each(function(i, item){
CKEDITOR.replace(item);
});
}
})
}
</script>
<script type="text/javascript">
$(document).ready(function(){
$('.add_new_options').sortable({'handle':'.icons-list-2'});
})
</script>
<%= form_for @default_greeting_card_setting,method: 'post',url: @url,html: { class: 'form-horizontal main-forms previewable' } do |f| %>
<%
@has_email_regex = true
%>
<%= render partial: 'greeting_card_setting',locals:{greeting_card_setting: @default_greeting_card_setting,f: f,submit_text: t('submit'), is_default: false} %>
<% end %>

View File

@ -0,0 +1,115 @@
<div id="pageslide">
<div class="page-title clearfix">
<a class="pull-right" href="javascript:$.pageslide.close()">
<i class="icons-arrow-left-2"></i>
</a>
<span></span>
</div>
<div class="view-page">
<div class="nano">
<div class="content">
<%= form_for :greeting_card_ticket_status, url: update_ticket_status_admin_greeting_cards_path, remote: true, :html=>{id: "greeting_card_ticket_status_form"} do |f| %>
<fieldset>
<%= hidden_field_tag :id, "", {:id=>'hidden_id_field'} %>
<%= f.fields_for :title_translations do |f| %>
<% @site_in_use_locales.each do |locale| %>
<div class="control-group">
<label class="control-label"><%= "#{t('greeting_card.status')} (#{t(locale)})" %></label>
<div class="controls">
<input class="input-large" id="<%=locale%>" name="<%=f.object_name%>[<%=locale%>]" placeholder="<%=t('greeting_card.status')%>" type="text">
</div>
</div>
<% end %>
<% end %>
<div class="form-actions">
<a href="javascript:$.pageslide.close()" class="btn btn-small"><%= t(:cancel) %></a>
<%= f.submit t(:submit), class: 'btn btn-primary btn-small', id: "greeting_card_ticket_status_submit" %>
</div>
</fieldset>
<% end %>
</div>
</div>
</div>
</div>
<table class="table main-list" id="status_table">
<thead>
<tr>
<th><%= t('greeting_card.status') %></th>
<th><%= t('greeting_card.action') %></th>
</tr>
</thead>
<tbody>
<% @ticket_statuses.each do |ticket_status| %>
<tr>
<td><%= ticket_status.title %></td>
<td>
<a href="#" class="btn btn-primary edit_ticket open-slide" data-id="<%=ticket_status.id%>"><%= t(:edit) %></a>
<% unless ticket_status.is_default %>
<button class="btn btn-danger delete_ticket" data-id="<%=ticket_status.id%>"><%= t(:delete_) %></button>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
<a href="#" class="btn btn-primary new_ticket open-slide" data-title="<%=t("greeting_card.new_status")%>"><%= t(:add) %></a>
<script>
function reload_page(){
$.get(window.location.href).done(function(data){
$('#status_table').html($(data).filter('#status_table').html());
openSlide();
})
}
$(document).ready(function(){
openSlide();
$('form#greeting_card_ticket_status_form').bind('ajax:success', function(evt, data, status, xhr){
window.setTimeout(function(){
reload_page();
$.pageslide.close();
}, 500);
})
$.pageslide.closeCallback(function(pageslide, item) {
$('.filter-item').removeClass("active");
});
$.pageslide.loadComplete(function(pageslide, item) {
var id = item.data('id');
var form = pageslide.find('form');
$.post('<%= get_ticket_status_admin_greeting_cards_path %>', {id: id}).done(function(data){
form.find('#hidden_id_field').val(id);
Object.keys(data).forEach(function(k){
var v = data[k];
if(v instanceof Object){
console.log(v);
var tmp = Object.keys(v);
if(tmp.length){
tmp.forEach(function(kk){
form.find('[name*="greeting_card_ticket_status['+k+']['+kk+']"').val(v[kk]);
});
}else{
form.find('[name*="greeting_card_ticket_status['+k+']"').val('');
}
}else{
form.find('[name*="greeting_card_ticket_status['+k+']"').val(v);
}
})
})
});
$(document).on('click', '.delete_ticket', function(){
var id = $(this).data('id');
var tr = $(this).parents('tr');
var sure_text = "<%=t(:are_you_sure_to_delete)%>";
if(window.confirm(sure_text)){
if(window.confirm(sure_text)){
$.ajax({
url : '<%=delete_ticket_status_admin_greeting_cards_path%>',
type : 'DELETE',
data: {id: id},
success: function(){
tr.remove();
}
});
}
}
})
})
</script>

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<% card = GreetingCardRecord.find(@data['greeting_card_record_id']) rescue nil %>
<% title = card.title %>
<img alt="<%= title %>" title="<%= title %>" src="<%= @data['site_host'] %><%= card.image.url %>" style="width: 100%;" />
<p>此為系統自動發信,請勿直接回覆</p>
</body>
</html>

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
</head>
<body>
<p>
<%= @data['validation_email_content'].to_s.gsub(/[(\n)(\r)]/, "\n" => "<br/>", "\r" => "" ).html_safe %>
</p>
<br />
<% if @data['referer_link'] %>
<%= @data['referer_link'].html_safe %>
<br />
<% else %>
<%= @data['verify_link'].html_safe %>
<br />
<% end %>
<p><%= t('greeting_card.email_automation_hint') %></p>
</body>
</html>

View File

@ -0,0 +1,197 @@
<% data = action_data
@greeting_card_record = data["greeting_card_record"]
@categories = data["categories"]
@tags = data["tags"]
@module_app = data["module_app"]
@switch_form = data["switch_form"]
greeting_card_setting = data["greeting_card_setting"]
set_input_name_for_greeting_card('greeting_card_record')
@default_greeting_card_setting = data['default_greeting_card_setting']
email_regex = data['email_regex']
%>
<% if data['layout_type'] != 'index' %>
<%= render template: "greeting_cards/#{data['layout_type']}",:locals => { :data => data, :greeting_card_setting => greeting_card_setting } %>
<% else %>
<style type="text/css">
#new-greeting_card-question .form-horizontal .control-group > *{
font-size: 1.125em;
}
.default_picker label{
display: none;
}
.greeting_card-question .control-group{
flex-wrap: wrap;
display: flex;
align-items: center;
}
.greeting_card-question .controls > *{
display: block;
}
.greeting_card-question .controls > script{
display: none;
}
.greeting_card-question .form-horizontal .control-label{
width: 24%;
max-width: 15em;
min-width: 7em;
padding: 0;
text-align: center;
}
.greeting_card-question .form-horizontal .control-group .controls{
margin: 0;
overflow: hidden;
position: relative;
min-width: 10em;
max-width: 25em;
padding-left: 0;
padding: 0.5em;
}
.greeting_card-question .single-col.form-horizontal .control-group{
width: 100%;
}
.greeting_card-question .single-col.form-horizontal .control-group .controls{
width: 100%;
display: inline-flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: flex-start;
}
.greeting_card-question .greeting_card_form.multi-col.form-horizontal div[data-list="fields"]{
float: left;
}
.greeting_card-question .greeting_card_form.multi-col.form-horizontal .form-actions{
float: left;
width: 100%;
}
.greeting_card-question .form-horizontal input[type="text"],.greeting_card-question .form-horizontal select{
width: 97%;
}
.greeting_card-question .form-horizontal input[type="text"].hasDatepicker{
width: auto;
}
.greeting_card-question .form-horizontal .form-actions{
position: relative;
padding: 1em 0 0 0;
text-align: center;
}
.greeting_card-question .controls > input[type="radio"]:not(:first-child) {
margin-left: 0.5em;
}
.greeting_card-question .checkbox-inline:first-child {
margin-left: 0.625em;
}
</style>
<%= javascript_include_tag "greeting_card/konva.min" %>
<%= javascript_include_tag "greeting_card/konva_frontend" %>
<%= javascript_include_tag "greeting_card/card_preview" %>
<%= stylesheet_link_tag "greeting_card/konva_frontend" %>
<%= stylesheet_link_tag "greeting_card/card_preview" %>
<%= stylesheet_link_tag "custom_field" %>
<%# stylesheet_link_tag "jquery-ui-timepicker-addon" %>
<script type="text/javascript">
/*
$(document).ready(function(){
$('select[name="greeting_card_record[category_id]"]').change(function(){
var category_id = $(this).val()
$(this).parents('.greeting_card-question').eq(0).find('select[name="greeting_card_record[category_id]"]').val(category_id)
var id
if ($('form#'+category_id).length != 0){
id = category_id
}
else{
id = 'greeting_card-default-form'
}
if (id != $(this).parents('form').eq(0).attr('id')){
$(this).parents('.greeting_card-question').eq(0).find('form').hide()
$(this).parents('.greeting_card-question').eq(0).find('form#'+id).show()
}
})
})*/
var datepicker_fn = $.fn.datepicker
var datepicker = $.datepicker
$(document).ready(function(){
$('input:file').change(function(e){
var fileName = e.target.files[0].name;
$(this).parents(".file-selector").eq(0).find('.filename').html(fileName);
})
})
</script>
<%# javascript_include_tag "lib/bootstrap-datetimepicker" %>
<%# javascript_include_tag "jquery.ui.datepicker.monthyearpicker" %>
<%= javascript_include_tag 'validator' %>
<link href="/assets/greeting_card/greeting_card.css" media="screen" rel="stylesheet">
<div id="new-greeting_card-question" class="greeting_card-question">
<%= @switch_form.html_safe %>
</div>
<script type='text/javascript'>
// $(function(){
// $("#button-mail").click(function(){
// if( $("#greeting_card_record_name").val()!='' ) $("#greeting_card_record_name").css('border','');
// if( $("#greeting_card_record_email").val()!='' ) $("#greeting_card_record_email").css('border','');
// if( $("#greeting_card_record_title").val()!='' ) $("#greeting_card_record_title").css('border','');
// if( $("#greeting_card_record_content").val()!='' ) $("#greeting_card_record_content").css('border','');
// if( $("#greeting_card_record_name").val()=='' ) $("#greeting_card_record_name").css('border','1px solid #F00');
// if( $("#greeting_card_record_email").val()=='' ) $("#greeting_card_record_email").css('border','1px solid #F00');
// if( $("#greeting_card_record_title").val()=='' ) $("#greeting_card_record_title").css('border','1px solid #F00');
// if( $("#greeting_card_record_content").val()=='' ) $("#greeting_card_record_content").css('border','1px solid #F00');
// });
$('.greeting_card-question .required').each(function() {
var text = $(this).text()
if (text[0]!='*'){
$(this).text('*' + text);
}
});
// $('#new-greeting_card-question form') .submit(function() {
// $.post($(this).attr('action'), $(this).serializeArray());
// return false;
// });
// });
$(document).ready(function(){
function scrollIntoView(selector, offset = 0) {
window.scroll(0, document.querySelector(selector).offsetTop - offset);
}
var email_regex = "<%=email_regex%>";
if(email_regex.length != 0){
email_regex = new RegExp(email_regex);
var fv = new FormValidator($("#new_greeting_card_record"));
fv.validate_functions.check_email = function(value){
if (email_regex.test(value)) {
return true;
}else{
return false;
}
}
var submit_flag = false;
$(".greeting_card_form").each(function(i, form){
var $form = $(form);
if($form.length != 0 && $form.find('#greeting_card_record_mail').length != 0){
$form.submit(function(){
var email_field = $(this).find('#greeting_card_record_mail');
if(!submit_flag){
submit_flag = true;
if(email_regex.test(email_field.val())){
submit_flag = false;
}else{
email_field.css("border", "2px solid red");
scrollIntoView('#greeting_card_record_mail');
alert("<%=t('greeting_card.please_check_email_format')%>");
email_field.one("input",function(){
email_field.css("border", "");
})
submit_flag = false;
return false;
}
}
})
}
})
}
})
</script>
<% end %>

View File

@ -0,0 +1,130 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<!-- <h1><%= @data['title'] %></h1> -->
<% if @data['edit_url'] %>
<%= link_to t("edit"), @data['edit_url'] %>
<% end %>
<table>
<% card = GreetingCardRecord.find(@data['greeting_card_record_id']) rescue nil %>
<% if card %>
<%
yes_trans = t('greeting_card.yes')
no_trans = t('greeting_card.no')
locale = I18n.locale.to_s
greeting_card_setting = GreetingCardCategorySetting.enabled.where(category_id: card.category_id.to_s).first
greeting_card_setting = GreetingCardSetting.first if greeting_card_setting.nil?
is_cat_record = (greeting_card_setting.class == GreetingCardCategorySetting)
tmp_greeting_card_cat_id = (is_cat_record ? greeting_card_setting.id.to_s : '')
%>
<% @data['disp_fields_infos'].each do |f, field_info| %>
<% next if f == 'recaptcha' %>
<tr>
<%
trans = field_info["trans"]
is_cat = false
is_custom = false
if f.include?("@")
field = f
is_custom = true
is_field_enable = false
if field.start_with?("default@")
f = is_cat_record ? field : field[8..-1]
v = greeting_card_setting.custom_fields[f]
if v
is_field_enable = true
end
elsif field.start_with?("custom@") && is_cat_record
if field.include?(tmp_greeting_card_cat_id)
f = field[8+tmp_greeting_card_cat_id.length..-1]
v = greeting_card_setting.custom_fields[f]
if v
is_field_enable = true
end
end
end
next if !is_field_enable
elsif f == 'greeting_card_category_id'
f = 'category_id'
is_cat = true
end
val = card[f]
if val == true || val == false
val = val ? yes_trans : no_trans
else
val = card.custom_values[f] if is_custom
type = field_info["type"]
if ["select", "radio_button", "checkbox"].include?(type)
if type == "checkbox"
val = val.values rescue []
else
val = Array(val)
end
val = val.map{|v| field_info["options"][v][locale] rescue ""}.join("<br>").html_safe
elsif ["file", "image"].include?(type)
if val.present?
val = "<a href=\"#{@data['site_host']}#{val[1]}\">#{val[0]}</a>".html_safe
end
elsif type == "date"
val = val["datetime"].values[0].values rescue []
if val.count == 2
val = val[0].to_s.gsub('-', '/') + " ~ " + val[1].to_s.gsub('-', '/')
else
val = val[0].to_s.gsub('-', '/')
end
elsif type == "instructions"
val = field_info["instructions"][locale].to_s.html_safe rescue ""
else
if is_cat
val = Category.find(val).title rescue ''
elsif f == 'usage_rule'
val = @data['usage_rule'].to_s.html_safe
elsif f == 'appointment'
val = card.appointment.strftime('%Y/%m/%d %H:%M') rescue ""
else
val = val.to_s.html_safe
end
end
end
%>
<th><%= trans %></th>
<td><%= val %></td>
</tr>
<% end %>
<% else %>
<tr>
<th><%= GreetingCardRecord.human_attribute_name(:name) %></th>
<td><%= @data['name'] %></td>
</tr>
<!-- <tr>
<th><%= GreetingCardRecord.human_attribute_name(:identity) %></th>
<td>
<% Tag.where({:id => @data['identity']}).each do |tag| %>
<%= tag.name %>
<% end %>
</td>
</tr> -->
<tr>
<th><%= GreetingCardRecord.human_attribute_name(:mail) %></th>
<td><%= @data['mail'] %></td>
</tr>
<tr>
<th><%= GreetingCardRecord.human_attribute_name(:phone) %></th>
<td><%= @data['phone'] %></td>
</tr>
<!-- <tr>
<th><%= GreetingCardRecord.human_attribute_name(:fax) %></th>
<td><%= @data['fax'] %></td>
</tr> -->
<tr>
<th><%= GreetingCardRecord.human_attribute_name(:name) %></th>
<td><%= @data['name'].to_s.gsub(/[(\n)(\r)]/, "\n" => "<br/>", "\r" => "" ).html_safe %></td>
</tr>
<% end %>
</table>
<p>此為系統自動發信,請勿直接回覆</p>
</body>
</html>

View File

@ -0,0 +1,18 @@
<table class="table">
<thead>
<tr class="bg-primary">
<th><%= t('categories') %></th>
<th><%= t('title') %></th>
</tr>
</thead>
<tbody>
<% data['greeting_card_records'].each do |greeting_card_record| %>
<tr>
<td><%= greeting_card_record.category.title %></td>
<td><%= link_to greeting_card_record.title,"#{data['url']}?item=#{greeting_card_record.id}",title: greeting_card_record.title %></td>
</tr>
<% end %>
</tbody>
</table>
<% total_pages = data['greeting_card_records'].total_pages %>
<%= create_pagination(total_pages).html_safe if total_pages > 1 %>

View File

@ -0,0 +1,9 @@
<link href="/assets/greeting_card/greeting_card.css" media="screen" rel="stylesheet">
<div class="form-horizontal">
<h2>
<%= t('greeting_card.see_email') %>
<div class="form-actions">
<a class="btn" href="<%= OrbitHelper.request.path_info %>"><%=t('greeting_card.go_back')%></a>
</div>
</h2>
</div>

View File

@ -0,0 +1,86 @@
<% greeting_card = data['greeting_card_record'] %>
<style type="text/css">
.greeting_card-question .form-horizontal .control-group > *{
font-size: 1.125em;
}
.default_picker label{
display: none;
}
.greeting_card-question .control-group{
flex-wrap: wrap;
display: flex;
width: 100%;
align-items: center;
}
.greeting_card-question .controls > *{
display: block;
}
.greeting_card-question .controls > script{
display: none;
}
.greeting_card-question .form-horizontal .control-label{
width: 24%;
max-width: 15em;
min-width: 14em;
padding: 0;
text-align: center;
}
.greeting_card-question .form-horizontal .control-group .controls{
margin: 0;
display: inline-flex;
align-items: center;
overflow: hidden;
position: relative;
min-width: 10em;
max-width: 20em;
padding-left: 0;
width: 70%;
padding: 0.5em;
justify-content: center;
}
.greeting_card-question .form-horizontal input[type="text"],.greeting_card-question .form-horizontal select{
width: 97%;
max-width: 13.75em;
}
.greeting_card-question .form-horizontal .form-actions{
position: relative;
padding: 1em 0 0 0;
text-align: center;
}
.greeting_card-question .checkbox-inline:first-child {
margin-left: 0.625em;
}
</style>
<%= stylesheet_link_tag "custom_field" %>
<link href="/assets/greeting_card/greeting_card.css" media="screen" rel="stylesheet">
<div class="greeting_card-question">
<div class="form-horizontal">
<div class="control-group">
<%= label_tag nil,t('category'), :class=> 'control-label' %>
<div class="controls">
<%= label_tag nil,(greeting_card.category.title rescue nil), class: 'control-label' %>
</div>
</div>
<div class="control-group">
<%= label_tag nil,t('title'), :class=> 'control-label' %>
<div class="controls">
<%= label_tag nil,greeting_card.title, :class=> 'control-label' %>
</div>
</div>
<%= greeting_card_setting.custom_fields.collect do |k,v|
required_pattern = v['required']=='true' ? '*' : ''
"<div class=\"control-group\">
<label class=\"control-label\">#{required_pattern}#{v['field'][I18n.locale]}</label>
<div class=\"controls\">
#{show_on_front(k,v,greeting_card,true)}
</div>
</div>"
end.join.html_safe %>
<div class="control-group">
<%= label_tag nil,t('mongoid.attributes.greeting_card_record.reply'), :class=> 'control-label' %>
<div class="controls">
<%= greeting_card.reply %>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,8 @@
<link href="/assets/greeting_card/greeting_card.css" media="screen" rel="stylesheet">
<div class="form-horizontal">
<p>驗證失敗,請重新填寫!</p>
<p>Failed to greeting_card questions, please re-greeting_card!</p>
<div class="form-actions">
<input name="goback" type="button" class="btn" onclick="window.history.go(-1);" onkeypress="window.history.go(-1);" value="<%=t('greeting_card.go_back')%>">
</div>
</div>

View File

@ -0,0 +1,14 @@
<link href="/assets/greeting_card/greeting_card.css" media="screen" rel="stylesheet">
<div class="form-horizontal">
<h2>
<% text = GreetingCardAcknowledgement.first.content[I18n.locale] rescue t('greeting_card.thank_text')
text = t('greeting_card.thank_text') if text.to_s.empty?
%>
<%= text.html_safe %>
<div class="form-actions">
<a class="btn" href="<%= OrbitHelper.request.path_info %>"><%=t('greeting_card.go_back')%></a>
</div>
</h2>
</div>

View File

@ -0,0 +1,13 @@
<style>
.error_msg {
color: red;
}
.success_msg {
color: green;
}
</style>
<% if @already_verify %>
<div class="error_msg"><%= t('greeting_card.this_link_has_expired') %></div>
<% else %>
<div class="success_msg"><%= t('greeting_card.verify_success') %></div>
<% end %>

View File

@ -0,0 +1,4 @@
<%# javascript_include_tag "//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"%>
<%# javascript_include_tag "/assets/lib/jquery-ui-1.12.1/jquery-ui.min" %>
<%= render :template => 'layouts/back_end' %>
<%# stylesheet_link_tag "jquery-ui-timepicker-addon" %>

4
bin/rails Normal file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'

183
config/locales/en.yml Normal file
View File

@ -0,0 +1,183 @@
en:
module_name:
greeting_card: Greeting Card
situation: Status
sex: Sex
greeting_card:
preview: Preview
automatically_send: Automatically send
regular_date: Regular date
birthday: Birthday
lineheight: Line Height
word_art: Word Art
borderline: Borderline
fill: Fill
all_greeting_cards: All Greeting Cards
layout_design: Layout Design
card_background: Card background
only_logged_in_users: Only logged-in users
sender_mail: Sender email
recipients: Recipients
_recipients: Recipients
greetings: Greetings
sending_time: Sending time
start: "Start"
end: "End"
options: "Options"
please_select: '--Please Select--'
default_option: Default Option
batch_modify_status: "Batch Modify Status"
delete_selected: "Delete Selected"
backend_table_setting: Backend Table Setting
greeting_card_category_id: Category
default_head_for_table: Default Head for Table
situation: Status
display_fields_setting: Display Fields Setting
go_back: "Go back"
this_field_is_default_custom_fields: "This field is default custom fields(Not editable)"
display_discard_fields: "Display discard fields"
are_you_sure_to_apply: "Are you sure to apply?"
are_you_sure_to_discard: "Are you sure to discard?"
apply: "Apply"
discard: "Discard"
apply_all: "Apply All"
discard_changes: "Discard Changes"
default_custom_fields: "Default custom fields"
serial_number: "No."
the_same_as_field_name: "The same as Field Name"
recover_data: "Recover Data"
are_you_sure_to_recover_data: "Are you sure to recover data?"
are_you_sure_to_switch_to_default_setting: "Are you sure to switch to default setting?"
are_you_sure_to_cancel_edit: "Are you sure to cancel edit?"
cancel_edit: "Cancel Edit"
instructions: "Instructions"
clone_default_setting: "Clone Default Setting"
use_default: "Use Default"
default: "Default"
new_status: "New Status"
status: "Status"
action: "Action"
ip: "IP"
ticket_status: "Ticket Status"
title_layout: Title layout
single_column: Single Column in One Row
two_column: Two Column in One Row
please_check_email_format: "Please check email format!"
enable: Enable
email_regex: Email validation regex
verify_link: Verify link
validation_email_content: Validation Email Content
email_verification_notification: Email verification notification
email_automation_hint: "This is an automatic email sent by the system, please do not reply directly."
please_save: Please click "Save Order" button when you done.
save_order: Save Order
order_fields: Fields Order
sort_number: Sort Number(ascending)
field_name: Field Name
more_title: See more Greeting Card history
save_name: Save FileName
usage_rule: Usage rule
agree_show_checkbox: Agree card content display on website checkbox
agree_usage_checkbox: Agree related usage rule checkbox
setting_type: Setting Type
field_setting: Field Setting
modify: Modify
select_category: '-----Select a category-----'
save_data: Save as pdf
print: Print
created_at: Creation time
greeting_card_time: Creation Time
custom_format_explain: use checkbox format to show custom-field's value
output_result: Output result
example: Example
example_explain: 'When custom field is test1、test2、test3, and being filled with a、b、c'
like: 'Like '
and_so_on: and so on
custom1: the first custom field
custom2: the second custom field
custom3: the third custom field
can_be_filled_with: can be filled with
show_title_trans: which will show the title's label being translated on now local
custom_explain: custom field which will automatically include all custom field to table but exclude the fields that are added
explanation: Explanation
name_mask: 'Name only show the first word,for example: 蔡**'
category_setting: Category fields
print_format: Print Format
file_field: File Field
image_field: Image Field
upload_file: Upload File
upload_image: Upload Image
no_index_page: There are no page for Greeting Card module created at site struture.
thank_text: We will reply as soon as posible,thank you.
is_email_not_confirmed: Email Not Confirmed
is_waiting: Pending
is_processed: Processed
is_referral: Rreferral
is_published: Processed and Published
'yes': 'Yes'
'no': 'No'
system_Email: System Email
fax: Fax
paper: Paper
required: Required
datepicker: Select a Date
enable_range_setting: Enable Time Range Setting
format: Format
add_new_options: Add new options
field: Field
prompt_word: Prompt Word
option_name: Option Name
field_name: Field Name
whether_open: Whether to open it
setting: Default fields
exports: Export
reply: Reply
reply_success: Reply success
to: To
widget:
index: Form
save_success: Successfully saved
teacher: Teacher
stuff: Stuff
student: Student
schoolfellow: Schoolfellow
others: Others
acknowledgements: Thank Note
admins: Administrator
new_card: New Greeting Card
verify_success: "Verify Successfully!"
this_link_has_expired: "This Link has been clicked and expired!"
modified_by: Modified by
remark: Remark
attachment: Attachment
updated_at: Updated at
must_verify_email: The form can only be filled in after email verification.
go_to_form: Go to Form
see_email: "Please check your email, so you can fill out the form."
mongoid:
attributes:
greeting_card_record:
card: Card
image: Image
usage_rule: Usage rule
agree_usage: Agree related usage rule
greeting_card_category_id: Greeting Card Category
recaptcha: Recaptcha
name: Sender's name
sender_mail: Sender email
recipients: Recipients
greetings: Greetings
sending_time: Sending time
title: Title
reply: Reply
created_at: Creation time
content: Content
comment: Comment
status: Status
send_email: Whether to reply email
agree_show: Do you agree on displaying your request and our reply on the webpage without your personal information?
agree_show_explain: Whether to agree on displaying your request and our reply on the webpage without your personal information?
reviewer: Reviewer
review_time: Review Time

190
config/locales/zh_tw.yml Normal file
View File

@ -0,0 +1,190 @@
zh_tw:
module_name:
greeting_card: 賀卡
situation: 狀態
recaptcha:
errors:
verification_failed: 驗證碼錯誤
greeting_card:
preview: 預覽
automatically_send: 自動發信
regular_date: 固定日期
birthday: 會員生日
lineheight: 行高
word_art: 文字藝術
borderline: 邊線
fill: 填滿
all_greeting_cards: 全部賀卡
layout_design: 賀卡排版設定
card_background: 卡片底圖
only_logged_in_users: 僅開放登入者使用
sender_mail: 寄件人電子郵件
recipients: 收件人電子郵件
_recipients: 收件人
greetings: 祝賀詞
sending_time: 寄送時間
start: "開始"
end: "結束"
options: "選項"
please_select: '--請選擇--'
default_option: 預設選項
batch_modify_status: "批次修改狀態"
delete_selected: "刪除所選"
backend_table_setting: 後台表格設定
greeting_card_category_id: 類別
default_head_for_table: 表格預設表頭
situation: 狀態
display_fields_setting: 顯示欄位設定
go_back: "回上一頁"
this_field_is_default_custom_fields: "此欄位為預設客製化欄位(不可修改)"
display_discard_fields: "顯示捨棄的欄位"
are_you_sure_to_apply: "您確定要套用嗎?"
are_you_sure_to_discard: "您確定要捨棄嗎?"
apply: "套用"
discard: "捨棄"
apply_all: "套用全部"
discard_changes: "捨棄變更"
default_custom_fields: "預設客製化欄位"
serial_number: "單號"
the_same_as_field_name: "與欄位名稱相同"
recover_data: "復原資料"
are_you_sure_to_recover_data: "您確定要復原資料嗎?"
are_you_sure_to_switch_to_default_setting: "您確定要切換成預設設定嗎?"
are_you_sure_to_cancel_edit: "您確定要取消修改嗎?"
cancel_edit: "取消修改"
instructions: "說明文字 Instructions"
clone_default_setting: "複製預設設定"
use_default: "使用預設"
default: "預設"
new_status: "新增狀態"
status: "狀態"
action: "動作"
ip: "IP"
ticket_status: "服務單狀態設定"
title_layout: 題目樣式
single_column: 單欄式
two_column: 兩欄式
please_check_email_format: "請檢察email是否正確!"
enable: 啟用
email_regex: Email驗證regex
verify_link: 驗證連結
validation_email_content: 驗證信內容
email_verification_notification: 電子郵件驗證通知
email_automation_hint: "此為系統自動發信,請勿直接回覆"
please_save: 調整完後, 請點選"儲存順序"
save_order: 儲存順序
order_fields: 排序欄位
sort_number: 排序數(升序)
field_show_name: 欄位名稱
more_title: 查看更多賀卡紀錄
save_name: 檔案儲存名稱
usage_rule: 使用規範
agree_show_checkbox: 同意卡片內容刊載於網站勾選框
agree_usage_checkbox: 同意相關使用規範勾選框
setting_type: 設定類型
field_setting: 欄位設定
modify: 修改
select_category: '-----選擇類別-----'
save_data: 存為pdf
print: 列印
greeting_card_time: 填寫時間
custom_format_explain: 使用checkbox樣式來呈現單選或多選的欄位
output_result: 輸出結果
example: 範例
example_explain: '當客製化欄位為: test1、test2、test3被填入: a、b、c'
like:
and_so_on: 以此類推
custom1: 客製化欄位的第一個欄位
custom2: 客製化欄位的第二個欄位
custom3: 客製化欄位的第三個欄位
custom_explain: 客製化欄位(會自動將所有新增的客製欄位帶入表格,但排除已使用數字加入的欄位)
can_be_filled_with: 可填入
show_title_trans: 會顯示當前語言的標籤翻譯
explanation: 說明
name_mask: 姓名只顯示第一個字,如蔡**
category_setting: 類別欄位設計
print_format: 列印格式
file_field: 檔案欄位
image_field: 照片欄位
upload_file: 上傳檔案
upload_image: 上傳圖片
no_index_page: 前台頁面尚未被建立,請前往網站架構設定,謝謝。
thank_text: 我們已經收到您的預約,期待您的蒞臨,謝謝
is_email_not_confirmed: Email未驗證
is_waiting: 待處理
is_processed: 已處理
is_referral: 轉介其他單位
is_published: 已處理並發佈網頁
'yes':
'no':
system_Email: 系統發信
phone: 電話
fax: 傳真
paper: 回覆函
required: 必填
datepicker: 選擇日期
enable_range_setting: 啟用時間區段設定
format: 格式
add_new_options: 新增選項
field: 欄位
prompt_word: 提示文字
option_name: 選項名稱
field_name: 欄位名稱
whether_open: 是否開啟
setting: "基本欄位設定(預設值)"
name: 寄件者姓名
created_at: 填寫時間
status: 狀態
exports: 匯出
reply: 問題回覆
reply_success: 回覆成功
to:
yes:
no:
widget:
index: 表單
save_success: 儲存成功
teacher: 教師
stuff: 職員
student: 學生
schoolfellow: 校友
others: 其他
acknowledgements: 感謝詞
admins: 管理者
new_card: 新的賀卡
verify_success: "驗證成功"
this_link_has_expired: "此連結已經點選並已失效!"
modified_by: 修改者
remark: 備註
attachment: 附件
updated_at: 更新時間
must_verify_email: Email驗證後才可開始填寫
go_to_form: 前往表單
see_email: "請確認email驗證信以開始填寫表單。"
mongoid:
attributes:
greeting_card_record:
card: 賀卡
image: 賀卡圖片
usage_rule: 使用規範
agree_usage: 同意相關使用規範
greeting_card_category_id: 賀卡類別
recaptcha: 驗證碼
name: 寄件者姓名
sender_mail: 寄件人電子郵件
recipients: 收件人電子郵件
greetings: 祝賀詞
sending_time: 寄送時間
title: 標題
reply: 回覆
created_at: 填寫時間
content: 內容
comment: 備註
status: 狀態
send_email: 是否回信
agree_show: 是否同意您提出之需求及卡片內容以不呈現填寫者資訊方式刊載於網站供他人參考?
agree_show_explain: 是否同意刊載於網站給他人參考
reviewer: 審核者
review_time: 審核時間

43
config/routes.rb Normal file
View File

@ -0,0 +1,43 @@
Rails.application.routes.draw do
locales = Site.first.in_use_locales rescue I18n.available_locales
scope "(:locale)", locale: Regexp.new(locales.join("|")) do
namespace :admin do #backend
resources :greeting_cards do
collection do
delete 'delete'
post 'batch_modify_status'
get ':id/print', to: 'greeting_cards#print'
get 'export'
get 'setting'
get 'backend_table_setting'
get 'category_setting'
post 'get_category_setting_partial'
post 'get_category_setting_field'
post 'category_setting_save'
get 'category_setting_delete'
post 'switch_to_default_setting'
get 'get_new_category_setting_index'
get 'layout_design'
get 'ticket_status'
post 'get_ticket_status'
post 'update_ticket_status'
delete 'delete_ticket_status'
post 'layout_design_save'
post 'setting_save'
post 'greeting_card_list_setting_save'
post 'get_new_setting_index'
post 'get_new_category_setting_index'
post 'export', to: 'greeting_cards#do_export'
get 'order_fields'
post 'update_order_fields'
post 'apply_default_custom_fields'
end
end
resources :greeting_card_acknowledgements
resources :greeting_card_admins
end
resources :greeting_cards #fronted
get "/xhr/greeting_cards/verify_email/:id" => "greeting_cards#verify_email"
end
end

43
greeting_card.gemspec Normal file
View File

@ -0,0 +1,43 @@
$:.push File.expand_path("../lib", __FILE__)
# Maintain your gem's version:
require "greeting_card/version"
bundle_update_flag = ARGV[0]=='update' || ARGV[0]=='install'
if bundle_update_flag
app_path = File.expand_path(__dir__)
template_path = ENV['PWD'] + '/app/templates'
all_template = Dir.glob(template_path+'/*/')
puts 'copying greeting_card module'
all_template.each do |folder|
if folder.split('/')[-1] != 'mobile'
begin
system ('cp -r '+ app_path + '/modules/ ' + folder)
rescue
puts 'error copy'
end
end
end
end
#syst
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
s.name = "greeting_card"
s.version = GreetingCard::VERSION
s.authors = ["RulingDigital"]
s.email = ["orbit@rulingcom.com"]
s.homepage = "http://www.rulingcom.com"
s.summary = "GreetingCard for orbit"
s.description = "GreetingCard for orbit"
s.license = "MIT"
s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"]
s.test_files = Dir["test/**/*"]
s.metadata = {
"_require" => "#{File.expand_path("../app/models/greeting_card_setting", __FILE__)}",
"global_hash" => "{last_ticket_key: (GreetingCardSetting.pluck(:last_ticket_key)[0].to_i rescue 0), last_serial_number: (GreetingCardSetting.pluck(:last_serial_number)[0].to_i rescue 0)}"
}
# s.add_dependency('ttfunk', '~> 1.5')
# s.add_dependency('rmagick', '~> 2.16')
s.add_dependency('freetype')
# s.add_dependency ~> "gotcha"
end

4
lib/greeting_card.rb Normal file
View File

@ -0,0 +1,4 @@
require "greeting_card/engine"
module GreetingCard
end

184
lib/greeting_card/engine.rb Normal file
View File

@ -0,0 +1,184 @@
module GreetingCard
class Engine < ::Rails::Engine
initializer "greeting_card" do
Rails.application.config.to_prepare do
locales = Site.first.in_use_locales rescue [:en,:zh_tw]
begin
t_data0 = locales.collect{|l| Dir["#{ENV['PWD']}/config/locales/#{l.to_s}.yml"]}.flatten.map{|yaml_file| YAML.load(File.read(yaml_file))}
t_data1 = Dir["#{GreetingCard::Engine.root}/config/locales/*.yml"].map{|yaml_file| YAML.load(File.read(yaml_file))}
data_item = {}
key_item1 = {}
value_item1 = {}
value_item2 = {}
t_data0.each do |t_data|
v = t_data.values
k = t_data.keys[0]
key_item1[k] = v[0]['theme']
end
t_data1.each do |t_data|
v = t_data.values
k = t_data.keys[0]
value_item1[k] = v[0]['greeting_card']['widget']['index']
value_item2[k] = v[0]['greeting_card']['is_published']
end
data_item[key_item1] = [value_item1,value_item2]
rescue => e
puts ['error in greeting_card',e]
end
begin
require File.join(GreetingCard::Engine.root, 'app/models/greeting_card_setting')
require File.join(GreetingCard::Engine.root, 'app/models/greeting_card_list_setting')
require File.join(GreetingCard::Engine.root, 'app/models/greeting_card_category_setting')
require File.join(GreetingCard::Engine.root, 'app/models/greeting_card_setting_index')
if defined?(GreetingCardSetting)
greeting_card_setting = GreetingCardSetting.first
if greeting_card_setting.nil?
greeting_card_setting = GreetingCardSetting.create()
elsif GreetingCardSetting.count > 1
GreetingCardSetting.all[1..-1].each do |a|
a.destroy
end
end
if greeting_card_setting.email_regex_enable
GreetingCardCategorySetting.all.update_all(email_regex_enable: greeting_card_setting.email_regex_enable,email_regex: greeting_card_setting.email_regex)
end
GreetingCardCategorySetting.all.each do |greeting_card_category_setting|
sort_number = greeting_card_category_setting.sort_number
have_custom_key = false
sort_number.keys.each do |sort_number_key|
have_default_key ||= sort_number_key.include?("default@default@")
have_custom_key ||= sort_number_key.include?("custom@")
end
if !have_custom_key
new_sort_number = {}
sort_number.keys.each do |sort_number_key|
new_sort_number_key = sort_number_key
if sort_number_key.include?("default@default@")
new_sort_number_key = sort_number_key.sub(/default@/, '')
else
new_sort_number_key = sort_number_key.sub(/default@/, "custom@#{greeting_card_category_setting.id}@")
end
new_sort_number[new_sort_number_key] = sort_number[sort_number_key]
end
greeting_card_category_setting.sort_number = new_sort_number
greeting_card_category_setting.save
end
end
end
if defined?(GreetingCardListSetting)
greeting_card_list_setting = GreetingCardListSetting.first
if greeting_card_list_setting.nil?
greeting_card_list_setting = GreetingCardListSetting.create()
elsif GreetingCardListSetting.count > 1
GreetingCardListSetting.where(:category_id=>nil)[1..-1].each do |a|
a.destroy
end
end
end
if defined?(GreetingCardSettingIndex)
if GreetingCardSettingIndex.first.nil?
GreetingCardSettingIndex.create()
elsif GreetingCardSettingIndex.count > 1
GreetingCardSettingIndex.all[1..-1].each do |greeting_card_setting_index|
greeting_card_setting_index.destroy
end
end
end
rescue => e
puts ['GreetingCardSetting not found',e]
end
OrbitApp.registration "GreetingCard", :type => "ModuleApp" do
module_label "module_name.greeting_card"
base_url File.expand_path File.dirname(__FILE__)
begin
set_keyword_contstraints ['/greeting_cards']
rescue => e
puts ['the site is too old']
end
widget_methods ["widget"]
widget_settings [{"data_count"=>10}]
taggable "GreetingCardRecord"
begin
show_option_items data_item
rescue => e
puts ['there_was_no_show_option_method',e]
end
categorizable
authorizable
frontend_enabled
# data_count 1..10
side_bar do
head_label_i18n 'module_name.greeting_card', icon_class: "icon-gift"
available_for "users"
active_for_controllers (['admin/greeting_cards'])
head_link_path "admin_greeting_cards_path"
context_link 'greeting_card.all_greeting_cards',
:link_path=>"admin_greeting_cards_path" ,
:priority=>1,
:active_for_action=>{'admin/greeting_cards'=>'index'},
:available_for => 'users'
context_link 'greeting_card.setting',
:link_path=>"setting_admin_greeting_cards_path" ,
:priority=>2,
:active_for_action=>{'admin/greeting_cards'=>'setting'},
:available_for => 'managers'
context_link 'greeting_card.category_setting',
:link_path=>"category_setting_admin_greeting_cards_path" ,
:priority=>3,
:active_for_action=>{'admin/greeting_cards'=>'category_setting'},
:available_for => 'sub_managers'
context_link 'greeting_card.order_fields',
:link_path=>"order_fields_admin_greeting_cards_path" ,
:priority=>4,
:active_for_action=>{'admin/greeting_cards'=>'order_fields'},
:available_for => 'sub_managers'
# context_link 'greeting_card.print_setting',
# :link_path=>"print_setting_admin_greeting_cards_path" ,
# :priority=>5,
# :active_for_action=>{'admin/greeting_cards'=>'print_setting'},
# :available_for => 'sub_managers'
context_link 'greeting_card.layout_design',
:link_path=>"layout_design_admin_greeting_cards_path" ,
:priority=>5,
:active_for_action=>{'admin/greeting_cards'=>'layout_design'},
:available_for => 'sub_managers'
context_link 'categories',
:link_path=>"admin_module_app_categories_path" ,
:link_arg=>"{:module_app_id=>ModuleApp.find_by(:key=>'greeting_card').id}",
:priority=>7,
:active_for_action=>{'admin/greeting_cards'=>'categories'},
:active_for_category => 'GreetingCard',
:available_for => 'managers'
# context_link 'tags',
# :link_path=>"admin_module_app_tags_path" ,
# :link_arg=>"{:module_app_id=>ModuleApp.find_by(:key=>'greeting_card').id}",
# :priority=>7,
# :active_for_action=>{'admin/greeting_card'=>'tags'},
# :active_for_tag => 'GreetingCard',
# :available_for => 'managers'
context_link 'greeting_card.acknowledgements',
:link_path=>"admin_greeting_card_acknowledgements_path" ,
:priority=>8,
:active_for_action=>{'admin/greeting_cards'=>'acknowledgements'},
:available_for => 'managers'
# context_link 'greeting_card.admins',
# :link_path=>"admin_greeting_card_admins_path" ,
# :priority=>9,
# :active_for_action=>{'admin/greeting_cards'=>'admins'},
# :available_for => 'managers'
# context_link 'greeting_card.exports',
# :link_path=>"export_admin_greeting_cards_path" ,
# :priority=>10,
# :active_for_action=>{'admin/greeting_cards'=>'exports'},
# :available_for => 'managers'
end
end
end
end
end
end

View File

@ -0,0 +1,3 @@
module GreetingCard
VERSION = "0.0.1"
end

View File

@ -0,0 +1,4 @@
# desc "Explaining what the task does"
# task :greeting_card do
# # Task goes here
# end

View File

@ -0,0 +1,117 @@
<div class="widget-greeting_card widget1">
<style type="text/css">
#new-greeting_card-question .form-horizontal .control-group > *{
font-size: 1.125em;
}
.default_picker label{
display: none;
}
.greeting_card-question .control-group{
flex-wrap: wrap;
display: flex;
width: 100%;
align-items: flex-start;
}
.greeting_card-question .controls > *{
display: block;
}
.greeting_card-question .controls > script{
display: none;
}
.greeting_card-question .form-horizontal .control-label{
width: 24%;
max-width: 15em;
min-width: 7em;
padding: 0;
text-align: center;
}
.greeting_card-question .form-horizontal .control-group .controls{
margin: 0;
display: inline-flex;
align-items: flex-start;
overflow: hidden;
position: relative;
min-width: 10em;
max-width: 25em;
padding-left: 0;
width: 100%;
padding: 0.5em;
justify-content: flex-start;
}
.greeting_card-question .form-horizontal input[type="text"],.greeting_card-question .form-horizontal select{
width: 97%;
}
.greeting_card-question .form-horizontal input[type="text"].hasDatepicker{
width: auto;
}
.greeting_card-question .form-horizontal .form-actions{
position: relative;
padding: 1em 0 0 0;
text-align: center;
}
.greeting_card-question .controls > input[type="radio"]:not(:first-child) {
margin-left: 0.5em;
}
</style>
<link href="/assets/custom_field.css" media="screen" rel="stylesheet">
<script src="/assets/validator"></script>
<link href="/assets/greeting_card/greeting_card.css" media="screen" rel="stylesheet">
<h3 class="widget-title">
<span>{{widget-title}}</span>
</h3>
<div id="new-greeting_card-question" class="greeting_card-question">
{{switch_form}}
</div>
<script type='text/javascript'>
$('.greeting_card-question .required').each(function() {
var text = $(this).text()
if (text[0]!='*'){
$(this).text('*' + text);
}
});
$(function(){
var fv = new FormValidator($("#new_greeting_card_record"));
fv.validate_functions.check_email = function(value){
reg = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9])+$/;
if (reg.test(value)) {
return true;
}else{
return false;
}
}
})
$(document).ready(function(){
function scrollIntoView(selector, offset = 0) {
window.scroll(0, document.querySelector(selector).offsetTop - offset);
}
var email_regex = "{{email_regex}}";
if(email_regex.length != 0){
email_regex = new RegExp(email_regex);
var submit_flag = false;
$(".greeting_card_form").each(function(i, form){
var $form = $(form);
var email_field = $form.find('#greeting_card_record_mail');
if($form.length != 0 && email_field.length != 0){
$form.submit(function(){
if(!submit_flag){
submit_flag = true;
if(email_regex.test(email_field.val())){
submit_flag = false;
}else{
email_field.css("border", "2px solid red");
scrollIntoView('#greeting_card_record_mail');
alert("<%=t('greeting_card.please_check_email_format')%>");
email_field.one("input",function(){
email_field.css("border", "");
})
submit_flag = false;
return false;
}
}
})
}
})
}
})
</script>
</div>

View File

@ -0,0 +1,18 @@
<div class="widget-greeting_cards widget1">
<h3 class="widget-title">
<span>{{widget-title}}</span>
</h3>
<table class="table">
<thead>
<tr data-level="0" data-list="th" class="bg-primary">
<th>{{td}}</th>
</tr>
</thead>
<tbody data-level="0" data-list="greeting_card_records">
<tr data-level="1" data-list="td">
<td>{{content}}</td>
</tr>
</tbody>
</table>
<div style="background: #337ab7; border: 1px solid rgb(204, 204, 204); padding: 5px 10px; text-align: right;"><span style="color:inherit;"><a href="{{more_href}}" title="{{more_title}}"><span style="color:#FFFFFF;">{{more_title}}</span></a></span></div>
</div>

View File

@ -0,0 +1,20 @@
{
"widgets" : [
{
"filename" : "greeting_card_widget_form",
"name" : {
"zh_tw" : "1. 模組標題、發問介面",
"en" : "1. widget-title, question"
},
"thumbnail" : "thumb.png"
},
{
"filename" : "greeting_card_widget_list",
"name" : {
"zh_tw" : "2. 模組標題、 發佈回覆列表",
"en" : "2. widget-title, published list"
},
"thumbnail" : "thumb.png"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB