diff --git a/app/assets/javascripts/admin.coffee b/app/assets/javascripts/admin.coffee index eadb77a..3158abc 100644 --- a/app/assets/javascripts/admin.coffee +++ b/app/assets/javascripts/admin.coffee @@ -37,21 +37,69 @@ #=require sheet_prices +#= require freeze-table + portlet_to_move = false content_type_to_move =false window.disable_portlet_select = false window.portlet_change = false +@set_table_header = -> + header_size = $("#qi_header_wrapper").outerHeight() + + header_size = header_size - 4 + + + + +$ -> + + #$('.data_table').DataTable + # info: false + # scrollX: true + #scrollY: "800px" + # scrollCollapse: false + # paging: false + # ordering: false + # keys: true + # fixedHeader: true + # searching: false + # colReorder: true + + #fixedColumns: + # leftColumns: 2 + # rightColumns: 1 + + + $(window).on "resize", -> + resize() + set_table_header() + + + + + + + + + + resize() + set_table_header() + + @resize = () -> header_size = $("#admin_nav").outerHeight() - if $(".qi_header").length > 0 - - header_size = header_size + $(".qi_header").first().outerHeight() + header_size = $("#qi_header_wrapper").outerHeight() $("body").css("padding-top", header_size+"px") - + + table_size = ($(window).height() - $("#qi_header_wrapper").outerHeight() - 100)+"px" + + + + @edit_watcher = (element_type, element_id, key) -> diff --git a/app/assets/javascripts/freeze-table.js b/app/assets/javascripts/freeze-table.js new file mode 100644 index 0000000..526201a --- /dev/null +++ b/app/assets/javascripts/freeze-table.js @@ -0,0 +1,804 @@ +/** + * RWD Table with freezing head and columns for jQuery + * + * @author Nick Tsai + * @version 1.3.0 + * @see https://github.com/yidas/jquery-freeze-table + */ +(function ($, window) { + + 'use strict'; + + /** + * Main object + * + * @param {element} element + * @param {object} options + */ + var FreezeTable = function(element, options) { + + // Target element initialization + this.$tableWrapper = $(element).first(); + + // Options + this.options = options || {}; + this.namespace = this.options.namespace || 'freeze-table'; + this.callback; + this.scrollBarHeight; + this.shadow; + this.fastMode; + this.backgroundColor; + this.scrollable; + + // Caches + this.$table = this.$tableWrapper.children("table"); + this.$container = ((typeof this.options.container !== 'undefined') && this.options.container && $(this.options.container).length) ? $(this.options.container) : $(window); + this.$headTableWrap; + this.$columnTableWrap; + this.$columnHeadTableWrap; + this.$scrollBarWrap; + this.fixedNavbarHeight; + this.isWindowScrollX = false; + + // Static class names for clone wraps + this.headWrapClass = 'clone-head-table-wrap'; + this.columnWrapClass = 'clone-column-table-wrap'; + this.columnHeadWrapClass = 'clone-column-head-table-wrap'; + this.scrollBarWrapClass = 'clone-scroll-bar-wrap'; + + this.init(); + + return this; + } + + /** + * Initialization + */ + FreezeTable.prototype.init = function() { + + // Element check + if (!this.$table.length) { + throw "The element must contain a table dom"; + } + + /** + * Update Mode + */ + if (this.options==='update') { + + this.destroy(); + this.options = this.$tableWrapper.data('freeze-table-data'); + } + else if (this.options==='resize') { + + this.options = this.$tableWrapper.data('freeze-table-data'); + // Get selected FreezeTable's namespace + this.namespace = this.options.namespace || this.namespace; + this.resize(); + // Skip init for better performance usage + return; + } + else { + // Save to DOM data + this.$tableWrapper.data('freeze-table-data', this.options); + } + + /** + * Options Setting + */ + var options = this.options; + var freezeHead = (typeof options.freezeHead !== 'undefined') ? options.freezeHead : true; + var freezeColumn = (typeof options.freezeColumn !== 'undefined') ? options.freezeColumn : true; + var freezeColumnHead = (typeof options.freezeColumnHead !== 'undefined') ? options.freezeColumnHead : true; + var scrollBar = (typeof options.scrollBar !== 'undefined') ? options.scrollBar : false; + var fixedNavbar = options.fixedNavbar || '.navbar-fixed-top'; + var callback = options.callback || null; + this.namespace = this.options.namespace || this.namespace; + // Default to get window scroll bar height + this.scrollBarHeight = ($.isNumeric(options.scrollBarHeight)) ? options.scrollBarHeight : (window.innerWidth - document.documentElement.clientWidth); + this.shadow = (typeof options.shadow !== 'undefined') ? options.shadow : false; + this.fastMode = (typeof options.fastMode !== 'undefined') ? options.fastMode : false; + this.backgroundColor = (typeof options.backgroundColor !== 'undefined') ? options.backgroundColor : 'white'; + this.scrollable = (typeof options.scrollable !== 'undefined') ? options.scrollable : false; + + // Get navbar height for keeping fixed navbar + this.fixedNavbarHeight = (fixedNavbar) ? $(fixedNavbar).outerHeight() || 0 : 0; + + // Check existence + if (this.isInit()) { + this.destroy(); + } + + // Release height of the table wrapper + if (!this.scrollable) { + this.$tableWrapper.css('height', '100%') + .css('min-height', '100%') + .css('max-height', '100%'); + } + + /** + * Building + */ + // Switch for freezeHead + if (freezeHead) { + this.buildHeadTable(); + } + // Switch for freezeColumn + if (freezeColumn) { + this.buildColumnTable(); + // X scroll bar + this.$tableWrapper.css('overflow-x', 'scroll'); + } + // Switch for freezeColumnHead + if (freezeColumnHead && freezeHead && freezeColumn) { + this.buildColumnHeadTable(); + } + // Switch for scrollBar + if (scrollBar) { + this.buildScrollBar(); + } + + // Body scroll-x prevention + var detectWindowScroll = (function (){ + // If body scroll-x is opened, close library to prevent Invalid usage + if (this.$container.scrollLeft() > 0) { + // Mark + this.isWindowScrollX = true; + // Hide all components + if (this.$headTableWrap) { + this.$headTableWrap.css('visibility', 'hidden'); + } + if (this.$columnTableWrap) { + this.$columnTableWrap.css('visibility', 'hidden'); + } + if (this.$columnHeadTableWrap) { + this.$columnHeadTableWrap.css('visibility', 'hidden'); + } + if (this.$scrollBarWrap) { + this.$scrollBarWrap.css('visibility', 'hidden'); + } + + } else { + // Unmark + this.isWindowScrollX = false; + } + + }).bind(this); + // Listener of Body scroll-x prevention + this.$container.on('scroll.'+this.namespace, function () { + + detectWindowScroll(); + }); + + // Initialization + this.resize(); + + // Callback + if (typeof callback === 'function') { + callback(); + } + } + + /** + * Freeze thead table + */ + FreezeTable.prototype.buildHeadTable = function() { + + var that = this; + + // Clone the table as Fixed thead + var $headTable = this.clone(this.$table); + + // Fast Mode + if (this.fastMode) { + var $headTable = this.simplifyHead($headTable); + } + + var headWrapStyles = this.options.headWrapStyles || null; + // Wrap the Fixed Column table + this.$headTableWrap = $('
') + .append($headTable) + .css('position', 'fixed') + .css('overflow', 'hidden') + .css('visibility', 'hidden') + .css('top', 0 + this.fixedNavbarHeight) + .css('z-index', 2); + // Shadow option + if (this.shadow) { + this.$headTableWrap.css('box-shadow', '0px 6px 10px -5px rgba(159, 159, 160, 0.8)'); + } + // Styles option + if (headWrapStyles && typeof headWrapStyles === "object") { + $.each(headWrapStyles, function(key, value) { + that.$headTableWrap.css(key, value); + }); + } + // Add into target table wrap + this.$tableWrapper.append(this.$headTableWrap); + + /** + * Listener - Table scroll for effecting Freeze Column + */ + this.$tableWrapper.on('scroll.'+this.namespace, function() { + + // this.$headTableWrap.css('left', this.$table.offset().left); + that.$headTableWrap.scrollLeft($(this).scrollLeft()); + }); + + // Scrollable option + if (this.scrollable) { + + var handler = function (window, that) { + + var top = that.$tableWrapper.offset().top; + + // Detect Current container's top is in the table scope + if (that.$tableWrapper.scrollTop() > 0 && top > that.fixedNavbarHeight) { + + that.$headTableWrap.offset({top: top}); + that.$headTableWrap.css('visibility', 'visible'); + + } else { + + that.$headTableWrap.css('visibility', 'hidden'); + } + } + + /** + * Listener - Window scroll for effecting freeze head table + */ + this.$tableWrapper.on('scroll.'+this.namespace, function() { + + handler(window, that); + }); + + this.$container.on('scroll.'+this.namespace, function() { + + handler(window, that); + }); + + } + // Default with window container + else if ($.isWindow(that.$container.get(0))) { + + /** + * Listener - Window scroll for effecting freeze head table + */ + this.$container.on('scroll.'+this.namespace, function() { + + // Current container's top position + var topPosition = that.$container.scrollTop() + that.fixedNavbarHeight; + var tableTop = that.$table.offset().top - 1; + + // Detect Current container's top is in the table scope + if (tableTop - 1 <= topPosition && (tableTop + that.$table.outerHeight() - 1) >= topPosition) { + + that.$headTableWrap.css('visibility', 'visible'); + + } else { + + that.$headTableWrap.css('visibility', 'hidden'); + } + }); + } + // Container setting + else { + + /** + * Listener - Window scroll for effecting freeze head table + */ + this.$container.on('scroll.'+this.namespace, function() { + + var windowTop = $(window).scrollTop(); + var tableTop = that.$table.offset().top - 1; + + // Detect Current container's top is in the table scope + if (tableTop <= windowTop && (tableTop + that.$table.outerHeight() - 1) >= windowTop) { + + that.$headTableWrap.offset({top: windowTop}); + that.$headTableWrap.css('visibility', 'visible'); + + } else { + + that.$headTableWrap.css('visibility', 'hidden'); + } + }); + } + + /** + * Listener - Window resize for effecting freeze head table + */ + this.$container.on('resize.'+this.namespace, function() { + + // Scrollable check and prevention + var headTableWrapWidth = (that.scrollable) ? that.$tableWrapper.width() - that.scrollBarHeight : that.$tableWrapper.width(); + headTableWrapWidth = (headTableWrapWidth > 0) ? headTableWrapWidth : that.$tableWrapper.width(); + that.$headTableWrap.css('width', headTableWrapWidth); + that.$headTableWrap.css('height', that.$table.find("thead").outerHeight()); + }); + } + + /** + * Freeze column table + */ + FreezeTable.prototype.buildColumnTable = function() { + + var that = this; + + /** + * Setting + */ + var columnWrapStyles = this.options.columnWrapStyles || null; + var columnNum = this.options.columnNum || 1; + var columnKeep = (typeof this.options.columnKeep !== 'undefined') ? this.options.columnKeep : false; + // Shadow option + var defaultColumnBorderWidth = (this.shadow) ? 0 : 1; + var columnBorderWidth = (typeof this.options.columnBorderWidth !== 'undefined') ? this.options.columnBorderWidth : defaultColumnBorderWidth; + + // Clone the table as Fixed Column table + var $columnTable = this.clone(this.$table); + + // Wrap the Fixed Column table + this.$columnTableWrap = $('
') + .append($columnTable) + .css('position', 'fixed') + .css('overflow', 'hidden') + .css('visibility', 'hidden') + .css('z-index', 1); + // Shadow option + if (this.shadow) { + this.$columnTableWrap.css('box-shadow', '6px 0px 10px -5px rgba(159, 159, 160, 0.8)'); + } + // Styles option + if (columnWrapStyles && typeof columnWrapStyles === "object") { + $.each(columnWrapStyles, function(key, value) { + that.$columnTableWrap.css(key, value); + }); + } + // Scrollable + if (this.scrollable) { + // Scrollable check and prevention + var columnTableWrapHeight = this.$tableWrapper.height() - this.scrollBarHeight; + columnTableWrapHeight = (columnTableWrapHeight > 0) ? columnTableWrapHeight : this.$tableWrapper.height(); + this.$columnTableWrap.height(columnTableWrapHeight); + } + // Add into target table wrap + this.$tableWrapper.append(this.$columnTableWrap); + + /** + * localize the column wrap to current top + */ + var localizeWrap = function () { + + that.$columnTableWrap.offset({top: that.$tableWrapper.offset().top}); + } + + // Column keep option + if (columnKeep) { + + this.$columnTableWrap.css('visibility', 'visible'); + + } else { + + // Scrollable option + if (that.scrollable) { + + /** + * Listener - Table scroll for effecting Freeze Column + */ + this.$tableWrapper.on('scroll.'+this.namespace, function() { + + + // Detect for horizontal scroll + if ($(this).scrollLeft() > 0) { + + // Scrollable localization + that.$columnTableWrap.scrollTop(that.$tableWrapper.scrollTop()); + that.$columnTableWrap.css('visibility', 'visible'); + + } else { + + that.$columnTableWrap.css('visibility', 'hidden'); + } + }); + + } else { + + /** + * Listener - Table scroll for effecting Freeze Column + */ + this.$tableWrapper.on('scroll.'+this.namespace, function() { + + // Disable while isWindowScrollX + if (that.isWindowScrollX) + return; + + // Detect for horizontal scroll + if ($(this).scrollLeft() > 0) { + + that.$columnTableWrap.css('visibility', 'visible'); + + } else { + + that.$columnTableWrap.css('visibility', 'hidden'); + } + }); + } + } + + /** + * Listener - Window resize for effecting tables + */ + this.$container.on('resize.'+this.namespace, function() { + + // Follows origin table's width + $columnTable.width(that.$table.width()); + + /** + * Dynamic column calculation + */ + // Get width by fixed column with number setting + var width = 0 + columnBorderWidth; + for (var i = 1; i <= columnNum; i++) { + // th/td detection + var th = that.$table.find('th:nth-child('+i+')').outerWidth(); + var addWidth = (th > 0) ? th : that.$table.find('td:nth-child('+i+')').outerWidth(); + width += addWidth; + } + that.$columnTableWrap.width(width); + + localizeWrap(); + }); + + /** + * Listener - Window scroll for effecting freeze column table + */ + this.$container.on('scroll.'+this.namespace, function() { + + localizeWrap(); + }); + } + + /** + * Freeze column thead table + */ + FreezeTable.prototype.buildColumnHeadTable = function() { + + var that = this; + + // Clone head table wrap + this.$columnHeadTableWrap = this.clone(this.$headTableWrap); + + // Fast Mode + if (this.fastMode) { + this.$columnHeadTableWrap = this.simplifyHead(this.$columnHeadTableWrap); + } + + var columnHeadWrapStyles = this.options.columnHeadWrapStyles || null; + + this.$columnHeadTableWrap.removeClass(this.namespace) + .addClass(this.columnHeadWrapClass) + .css('z-index', 3); + // Shadow option + if (this.shadow) { + this.$columnHeadTableWrap.css('box-shadow', 'none'); + } + // Styles option + if (columnHeadWrapStyles && typeof columnHeadWrapStyles === "object") { + $.each(columnHeadWrapStyles, function(key, value) { + this.$columnHeadTableWrap.css(key, value); + }); + } + + // Add into target table wrap + this.$tableWrapper.append(this.$columnHeadTableWrap); + + // Scrollable option + if (this.scrollable) { + + var detect = function () { + + var top = that.$tableWrapper.offset().top; + + // Detect Current container's top is in the table scope + if (that.$tableWrapper.scrollTop() > 0 && top > that.fixedNavbarHeight) { + + that.$columnHeadTableWrap.offset({top: top}); + that.$columnHeadTableWrap.css('visibility', 'visible'); + + } else { + + that.$columnHeadTableWrap.css('visibility', 'hidden'); + } + } + + /** + * Listener - Window scroll for effecting freeze head table + */ + $(this.$tableWrapper).on('scroll.'+this.namespace, function() { + + detect(); + }); + + } + // Default with window container + else if ($.isWindow(this.$container.get(0))) { + + var detect = function () { + + // Current container's top position + var topPosition = that.$container.scrollTop() + that.fixedNavbarHeight; + var tableTop = that.$table.offset().top - 1; + + // Detect Current container's top is in the table scope + if (tableTop - 1 <= topPosition && (tableTop + that.$table.outerHeight() - 1) >= topPosition && that.$tableWrapper.scrollLeft() > 0) { + + that.$columnHeadTableWrap.css('visibility', 'visible'); + + } else { + + that.$columnHeadTableWrap.css('visibility', 'hidden'); + } + } + } + // Container setting + else { + + var detect = function () { + + var windowTop = $(window).scrollTop(); + var tableTop = that.$table.offset().top - 1; + + // Detect Current container's top is in the table scope + if (tableTop <= windowTop && (tableTop + that.$table.outerHeight() - 1) >= windowTop && that.$tableWrapper.scrollLeft() > 0) { + + that.$columnHeadTableWrap.offset({top: windowTop}); + that.$columnHeadTableWrap.css('visibility', 'visible'); + + } else { + + that.$columnHeadTableWrap.css('visibility', 'hidden'); + } + } + } + + /** + * Listener - Window scroll for effecting Freeze column-head table + */ + this.$container.on('scroll.'+this.namespace, function() { + + detect(); + }); + + /** + * Listener - Table scroll for effecting Freeze column-head table + */ + this.$tableWrapper.on('scroll.'+this.namespace, function() { + + // Disable while isWindowScrollX + if (that.isWindowScrollX) + return; + + detect(); + }); + + /** + * Listener - Window resize for effecting freeze column-head table + */ + this.$container.on('resize.'+this.namespace, function() { + + // Table synchronism + that.$columnHeadTableWrap.find("> table").css('width', that.$table.width()); + that.$columnHeadTableWrap.css('width', that.$columnTableWrap.width()); + that.$columnHeadTableWrap.css('height', that.$table.find("thead").outerHeight()); + }); + } + + /** + * Freeze scroll bar + */ + FreezeTable.prototype.buildScrollBar = function() { + + var that = this; + + var theadHeight = this.$table.find("thead").outerHeight(); + + // Scroll wrap container + var $scrollBarContainer = $('
') + .css('width', this.$table.width()) + .css('height', 1); + + // Wrap the Fixed Column table + this.$scrollBarWrap = $('
') + .css('position', 'fixed') + .css('overflow-x', 'scroll') + .css('visibility', 'hidden') + .css('bottom', 0) + .css('z-index', 2) + .css('width', this.$tableWrapper.width()) + .css('height', this.scrollBarHeight); + + // Add into target table wrap + this.$scrollBarWrap.append($scrollBarContainer); + this.$tableWrapper.append(this.$scrollBarWrap); + + /** + * Listener - Freeze scroll bar effected Table + */ + this.$scrollBarWrap.on('scroll.'+this.namespace, function() { + + that.$tableWrapper.scrollLeft($(this).scrollLeft()); + }); + + /** + * Listener - Table scroll for effecting Freeze scroll bar + */ + this.$tableWrapper.on('scroll.'+this.namespace, function() { + + // this.$headTableWrap.css('left', $table.offset().left); + that.$scrollBarWrap.scrollLeft($(this).scrollLeft()); + }); + + /** + * Listener - Window scroll for effecting scroll bar + */ + this.$container.on('scroll.'+this.namespace, function() { + + // Current container's top position + var bottomPosition = that.$container.scrollTop() + that.$container.height() - theadHeight + that.fixedNavbarHeight; + + // Detect Current container's top is in the table scope + if (that.$table.offset().top - 1 <= bottomPosition && (that.$table.offset().top + that.$table.outerHeight() - 1) >= bottomPosition) { + + that.$scrollBarWrap.css('visibility', 'visible'); + + } else { + + that.$scrollBarWrap.css('visibility', 'hidden'); + } + }); + + /** + * Listener - Window resize for effecting scroll bar + */ + this.$container.on('resize.'+this.namespace, function() { + + // Update width + $scrollBarContainer.css('width', that.$table.width()) + // Update Wrap + that.$scrollBarWrap.css('width', that.$tableWrapper.width()); + }); + } + + /** + * Clone element + * + * @param {element} element + */ + FreezeTable.prototype.clone = function (element) { + + var $clone = $(element).clone() + .removeAttr('id') // Remove ID + + // Bootstrap background-color transparent problem + if (this.backgroundColor) { + $clone.css('background-color', this.backgroundColor); + } + + return $clone; + } + + /** + * simplify cloned head table + * + * @param {element} table Table element + */ + FreezeTable.prototype.simplifyHead = function (table) { + + var that = this; + + var $headTable = $(table); + // Remove non-display DOM but keeping first row for accuracy + $headTable.find("> tr, > tbody > tr, tfoot > tr").not(':first').remove(); + // Each th/td width synchronism + $.each($headTable.find("> thead > tr:nth-child(1) >"), function (key, value) { + + var width = that.$table.find("> thead > tr:nth-child(1) > :nth-child("+parseInt(key+1)+")").outerWidth(); + $(this).css('width', width); + }); + + return $headTable; + } + + /** + * Detect is already initialized + */ + FreezeTable.prototype.isInit = function() { + + // Check existence DOM + if (this.$tableWrapper.find("."+this.headWrapClass).length) + return true; + if (this.$tableWrapper.find("."+this.columnWrapClass).length) + return true; + if (this.$tableWrapper.find("."+this.columnHeadWrapClass).length) + return true; + if (this.$tableWrapper.find("."+this.scrollBarWrapClass).length) + return true; + + return false; + + } + + /** + * Unbind all events by same namespace + */ + FreezeTable.prototype.unbind = function() { + + this.$container.off('resize.'+this.namespace); + this.$container.off('scroll.'+this.namespace); + this.$tableWrapper.off('scroll.'+this.namespace); + } + + /** + * Destroy Freeze Table by same namespace + */ + FreezeTable.prototype.destroy = function() { + + this.unbind(); + this.$tableWrapper.find("."+this.headWrapClass).remove(); + this.$tableWrapper.find("."+this.columnWrapClass).remove(); + this.$tableWrapper.find("."+this.columnHeadWrapClass).remove(); + this.$tableWrapper.find("."+this.scrollBarWrapClass).remove(); + } + + /** + * Resize trigger for current same namespace + */ + FreezeTable.prototype.resize = function() { + + this.$container.trigger('resize.'+this.namespace); + this.$container.trigger('scroll.'+this.namespace); + this.$tableWrapper.trigger('scroll.'+this.namespace); + + return true; + } + + /** + * Update for Dynamic Content + */ + FreezeTable.prototype.update = function() { + + // Same as re-new object + this.options = 'update'; + this.init(); + return this; + } + + /** + * Interface + */ + // Class for single element + window.FreezeTable = FreezeTable; + // jQuery interface + $.fn.freezeTable = function (options) { + + // Single/Multiple mode + if (this.length === 1) { + + return new FreezeTable(this, options) + } + else if (this.length > 1) { + + var result = []; + // Multiple elements bundle + this.each(function () { + result.push(new FreezeTable(this, options)); + }); + + return result; + } + + return false; + } + +})(jQuery, window); \ No newline at end of file diff --git a/app/assets/stylesheets/admin.css.scss b/app/assets/stylesheets/admin.css.scss index 384cdaa..1b81c0f 100644 --- a/app/assets/stylesheets/admin.css.scss +++ b/app/assets/stylesheets/admin.css.scss @@ -14,6 +14,31 @@ @import "redactor_plugins/alignment"; $vert:rgba(143,193,46,0.9); +$ap_red:rgba(50,50,50,1); +$ap_add:rgb(101,207,150); +$ap_error:rgb(249,163,166); +$ap_warn:rgb(255,192,0); +$ap_dark_gray:rgb(76,76,76); + +.navbar-inverse .navbar-nav > .open > a, .navbar-inverse .navbar-nav > .open > a:hover, .navbar-inverse .navbar-nav > .open > a:focus{ + + background:$ap_dark_gray; +} +.navbar-inverse{ + background:$ap_red; + + .navbar-toggle{ + border-color:transparent; + } +} + +input[type=number]::-webkit-inner-spin-button, +input[type=number]::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; +} + + #edit_watcher_result{ .inner{ @@ -67,6 +92,7 @@ $vert:rgba(143,193,46,0.9); #admin_nav{ border-radius:0px; +border:0; .active{ color:white; @@ -98,7 +124,7 @@ html { body { width: 100%; - font-family:"Roboto"; + font-family: 'Nunito Sans', sans-serif; background:#E9ECEE no-repeat fixed; background-size:100%; background-position:bottom center; @@ -161,7 +187,7 @@ padding:3px; font-size:18px; min-width: 30px; text-align:center; -background:white; +background:transparent; color:rgba(0,0,0,0.8); &:hover{ @@ -682,14 +708,7 @@ margin:0.5em; } -.table-striped{ - tr:nth-child(odd) { - td, th{ - background:#f9f9f9 !important; - }} - -} @media print { .visible-print { display: inherit !important; } @@ -763,11 +782,8 @@ opacity:0.5; } -.table-striped tr:nth-child(odd) td, .table-striped tr:nth-child(odd) th{ -background:rgba(235,244,250,1) !important; -} .block_portlets{ .portlet{ @@ -965,50 +981,6 @@ h1{ } -#right_bar{ - background:white; - position:fixed; - top:0; - left:0; - bottom:0; - width:100px; - padding:10px 0; - box-shadow:0 0 5px rgba(0,0,0,0.2); - .bottom{ - position:absolute; - bottom:20px; - left:0; - right:0; - - } - .element{ - .cat{ - - } - display:block; - position:relative; - text-align:center; - font-size:11px; - i{ - position:relative; - display:block; - font-size:30px; - line-height:40px; - } - - a{ - color:rgba(0,0,0,0.55); - display:block; - padding:8px 0; - &:hover, .active, &:focus{ - text-decoration:none; - color:rgba(0,0,0,0.8); - } - } - } - - -} .ui-autocomplete { @@ -1061,19 +1033,168 @@ h1{ background-image: none; } -.table-warning{ +.tdr{ + text-align:right !important; + padding-left:5px; +} + +.p_customer_fin{ + border:3px solid rgba(0,0,0,0.6); +} + + +#right_bar{ + background:rgba(0,0,0,0.8); + position:fixed; + box-shadow:0 0 5px rgba(0,0,0,0.6); + top:0; + left:0; + bottom:0; + width:100px; + padding:10px 0; + padding-top:0; + + z-index:4; + + + #logo-basic{ + display:block; + max-width:70%; + margin:auto ; + margin-top:10px; + margin-bottom:-5px; + } + + + #logo{ + display:block; + //background:white; + img{ + //background:white; + display:block; + margin:auto; + max-width:80px; + + padding:10px; + margin-bottom:10px; + //padding-right:5px; + //padding-top:0; + } + } + + .bottom{ + position:absolute; + bottom:20px; + left:0; + right:0; + + } + .element{ + .cat{ + padding:7px 0; + } + display:block; + position:relative; + text-align:center; + font-size:11px; + i{ + position:relative; + display:block; + font-size:30px; + line-height:40px; + } + + a{ + color:rgba(white, 0.6); + display:block; + padding:0px 0; + + + &:hover, .active, &:focus{ + text-decoration:none; + color:white; + } + } + } + - background:#fcf8e3 !important; } -input[type=number]::-webkit-inner-spin-button, -input[type=number]::-webkit-outer-spin-button { - -webkit-appearance: none; - margin: 0; + +#logo{ + display:block; + img{ + display:block; + margin:auto; + width:80px; + padding:12px 0; + padding-top:0; + } } -//CSS 3P + + + + + + + +$big_colors :( +clients:rgba(1,102,153 ,1), +ventes : #518889, +todos : #f8b411, +tournees:#786455, +stocks:#718197, +documents : rgba(217, 121, 65, 1), +payments : #ED6353, +statistiques : #6C5B7B, +export_compta : #7d308e + +); + + +@each $admin_space, $color in $big_colors { + #body_#{$admin_space}{ + #admin_nav{ + //background:$big_color_#{$admin_space} !important; + background-color: $color !important; + } + + } + #big_cat_#{$admin_space}.active, #big_cat_#{$admin_space}:hover{ + //color:$big_color_#{$admin_space} !important; + //background-color: $color !important; + color:white !important; + border-right:4px solid $color; + + } + + #big_cat_#{$admin_space}{ + //color:$big_color_#{$admin_space} !important; + color: rgba(white, 0.5) !important; + border-right:4px solid transparent; + } + + .bgbd-#{$admin_space}{ + background-color: $color !important; + border-color: $color !important; + } + +} + + +.btn-ap-add{ + background-color: $ap_add !important; + border-color: $ap_add !important; + +} + +.btn-ap-error{ + background-color: $ap_error !important; + border-color: $ap_error !important; + +} .table-striped > tbody > tr:nth-child(odd) > td, .table-striped tr:nth-child(odd) td, .table-striped tr:nth-child(odd) th{ @@ -1114,6 +1235,16 @@ input[type=number]::-webkit-outer-spin-button { background:#f1f1fe ;} } +.no-wrap{ + white-space: nowrap; +} + +.table-no-wrap{ + + td, th{ + white-space: nowrap; + } +} @@ -1144,13 +1275,21 @@ input[type=number]::-webkit-outer-spin-button { } } +#qi_header_wrapper{ + position:fixed; + right:0; + left:100px; + z-index:10; + top:0; +} + + #admin_nav{ border-radius:0px; -position:fixed; -right:0; -left:100px; -top:0; -z-index:10; +position:relative; +z-index:4; + + .active{ color:white; border-bottom:1px solid white; @@ -1158,12 +1297,10 @@ z-index:10; } .qi_header{ - position:fixed; + position:relative; z-index:3; box-shadow:0 0 5px rgba(0,0,0,0.2); - top:50px; - right:0; - left:100px; + min-height:48px; } @@ -1218,10 +1355,6 @@ z-index:10; } -td.actions{ - - text-align:right; -} td.numeraire{ @@ -1229,3 +1362,316 @@ td.numeraire{ text-align:right; } + + + +.big_icon{ + font-size:1.5em; + display:inline-block; + margin-right:3px; + text-decoration:none; + color:rgba(0,0,0,0.2); + + &.active{ + color:#ffd400; + } +} +.done{ + color:green; +} + +.fire{ + color:red; +} +.undone, .unfire{ + color:rgba(0,0,0,0.2); +} + +.i_task_row{ + margin:10px 0; + padding:0px 0; + + .icon{ + background:transparent !important; + } + .qi_pannel.padding{ + padding:2px; + + + } + td{ + border:0 !important; + border:0 !important; + vertical-align: middle !important; + } + + table{ + margin:0; + } + +} + +.ui-helper-hidden-accessible{ + display:none; +} + + +.no_wrap{ + white-space: nowrap; + +} + +.top_td{ + td, th{ + vertical-align:top; + } +} + +.large_actions{ + min-height:150px; + .actions{ + position:fixed; + z-index: 3; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); + bottom: 0px; + right: 0; + left: 100px; + padding:10px 30px; + text-align:right; + background:white; + } +} + +.red{ + color:red; +} + +.lock_label{ + + background:red; + display:inline-block; + padding:2px 3px; + color:white; +} + + +.check_boxes{ + list-style-type: none; + +} +.choices{ + .choices-group{ + padding-left:0; + } + ol li{ + list-style-type: none; + + ul{ + padding:0; + } + + } + + label{ + font-weight:normal; + } + + .label{ + display: inherit !important; + padding: inherit !important; + font-size: inherit !important; + font-weight: bold !important; + line-height: inherit !important; + color: inherit !important; + text-align: inherit !important; + white-space: inherit !important; + vertical-align: inherit !important; + border-radius: inherit !important; + border:0; + margin-bottom:0; + + label{ + font-weight: bold !important; + } + + + } + + +} + + + +.qi_search_row{ + position:relative; + + padding:20px; + padding-top:10px; + background:#dbe4ea; + padding-bottom:40px; + + table{ + td,th{ + padding: 3px 0; + padding-right:5px; + } + + } + .results_count{ + position:absolute; + color:rgba(0,0,0,0.5); + font-size:12px; + bottom:12px; + left:20px; + } + .btn-qi-search{ + background:#6bbdf6; + border-color:#6bbdf6; + color:white; + position:absolute; + + bottom:10px; + right:20px; + + } + +} + + + +.search_label{ + width:110px; + text-align:right; + padding-right:5px; +} +.search_op{ + width:25px; + text-align:center; + color:rgba(0,0,0,0.5); +} + +.search_number_input{ + width:100px; +} + +.table-area{ + position:relative; + padding-top:15px; + + + .table{ + background:white; + } + .zoom{ + display:block; + position:absolute; + top:5px; + right:5px; + + } + .unzoom{ + display:none; + + + + } + + .table-area-inner{ + + + } + + td, th{ + white-space: nowrap; + + } + +} +.large_table_area{ + position:fixed; + top:0; + left:0; + right:0; + bottom:0; + background:white; + z-index:100; + padding:20px; + overflow:auto; + .table-area-inner{ + + } + td, th{ + white-space: nowrap; + + } + .zoom{ + display:none; + } + .unzoom{ + display:block; + position:absolute; + top:5px; + right:5px; + + + + } + +} + +.dyn_table_container{ + td, th{ + white-space: nowrap; + + } + +} + +.new_table_container{ + + padding:15px 30px !important; +} + + +.clone-column-table-wrap{ + box-shadow: 15px 0 15px -18px rgba(0,0,0,0.3); +} + +.DTFC_LeftBodyWrapper{ + box-shadow: 15px 0 15px -14px rgba(0,0,0,0.3); + border-right:2px solid white; +} + + +.DTFC_RightBodyWrapper{ + box-shadow: -15px 0 15px -14px rgba(0,0,0,0.3); + border-right:2px solid white; +} + +.dataTables_wrapper{ + .col-sm-12{ + padding:0; + } + + th{ + + } + .table{ + td{ + + + } + } +} + + + +form{ + + .qi_pannel.qi_plain{ + background-color:rgba(white,0.5); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); + + } + +} diff --git a/app/controllers/admin/p_customer_sheets_controller.rb b/app/controllers/admin/p_customer_sheets_controller.rb index 506b65e..77ce8fe 100644 --- a/app/controllers/admin/p_customer_sheets_controller.rb +++ b/app/controllers/admin/p_customer_sheets_controller.rb @@ -24,11 +24,52 @@ class Admin::PCustomerSheetsController < ApplicationController end def index - @p_customer_sheets = PCustomerSheet.order("created_at DESC").all + @p_customer_sheets = PCustomerSheet.all - per_page = (params[:per_page] and params[:per_page] != "") ? params[:per_page] : 50 - page = (params[:page] and params[:page] != "") ? params[:page] : 1 - @p_customer_sheets = @p_customer_sheets.page(page).per(per_page) + + date_regex = /^(0[1-9]|[12][0-9]|3[01])[\/](0[1-9]|1[012])[\/](19|20)\d\d$/i + + + + if params[:search][:created_at_start] and params[:search][:created_at_start] =~ date_regex + + @start = Date.parse(params[:search][:created_at_start]).beginning_of_day + params[:search][:created_at_start]= @start.strftime('%d/%m/%Y') + + + else + @start = nil + end + if params[:search][:created_at_stop].to_s != "" # and params[:search][:created_at_stop] =~ date_regex + @stop = Date.parse(params[:search][:created_at_stop]).end_of_day + + params[:search][:created_at_stop]= @stop.strftime('%d/%m/%Y') + + + else + @stop = nil + end + + @p_customer_sheets = @p_customer_sheets.where("p_customer_sheets.created_at >= ?", @start) if @start + @p_customer_sheets = @p_customer_sheets.where("p_customer_sheets.created_at <= ?", @stop.end_of_day) if @stop + + + if params[:search][:state].to_s != "" + @p_customer_sheets = @p_customer_sheets.where(:state => params[:search][:state]) + end + + + @p_customer_sheets = sort_by_sorting(@p_customer_sheets, "created_at DESC") + respond_to do |format| + format.html{ + + params[:search][:per_page] = params[:search][:per_page] || 50 + per_page = params[:search][:per_page] + page = (params[:page] and params[:page] != "") ? params[:page] : 1 + @p_customer_sheets = @p_customer_sheets.page(page).per(per_page) + + } + end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 415b509..fe9e728 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -15,6 +15,110 @@ class ApplicationController < ActionController::Base before_filter :debug_translation + + before_action :get_sorting + + def get_sorting( column_default=nil, direction_default="desc") + + + + sorting_direction = %w[asc desc].include?(params[:direction]) ? params[:direction] : direction_default + sorting_column = params[:column] ? params[:column] : column_default + + if sorting_direction and sorting_column + @sorting = [sorting_column, sorting_direction] + end + end + + + before_action :set_qi_order + + def set_qi_order + params[:search] = params[:search] || {} + + session[:qi_sort_string] = session[:qi_sort_string] || {} + + if params[:qi_sort_string].to_s != "" and params[:qi_sort_string][:class] + + if current_admin + if ap = current_admin.admin_preferences.where(:key => "sort_table_"+params[:qi_sort_string][:class]).first + ap.value = params[:qi_sort_string][:list].to_s + ap.save + else + current_admin.admin_preferences.create(:key => "sort_table_"+params[:qi_sort_string][:class], :value => params[:qi_sort_string][:list].to_s) + end + + + + else + session[:qi_sort_string][params[:qi_sort_string][:class]] = params[:qi_sort_string][:list].to_s + end + + else + + end + + + if params[:qi_sort_string].to_s != "" and params[:qi_sort_string][:nbr_colonnes].to_s != "" + + if current_admin + if ap = current_admin.admin_preferences.where(:key => "sort_table_"+params[:qi_sort_string][:class]+"_nbr_col").first + ap.value = params[:qi_sort_string][:nbr_colonnes].to_s + ap.save + else + current_admin.admin_preferences.create(:key => "sort_table_"+params[:qi_sort_string][:class]+"_nbr_col", :value => params[:qi_sort_string][:nbr_colonnes].to_s) + end + + else + session[:qi_sort_string][params[:qi_sort_string][:class]+"_nbr_col"] = params[:qi_sort_string][:nbr_colonnes].to_s + end + + else + + end + + + + + end + + + def sort_by_sorting(var, default=nil) + if @sorting + klass = var.klass.to_s + + if eval(klass).valid_sort.include?(@sorting[0]) + if @sorting[0].split(",").size > 0 + order_text = "" + i = 0 + @sorting[0].split(",").each do |s| + + order_text += "#{s} #{@sorting[1]}" + order_text += "," if i < (@sorting[0].split(",").size - 1 ) + i+=1 + end + var = var.order(order_text) + else + var = var.order("#{@sorting[0]} #{@sorting[1]}") + end + + + end + + elsif default + var = var.order(default) + end + + + + return var + + + + end + + + def debug_translation if params[:debug_translation] if current_admin diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 77895a7..db33c9e 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,5 +1,19 @@ module ApplicationHelper + def qi_js_field(form, model, method, options = {}) + r = "" + if options[:hidden] + r += hidden_field_tag(method, eval("form.object.#{method}"), :class => "input_#{model}_#{method} form-control",:disabled => true) + else + if options[:label] + r += label_tag(:input, options[:label]) + end + r += text_field_tag(method, (options[:value] ? options[:value] : eval("form.object.#{method}")), :class => "input_#{model}_#{method} form-control",:disabled => true) + end + return raw(r) + end + + def edit_watcher(element_type, element_id, key='' ) raw ('
') end @@ -30,4 +44,26 @@ module ApplicationHelper end end + + + def sort_link(column, title = nil) + + #def sortable_columns + # ["name", "price"] + + + sort_column = (params[:column] ? params[:column] : nil) + + + sort_direction = (%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc") + + + + title ||= column.titleize + direction = column == sort_column && sort_direction == "asc" ? "desc" : "asc" + icon = sort_direction == "asc" ? "chevron-up" : "chevron-down" + icon = column == sort_column ? icon : "" + link_to raw("#{title} "+ic(icon).html_safe), request.query_parameters.merge({column: column, direction: direction}) + end + end diff --git a/app/models/admin.rb b/app/models/admin.rb index 1d59c1a..bfdbb85 100644 --- a/app/models/admin.rb +++ b/app/models/admin.rb @@ -47,6 +47,7 @@ class Admin < ActiveRecord::Base has_many :admin_admin_roles has_many :admin_roles, :through => :admin_admin_roles has_many :admin_permissions, :through => :admin_roles + has_many :admin_preferences def has_permission?(permission) diff --git a/app/models/admin_preference.rb b/app/models/admin_preference.rb new file mode 100644 index 0000000..d35709a --- /dev/null +++ b/app/models/admin_preference.rb @@ -0,0 +1,3 @@ +class AdminPreference < ActiveRecord::Base + belongs_to :admin +end diff --git a/app/models/p_customer_sheet.rb b/app/models/p_customer_sheet.rb index 1a89349..463dea7 100644 --- a/app/models/p_customer_sheet.rb +++ b/app/models/p_customer_sheet.rb @@ -1,4 +1,41 @@ + + class PCustomerSheet < ActiveRecord::Base + + acts_as_caching :fields => [:total_ht, :total_tva, :total_ttc] + + acts_as_sorting :fields => { + :id => {:name => "ID", :reorder => true}, + :created_at => {:name => "Date", :reorder => true}, + :customer_validation_at => {:name => "Date validation", :reorder => true}, + :p_customer => {:name => "Client", :reorder => false}, + :cc_total_ht => {:name => "Total HT", :reorder => true}, + :cc_total_tva => {:name => "TVA", :reorder => true}, + :cc_total_ttc => {:name => "Total TTC", :reorder => true}, + :state => {:name => "Statut", :reorder => true}, + :actions => {:name => "Actions", :reorder => false} + } + + def ca_total_ht + PSheetLine.totals(self.p_sheet_lines)[:total] + end + + def ca_total_tva + self.ca_total_ttc - self.ca_total_ht + end + + def ca_total_ttc + PSheetLine.totals(self.p_sheet_lines)[:total_ttc] + end + + def to_no_archive + [] + #[:total_ttc] + end + + + + has_many :p_documents, :as => :element has_many :p_box_fdps, :as => :element @@ -34,6 +71,10 @@ class PCustomerSheet < ActiveRecord::Base + + + + def validate_cgv? true if self.validate_cgv end diff --git a/app/views/admin/p_customer_sheets/_p_customer_sheet.html.haml b/app/views/admin/p_customer_sheets/_p_customer_sheet.html.haml index abfe017..ef33838 100644 --- a/app/views/admin/p_customer_sheets/_p_customer_sheet.html.haml +++ b/app/views/admin/p_customer_sheets/_p_customer_sheet.html.haml @@ -1,34 +1,45 @@ +-totals = PSheetLine.totals(p_customer_sheet.p_sheet_lines) + -if (p_customer_sheet.state != "panier" or p_customer_sheet.p_sheet_lines.count > 0) %tr#p_customer_sheet{:id => p_customer_sheet.id} - %td="##{p_customer_sheet.id}" - %td=l p_customer_sheet.created_at, :format => :date - %td=l p_customer_sheet.customer_validation_at, :format => "%d/%m/%Y %H:%M" if p_customer_sheet.customer_validation_at + -tr = {} + + -tr[:id] = capture do + %td="##{p_customer_sheet.id}" + -tr[:created_at] = capture do + %td=l p_customer_sheet.created_at, :format => :date + -tr[:customer_validation_at] = capture do + %td=l p_customer_sheet.customer_validation_at, :format => "%d/%m/%Y %H:%M" if p_customer_sheet.customer_validation_at - -if !@p_customer + -tr[:p_customer] = capture do %td= p_customer_sheet.p_customer.show_name if p_customer_sheet.p_customer - =#%td= p_customer_sheet.sheet_lines_not_shiped.count - =#%td= p_customer_sheet.sheet_lines_shiped.count - - - %td - -totals = PSheetLine.totals(p_customer_sheet.p_sheet_lines) - =number_to_currency totals[:total] + + -tr[:cc_total_ht] = capture do + %td.numeraire + =number_to_currency p_customer_sheet.cc_total_ht + -tr[:cc_total_tva] = capture do + %td.numeraire + =number_to_currency p_customer_sheet.cc_total_tva - %td - =number_to_currency totals[:total_ttc] - - %td - =raw p_customer_sheet.state_html + -tr[:cc_total_ttc] = capture do + %td.numeraire + =number_to_currency p_customer_sheet.cc_total_ttc + + -tr[:state] = capture do + %td + =raw p_customer_sheet.state_html - - %td.actions + -tr[:actions] = capture do + %td.actions - =link_to i(:copy), dup_admin_p_customer_sheet_path(p_customer_sheet), :data => {:confirm => 'Voulez-vous vraiment dupliquer cette commande ?'} + =link_to i(:copy), dup_admin_p_customer_sheet_path(p_customer_sheet), :data => {:confirm => 'Voulez-vous vraiment dupliquer cette commande ?'} - -if p_customer_sheet.state == "brouillon" - = link_to i(:"trash-o"), [:admin, p_customer_sheet], method: :delete, data: { confirm: 'Voulez-vous vraiment supprimer cet auteur ? ' } , :remote => true - = link_to i(:pencil), edit_admin_p_customer_sheet_path(p_customer_sheet), :remote => false - = link_to i(:eye), admin_p_customer_sheet_path(p_customer_sheet), :remote => false + -if p_customer_sheet.state == "brouillon" + = link_to i(:"trash-o"), [:admin, p_customer_sheet], method: :delete, data: { confirm: 'Voulez-vous vraiment supprimer cet auteur ? ' } , :remote => true + = link_to i(:pencil), edit_admin_p_customer_sheet_path(p_customer_sheet), :remote => false + = link_to i(:eye), admin_p_customer_sheet_path(p_customer_sheet), :remote => false + + =render :partial => "qi/qi_ordered_table_object", :locals => {:tr => tr, :object => p_customer_sheet} \ No newline at end of file diff --git a/app/views/admin/p_customer_sheets/index.html.haml b/app/views/admin/p_customer_sheets/index.html.haml index 74a905a..e2df296 100644 --- a/app/views/admin/p_customer_sheets/index.html.haml +++ b/app/views/admin/p_customer_sheets/index.html.haml @@ -6,31 +6,33 @@ Offres -.qi_row - .qi_pannel.qi_plain.padding - %table.table +.qi_search_row + =form_tag "", :method => "get", :onsubmit => "" do + -params[:search] =params[:search] || {} + + + %table %tr - %th ID - %th Date - %th Date validation - - %th Client - - =#%th Non livrés - =#%th Livrés - %th Total HT - %th Total TTC - %th Statut - %th + %td + Statut : + =select_tag "search[state]", options_for_select([["",""]]+PCustomerSheet.group(:state).order(:state).all.map{|a| [a.state, a.state]}, params[:search][:state]) + + %td + Date de : + %td + =text_field_tag "search[created_at_start]", params[:search][:created_at_start],:class => "datepicker" + + %td à : + + %td=text_field_tag "search[created_at_stop]", params[:search][:created_at_stop],:class => "datepicker" - %tbody#p_customer_sheets_rows - =render @p_customer_sheets - - #pagination - = paginate @p_customer_sheets #, :remote => true - + + - \ No newline at end of file + =render :partial => "qi/qi_ordered_table_search_footer", :locals => {:collection_object => @p_customer_sheets} + + +=render :partial => "qi/qi_ordered_table", :locals => {:qi_ordered_table_collection => @p_customer_sheets} diff --git a/app/views/admin/p_customer_sheets/show.html.haml b/app/views/admin/p_customer_sheets/show.html.haml index bf5a625..55783a5 100644 --- a/app/views/admin/p_customer_sheets/show.html.haml +++ b/app/views/admin/p_customer_sheets/show.html.haml @@ -19,6 +19,11 @@ %h3 Client =link_to @p_customer_sheet.p_customer.show_name, admin_p_customer_path(@p_customer_sheet.p_customer) + =#debug @p_customer_sheet.unarchive_now + + =#debug @p_customer_sheet.archive_now + + =#debug @p_customer_sheet.abcdef %table.table{:style => ""} %tr diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index 42fb0da..74259cc 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -71,22 +71,22 @@ =raw '$("#big_cat_'+@admin_space.to_s+'").addClass("active");' - - %nav#admin_nav.navbar.navbar-default.navbar-inverse{role: "navigation"} - .container-fluid + #qi_header_wrapper.fh-fixedHeader + %nav#admin_nav.navbar.navbar-default.navbar-inverse{role: "navigation"} + .container-fluid - .navbar-header - %button.navbar-toggle{"data-target" => "#bs-example-navbar-collapse-1", "data-toggle" => "collapse", type: "button"} - %span.sr-only Toggle navigation - %span.icon-bar - %span.icon-bar - %span.icon-bar + .navbar-header + %button.navbar-toggle{"data-target" => "#bs-example-navbar-collapse-1", "data-toggle" => "collapse", type: "button"} + %span.sr-only Toggle navigation + %span.icon-bar + %span.icon-bar + %span.icon-bar - #bs-example-navbar-collapse-1.collapse.navbar-collapse - %ul.nav.navbar-nav - -if @admin_space - =render :partial => "admin/admin_spaces/#{@admin_space.to_s}" + #bs-example-navbar-collapse-1.collapse.navbar-collapse + %ul.nav.navbar-nav + -if @admin_space + =render :partial => "admin/admin_spaces/#{@admin_space.to_s}" @@ -94,25 +94,27 @@ - %ul.nav.navbar-nav.navbar-right - %li.dropdown - %a.dropdown-toggle{"data-toggle" => "dropdown", href: "#"} - =current_admin.firstname - =current_admin.name - %b.caret + %ul.nav.navbar-nav.navbar-right + %li.dropdown + %a.dropdown-toggle{"data-toggle" => "dropdown", href: "#"} + =current_admin.firstname + =current_admin.name + %b.caret - %ul.dropdown-menu - %li= link_to "Gestion des admins", admin_admins_path - %li.divider - %li=link_to "Se déconnecter", admin_admin_auth_path(1), method: :delete - + %ul.dropdown-menu + %li= link_to "Gestion des admins", admin_admins_path + %li.divider + %li=link_to "Se déconnecter", admin_admin_auth_path(1), method: :delete - + %li + =link_to ic(:refresh), "#", :onclick => "location.reload();" + + = yield :header - = yield + #main_yield= yield diff --git a/app/views/qi/_qi_ordered_table.html.haml b/app/views/qi/_qi_ordered_table.html.haml new file mode 100644 index 0000000..78fb017 --- /dev/null +++ b/app/views/qi/_qi_ordered_table.html.haml @@ -0,0 +1,261 @@ +-qi_ordered_table_name = qi_ordered_table_collection.klass.to_s.tableize + +-qi_ordered_table_model = qi_ordered_table_collection.klass + + + +=render :partial => "qi/qi_ordered_table_head", :locals => {:qi_ordered_table_name => qi_ordered_table_name, :qi_ordered_table_model => qi_ordered_table_model} + + +-@qi_table_orders = @qi_table_orders || {} + +-if current_admin + + -if ap = current_admin.admin_preferences.where(:key => "sort_table_"+qi_ordered_table_name).first + -qi_ordered_table_personalised = ap.value + + + -if ap = current_admin.admin_preferences.where(:key => "sort_table_"+qi_ordered_table_name+"_nbr_col").first + -qi_ordered_table_nbr_col = ap.value + -else + -qi_ordered_table_nbr_col = 1 + + + +-else + -qi_ordered_table_personalised = session[:qi_sort_string][qi_ordered_table_name] + + -qi_ordered_table_nbr_col = session[:qi_sort_string][qi_ordered_table_name+"_nbr_col"] || 1 + + + + + + +%span.qi_ordered_table_column{:onclick => "$(this).next('.qi_ordered_table_sort_select_wrapper').toggle();"} + =ic :columns + + +.qi_ordered_table_sort_select_wrapper{:style => "display:none;"} + =form_tag request.url, :method => "get", :onsubmit => "", :remote => false do + + + =hidden_field_tag "qi_sort_string[class]",qi_ordered_table_name + + =hidden_field_tag "qi_sort_string[list]", "", :class => "qi_sort_string" + .qi_ordered_table_sort_select + + -my_keys = [] + -@qi_table_orders[qi_ordered_table_name.to_sym].each do |key, value| + .qi_order_item{:"data-ref" => "#{key}", :class => "active", :onclick => "$(this).toggleClass('active');"} + -if value.instance_of? Hash + =value[:name] + -else + =value + -my_keys << key + + + -qi_ordered_table_collection.klass.qi_table_order.each do |key, value| + -if !my_keys.include?(key) + .qi_order_item{:"data-ref" => "#{key}", :onclick => "$(this).toggleClass('active');"} + -if value.instance_of? Hash + =value[:name] + -else + =value + %hr{:style => "margin:3px 0;"} + -if false + Colonnes fixes : + =select_tag "qi_sort_string[nbr_colonnes]", options_for_select([0,1,2,3], qi_ordered_table_nbr_col) + + + =link_to "Mettre à jour", "#", :class => "btn btn-primary update_table_order_link" + + +:scss + .qi_ordered_table_column{ + position:absolute; + color:rgba(0,0,0,0.2); + font-size:1.2em; + padding-top:3px; + padding-left:10px; + cursor:pointer; + + &:hover{ + color:rgba(0,0,0,0.6); + } + + } + + .qi_ordered_table_sort_select_wrapper{ + background:rgba(white, 0.98); + box-shadow:0 0 10px rgba(0,0,0,0.2); + width:auto; + position:absolute; + margin-left:15px; + margin-top:25px; + z-index:5; + padding:5px 10px; + .qi_order_item{ + padding:2px 0; + cursor:pointer; + + } + .active{ + font-weight:bold; + } + } + +:coffeescript + $(".update_table_order_link").click -> + r = [] + $(this).closest('.qi_ordered_table_sort_select_wrapper').find(".qi_order_item").each -> + if $(this).hasClass("active") + r.push $(this).data("ref") + + + $(this).closest("form").find(".qi_sort_string").val(r.join(',')) + $.ajax + type: "GET", + url: "/", + data: $(this).closest("form").serialize(), + success: -> + location.reload() + + + + + + + + $( ".qi_ordered_table_sort_select" ).sortable + axis: "y" + + + + + +.qi_pannel.padding.new_table_container + .table-slider + .inner +
+ +
+ .table-area + .table-area-inner + + + .freezeTable + %table.table.table-striped.table-hover.table-bordered.data_table + %thead.header + %tr + -@qi_table_orders[qi_ordered_table_name.to_sym].each do |key, value| + -if value.instance_of? Hash + -if value[:reorder] + -sort_name = value[:sort_name] ? value[:sort_name] : key + + %th=raw sort_link sort_name.to_s, value[:name] + -else + %th=raw value[:name] + + -else + %th=raw value + + + =#sort_link "code", "Code" + + + -if false + %th + + + %tbody{:id => "#{qi_ordered_table_name}_rows"} + =render qi_ordered_table_collection + + + .qi_pagination + = paginate qi_ordered_table_collection #, :remote => true + +:scss + .table-slider{ + position:fixed; + bottom:0; + width:200px; + right:0; + z-index:2; + background:rgba(black,0.3); + padding:10px 20px; + padding-left:20px; + + border-radius:40px 0 0 0; + opacity:0.4; + &:hover{ + opacity:1; + background:rgba(black,0.7); + box-shadow:0 0 5px rgba(black,0.2); + } + } + + + + +:javascript + resize(); + $('.freezeTable').freezeTable({columnNum:#{qi_ordered_table_nbr_col},fixedNavbar:'#qi_header_wrapper'}); + + + +:coffeescript + #mousemove + + + + lastScrollLeft = 0 + $(".freezeTable").scroll -> + #alert("t") + documentScrollLeft = $(this).scrollLeft() + + if (lastScrollLeft != documentScrollLeft) + + lastScrollLeft = documentScrollLeft + + size = ($(this).find(".table").outerWidth() - $(this).outerWidth()) + + value = ( $(this).scrollLeft() / size)*100 + + + $(this).closest(".new_table_container").find(".range").val(value) + + + + + + + $(".freezeTable").each -> + freeze = $(this) + + + + $("document").on "scroll", -> + if ($(this).scrollTop() < freeze.offset[0] + freeze.outerHeight()) + freeze.closest(".new_table_container").find(".table-slider").show() + + else + freeze.closest(".new_table_container").find(".table-slider").hide() + + + $(".range").on 'input change mousemove', -> + + freeze = $(this).closest(".new_table_container").find(".freezeTable") + + size = (freeze.find(".table").outerWidth() - freeze.outerWidth()) + + value = size*($(this).val() / 100) + + freeze.scrollLeft(value); + + + + + +=#1 + diff --git a/app/views/qi/_qi_ordered_table.html.haml.old b/app/views/qi/_qi_ordered_table.html.haml.old new file mode 100644 index 0000000..6105a21 --- /dev/null +++ b/app/views/qi/_qi_ordered_table.html.haml.old @@ -0,0 +1,177 @@ +-qi_ordered_table_name = qi_ordered_table_collection.klass.to_s.tableize + +-qi_ordered_table_model = qi_ordered_table_collection.klass + + + +=render :partial => "qi/qi_ordered_table_head", :locals => {:qi_ordered_table_name => qi_ordered_table_name, :qi_ordered_table_model => qi_ordered_table_model} + + +-@qi_table_orders = @qi_table_orders || {} + +-if current_admin + + -if ap = current_admin.admin_preferences.where(:key => "sort_table_"+qi_ordered_table_name).first + -qi_ordered_table_personalised = ap.value + + + -if ap = current_admin.admin_preferences.where(:key => "sort_table_"+qi_ordered_table_name+"_nbr_col").first + -qi_ordered_table_nbr_col = ap.value + -else + -qi_ordered_table_nbr_col = 1 + + + +-else + -qi_ordered_table_personalised = session[:qi_sort_string][qi_ordered_table_name] + + -qi_ordered_table_nbr_col = session[:qi_sort_string][qi_ordered_table_name+"_nbr_col"] || 1 + + + + + + +%span.qi_ordered_table_column{:onclick => "$(this).next('.qi_ordered_table_sort_select_wrapper').toggle();"} + =ic :columns + + +.qi_ordered_table_sort_select_wrapper{:style => "display:none;"} + =form_tag request.url, :method => "get", :onsubmit => "", :remote => false do + + + =hidden_field_tag "qi_sort_string[class]",qi_ordered_table_name + + =hidden_field_tag "qi_sort_string[list]", "", :class => "qi_sort_string" + .qi_ordered_table_sort_select + + -my_keys = [] + -@qi_table_orders[qi_ordered_table_name.to_sym].each do |key, value| + .qi_order_item{:"data-ref" => "#{key}", :class => "active", :onclick => "$(this).toggleClass('active');"} + -if value.instance_of? Hash + =value[:name] + -else + =value + -my_keys << key + + + -qi_ordered_table_collection.klass.qi_table_order.each do |key, value| + -if !my_keys.include?(key) + .qi_order_item{:"data-ref" => "#{key}", :onclick => "$(this).toggleClass('active');"} + -if value.instance_of? Hash + =value[:name] + -else + =value + %hr{:style => "margin:3px 0;"} + -if false + Colonnes fixes : + =select_tag "qi_sort_string[nbr_colonnes]", options_for_select([0,1,2,3], qi_ordered_table_nbr_col) + + + =link_to "Mettre à jour", "#", :class => "btn btn-primary update_table_order_link" + + +:scss + .qi_ordered_table_column{ + position:absolute; + color:rgba(0,0,0,0.2); + font-size:1.2em; + padding-top:3px; + padding-left:10px; + cursor:pointer; + + &:hover{ + color:rgba(0,0,0,0.6); + } + + } + + .qi_ordered_table_sort_select_wrapper{ + background:rgba(white, 0.98); + box-shadow:0 0 10px rgba(0,0,0,0.2); + width:auto; + position:absolute; + margin-left:15px; + margin-top:25px; + z-index:5; + padding:5px 10px; + .qi_order_item{ + padding:2px 0; + cursor:pointer; + + } + .active{ + font-weight:bold; + } + } + +:coffeescript + $(".update_table_order_link").click -> + r = [] + $(this).closest('.qi_ordered_table_sort_select_wrapper').find(".qi_order_item").each -> + if $(this).hasClass("active") + r.push $(this).data("ref") + + + $(this).closest("form").find(".qi_sort_string").val(r.join(',')) + $.ajax + type: "GET", + url: "/", + data: $(this).closest("form").serialize(), + success: -> + location.reload() + + + + + + + + $( ".qi_ordered_table_sort_select" ).sortable + axis: "y" + + + + + +.qi_pannel.padding.new_table_container + + .table-area + .table-area-inner + + + .freezeTable + %table.table.table-striped.table-hover.table-bordered.data_table + %thead.header + %tr + -@qi_table_orders[qi_ordered_table_name.to_sym].each do |key, value| + -if value.instance_of? Hash + -if value[:reorder] + -sort_name = value[:sort_name] ? value[:sort_name] : key + + %th=raw sort_link sort_name.to_s, value[:name] + -else + %th=raw value[:name] + + -else + %th=raw value + + + =#sort_link "code", "Code" + + + -if false + %th + + + %tbody{:id => "#{qi_ordered_table_name}_rows"} + =render qi_ordered_table_collection + + + .qi_pagination + = paginate qi_ordered_table_collection #, :remote => true + +:javascript + resize(); + $('.freezeTable').freezeTable({columnNum:#{qi_ordered_table_nbr_col},fixedNavbar:'#qi_header_wrapper'}); + \ No newline at end of file diff --git a/app/views/qi/_qi_ordered_table_head.html.haml b/app/views/qi/_qi_ordered_table_head.html.haml new file mode 100644 index 0000000..80da8d8 --- /dev/null +++ b/app/views/qi/_qi_ordered_table_head.html.haml @@ -0,0 +1,35 @@ + + +-@qi_table_orders = @qi_table_orders || {} + +-if current_admin + + -if ap = current_admin.admin_preferences.where(:key => "sort_table_"+qi_ordered_table_name).first + -qi_ordered_table_personalised = ap.value + + + -if ap = current_admin.admin_preferences.where(:key => "sort_table_"+qi_ordered_table_name+"_nbr_col").first + -qi_ordered_table_nbr_col = ap.value + -else + -qi_ordered_table_nbr_col = 1 + + + +-else + -qi_ordered_table_personalised = session[:qi_sort_string][qi_ordered_table_name] + + -qi_ordered_table_nbr_col = session[:qi_sort_string][qi_ordered_table_name+"_nbr_col"] || 1 + + + + +-if qi_ordered_table_personalised.to_s != "" + -@qi_table_orders[qi_ordered_table_name.to_sym] = {} + + -qi_ordered_table_personalised.split(",").each do |k| + -if qi_ordered_table_model.qi_table_order[k.to_sym] + + -@qi_table_orders[qi_ordered_table_name.to_sym][k.to_sym] = qi_ordered_table_model.qi_table_order[k.to_sym] + +-else + -@qi_table_orders[qi_ordered_table_name.to_sym] = qi_ordered_table_model.qi_table_order diff --git a/app/views/qi/_qi_ordered_table_head.html.haml.old b/app/views/qi/_qi_ordered_table_head.html.haml.old new file mode 100644 index 0000000..80da8d8 --- /dev/null +++ b/app/views/qi/_qi_ordered_table_head.html.haml.old @@ -0,0 +1,35 @@ + + +-@qi_table_orders = @qi_table_orders || {} + +-if current_admin + + -if ap = current_admin.admin_preferences.where(:key => "sort_table_"+qi_ordered_table_name).first + -qi_ordered_table_personalised = ap.value + + + -if ap = current_admin.admin_preferences.where(:key => "sort_table_"+qi_ordered_table_name+"_nbr_col").first + -qi_ordered_table_nbr_col = ap.value + -else + -qi_ordered_table_nbr_col = 1 + + + +-else + -qi_ordered_table_personalised = session[:qi_sort_string][qi_ordered_table_name] + + -qi_ordered_table_nbr_col = session[:qi_sort_string][qi_ordered_table_name+"_nbr_col"] || 1 + + + + +-if qi_ordered_table_personalised.to_s != "" + -@qi_table_orders[qi_ordered_table_name.to_sym] = {} + + -qi_ordered_table_personalised.split(",").each do |k| + -if qi_ordered_table_model.qi_table_order[k.to_sym] + + -@qi_table_orders[qi_ordered_table_name.to_sym][k.to_sym] = qi_ordered_table_model.qi_table_order[k.to_sym] + +-else + -@qi_table_orders[qi_ordered_table_name.to_sym] = qi_ordered_table_model.qi_table_order diff --git a/app/views/qi/_qi_ordered_table_object.html.haml b/app/views/qi/_qi_ordered_table_object.html.haml new file mode 100644 index 0000000..dafe995 --- /dev/null +++ b/app/views/qi/_qi_ordered_table_object.html.haml @@ -0,0 +1,28 @@ +-qi_ordered_table_model = object.class +-qi_ordered_table_name = qi_ordered_table_model.to_s.tableize + +-if !@qi_table_orders + =render :partial => "qi/qi_ordered_table_head", :locals => {:qi_ordered_table_name => qi_ordered_table_name, :qi_ordered_table_model => qi_ordered_table_model} + + + + + +-@qi_table_orders[qi_ordered_table_name.to_sym].each do |key,value| + -if tr[:"#{key}"] + =raw tr[:"#{key}"] + + -elsif object.respond_to?("tr_"+key.to_s) + %td + =#eval("#{qi_ordered_table_name.singularize}.send('#{key}')") + =object.send("tr_"+key.to_s) + + -elsif object.respond_to?(key.to_s) + %td + =#eval("#{qi_ordered_table_name.singularize}.send('#{key}')") + =object.send(key.to_s) + + -else + %td + Err : + =key diff --git a/app/views/qi/_qi_ordered_table_search_footer.html.haml b/app/views/qi/_qi_ordered_table_search_footer.html.haml new file mode 100644 index 0000000..b9fe2dd --- /dev/null +++ b/app/views/qi/_qi_ordered_table_search_footer.html.haml @@ -0,0 +1,10 @@ +=link_to ic(:search)+" Rechercher", "#", :class => "btn btn-default btn-qi-search", :onclick => "$(this).closest('form').submit();$(this).html('...');return false;" + + +.results_count + ="(#{collection_object.total_count}) résultat(s)" + + ="-" + + =select_tag "search[per_page]", options_for_select([50,100,200,500], params[:search][:per_page]) + résultats par page \ No newline at end of file diff --git a/config/initializers/qi.rb b/config/initializers/qi.rb new file mode 100644 index 0000000..08793b5 --- /dev/null +++ b/config/initializers/qi.rb @@ -0,0 +1,4 @@ +require "acts_as_caching" + + +require "acts_as_sorting" \ No newline at end of file diff --git a/db/migrate/20200216215344_create_admin_preferences.rb b/db/migrate/20200216215344_create_admin_preferences.rb new file mode 100644 index 0000000..5ad69ae --- /dev/null +++ b/db/migrate/20200216215344_create_admin_preferences.rb @@ -0,0 +1,11 @@ +class CreateAdminPreferences < ActiveRecord::Migration + def change + create_table :admin_preferences do |t| + t.references :admin, foreign_key: true + t.string :key + t.text :value + + t.timestamps + end + end +end diff --git a/db/migrate/20200318223627_add_totals_to_p_customer_sheets.rb b/db/migrate/20200318223627_add_totals_to_p_customer_sheets.rb new file mode 100644 index 0000000..e165280 --- /dev/null +++ b/db/migrate/20200318223627_add_totals_to_p_customer_sheets.rb @@ -0,0 +1,16 @@ +class AddTotalsToPCustomerSheets < ActiveRecord::Migration + def change + add_column :p_customer_sheets, :cc_total_ht, :decimal, precision: 14, scale: 2 + add_column :p_customer_sheets, :ac_total_ht, :decimal, precision: 14, scale: 2 + add_column :p_customer_sheets, :cc_total_tva, :decimal, precision: 14, scale: 2 + add_column :p_customer_sheets, :ac_total_tva, :decimal, precision: 14, scale: 2 + add_column :p_customer_sheets, :cc_total_ttc, :decimal, precision: 14, scale: 2 + add_column :p_customer_sheets, :ac_total_ttc, :decimal, precision: 14, scale: 2 + add_column :p_customer_sheets, :archived, :boolean, :default => false + + + PCustomerSheet.all.each do |pcs| + pcs.save + end + end +end diff --git a/db/schema.rb b/db/schema.rb index ddb0a40..cffab7f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20191113231005) do +ActiveRecord::Schema.define(version: 20200318223627) do create_table "admin_admin_roles", force: :cascade do |t| t.integer "admin_id", limit: 4 @@ -39,6 +39,16 @@ ActiveRecord::Schema.define(version: 20191113231005) do t.datetime "updated_at", null: false end + create_table "admin_preferences", force: :cascade do |t| + t.integer "admin_id", limit: 4 + t.string "key", limit: 255 + t.text "value", limit: 65535 + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "admin_preferences", ["admin_id"], name: "fk_rails_8897321ed6", using: :btree + create_table "admin_roles", force: :cascade do |t| t.string "name", limit: 255 t.datetime "created_at", null: false @@ -854,6 +864,13 @@ ActiveRecord::Schema.define(version: 20191113231005) do t.text "obs_devis", limit: 65535 t.text "obs_bdc", limit: 65535 t.text "obs_bdl", limit: 65535 + t.decimal "cc_total_ht", precision: 14, scale: 2 + t.decimal "ac_total_ht", precision: 14, scale: 2 + t.decimal "cc_total_tva", precision: 14, scale: 2 + t.decimal "ac_total_tva", precision: 14, scale: 2 + t.decimal "cc_total_ttc", precision: 14, scale: 2 + t.decimal "ac_total_ttc", precision: 14, scale: 2 + t.boolean "archived", default: false end add_index "p_customer_sheets", ["p_payment_type_id"], name: "index_p_customer_sheets_on_p_payment_type_id", using: :btree @@ -1666,6 +1683,7 @@ ActiveRecord::Schema.define(version: 20191113231005) do add_foreign_key "admin_admin_roles", "admins" add_foreign_key "admin_permission_admin_roles", "admin_permissions" add_foreign_key "admin_permission_admin_roles", "admin_roles" + add_foreign_key "admin_preferences", "admins" add_foreign_key "articleindexs_contents", "categories" add_foreign_key "articles", "article_authors" add_foreign_key "block_contents", "image_files" diff --git a/lib/acts_as_caching.rb b/lib/acts_as_caching.rb new file mode 100644 index 0000000..8d6197b --- /dev/null +++ b/lib/acts_as_caching.rb @@ -0,0 +1,9 @@ +require 'active_support/core_ext' +p "loading main" +require File.join(File.dirname(__FILE__), "acts_as_caching/railtie.rb") + +module ActsAsCaching + autoload :Hook, File.join(File.dirname(__FILE__), "acts_as_caching/hook") + #autoload :InstanceMethods, File.join(File.dirname(__FILE__), "acts_as_caching/instance_methods") +end + diff --git a/lib/acts_as_caching/hook.rb b/lib/acts_as_caching/hook.rb new file mode 100644 index 0000000..0eabb1d --- /dev/null +++ b/lib/acts_as_caching/hook.rb @@ -0,0 +1,74 @@ +module ActsAsCaching::Hook + def acts_as_caching(*args) + @acts_as_caching_options = args.extract_options! + + + def self.qi_cache_fields + @acts_as_caching_options[:fields] + + end + + + @acts_as_caching_options[:fields].each do |s| + define_method("#{s}") { + return eval("!self.ac_#{s} ? self.ca_#{s} : self.ac_#{s}") + } + end + + + + + + + + define_method("qi_dynamics_cache"){ + puts "qi_dynamics_cache" + + if self.methods.include?(:to_no_archive) + self.to_no_archive.each do |noc| + eval("self.ac_#{noc} = nil") + end + + + end + + + self.class.qi_cache_fields.each do |s| + eval("self.cc_#{s} = self.#{s}") + end + } + + after_validation :qi_dynamics_cache + + define_method("archive_now"){ + self.qi_dynamics_cache + self.archived = true + + self.class.qi_cache_fields.each do |s| + eval("self.ac_#{s} = self.cc_#{s} ") + end + + self.personalised_archive if self.methods.include?(:personalised_archive) + self.save + } + + define_method("unarchive_now"){ + self.archived = false + self.qi_dynamics_cache + + self.class.qi_cache_fields.each do |s| + eval("self.ac_#{s} = nil ") + end + + self.personalised_unarchive if self.methods.include?(:personalised_unarchive) + + self.save + } + + + end + + + + +end diff --git a/lib/acts_as_caching/railtie.rb b/lib/acts_as_caching/railtie.rb new file mode 100644 index 0000000..d1770b6 --- /dev/null +++ b/lib/acts_as_caching/railtie.rb @@ -0,0 +1,18 @@ +require 'rails' +require 'acts_as_caching' + +p "Railtie loaded" + +begin +module ActsAsCaching + class Railtie < Rails::Railtie + config.to_prepare do + p "hook added" + ActiveRecord::Base.send(:extend, ActsAsCaching::Hook) + end + end +end +rescue +p $!, $!.message +raise $! +end diff --git a/lib/acts_as_sorting.rb b/lib/acts_as_sorting.rb new file mode 100644 index 0000000..93da84e --- /dev/null +++ b/lib/acts_as_sorting.rb @@ -0,0 +1,9 @@ +require 'active_support/core_ext' +p "loading main" +require File.join(File.dirname(__FILE__), "acts_as_sorting/railtie.rb") + +module ActsAsSorting + autoload :Hook, File.join(File.dirname(__FILE__), "acts_as_sorting/hook") + #autoload :InstanceMethods, File.join(File.dirname(__FILE__), "acts_as_sorting/instance_methods") +end + diff --git a/lib/acts_as_sorting/hook.rb b/lib/acts_as_sorting/hook.rb new file mode 100644 index 0000000..2ac1717 --- /dev/null +++ b/lib/acts_as_sorting/hook.rb @@ -0,0 +1,39 @@ +module ActsAsSorting::Hook + def acts_as_sorting(*args) + @options = args.extract_options! + + + def self.qi_table_order + @options[:fields] + + end + + def self.valid_sort + r = [] + self.qi_table_order.each do |key, value| + if value.instance_of? Hash + if value[:reorder] == false + + elsif value[:reorder] == true + if value[:sort_name] + r << value[:sort_name] + else + r << key.to_s + end + + end + end + end + return r + + + end + + + + end + + + + +end diff --git a/lib/acts_as_sorting/railtie.rb b/lib/acts_as_sorting/railtie.rb new file mode 100644 index 0000000..27f6dde --- /dev/null +++ b/lib/acts_as_sorting/railtie.rb @@ -0,0 +1,18 @@ +require 'rails' +require 'acts_as_sorting' + +p "Railtie loaded" + +begin +module ActsAsSorting + class Railtie < Rails::Railtie + config.to_prepare do + p "hook sorting added" + ActiveRecord::Base.send(:extend, ActsAsSorting::Hook) + end + end +end +rescue +p $!, $!.message +raise $! +end diff --git a/lib/assets/.keep b/lib/assets/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/lib/tasks/.keep b/lib/tasks/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/lib/tasks/export_survey.rake b/lib/tasks/export_survey.rake deleted file mode 100644 index 3d4654b..0000000 --- a/lib/tasks/export_survey.rake +++ /dev/null @@ -1,176 +0,0 @@ -namespace :survey do - desc "TODO" - - - task export_2017: :environment do - - - @survey = SurveyType.find(9) - - @survey_sets = @survey.survey_sets.where(:is_fill => true) - - #@survey_sets = @survey_sets.where("created_at < ?", Date.parse("2017/06/27").beginning_of_day) - @survey_sets = @survey_sets.where("created_at < ? and created_at >= ?", Date.parse("2017/07/19").beginning_of_day,Date.parse("2017/06/27").beginning_of_day) - - - headers = [] - headers << "id" - headers << "date" - @survey.items.each do |survey_item| - headers << survey_item.title - - - if survey_item.questions_type == 3 - survey_item.answers.each do |survey_item_answer| - headers << survey_item_answer.label_text - end - end - end - - - - @csv = CSV.generate(:headers => true, :col_sep => ";") do |csv| - csv << headers - - - - - @survey_sets.each do |survey_set| - line = [] - - line << survey_set.id - puts survey_set.id - line << survey_set.created_at - survey_set.survey_type.items.each do |survey_item| - question_set = survey_set.question_sets.find_by_survey_item_id(survey_item.id) - line < :replace, :replace => '') - end - - - #send_data @csv.encode('iso-8859-1', :undef => :replace, :replace => ''), :filename => "export-survey-#{Date.today.to_s.to_slug}.csv", :type => 'text/csv; charset=iso-8859-1; header=present' } - - - - - end - - - - task export_all: :environment do - - - @survey = SurveyType.find(9) - - @survey_sets = @survey.survey_sets.where(:is_fill => true) - - #@survey_sets = @survey_sets.where("created_at < ?", Date.parse("2017/06/27").beginning_of_day) - @survey_sets = @survey_sets.where("created_at < ? and created_at >= ?", Date.parse("2017/10/11").beginning_of_day,Date.parse("2000/06/27").beginning_of_day) - - - headers = [] - headers << "id" - headers << "date" - @survey.items.each do |survey_item| - headers << survey_item.title - - - if survey_item.questions_type == 3 - survey_item.answers.each do |survey_item_answer| - headers << survey_item_answer.label_text - end - end - end - - - - @csv = CSV.generate(:headers => true, :col_sep => ";") do |csv| - csv << headers - - - - - @survey_sets.each do |survey_set| - line = [] - - line << survey_set.id - puts survey_set.id - line << survey_set.created_at - survey_set.survey_type.items.each do |survey_item| - question_set = survey_set.question_sets.find_by_survey_item_id(survey_item.id) - line < :replace, :replace => '') - end - - - #send_data @csv.encode('iso-8859-1', :undef => :replace, :replace => ''), :filename => "export-survey-#{Date.today.to_s.to_slug}.csv", :type => 'text/csv; charset=iso-8859-1; header=present' } - - - - - end - - -end diff --git a/lib/tasks/fourrure.rake b/lib/tasks/fourrure.rake deleted file mode 100644 index 4531149..0000000 --- a/lib/tasks/fourrure.rake +++ /dev/null @@ -1,20 +0,0 @@ -namespace :fourrure do - desc "TODO" - - - task import: :environment do - @file = File.open(Rails.root.join('import_csv/fourrure_clean_mail.csv')).read - - r = Regexp.new(/\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}\b/) - @emails = @file.scan(r).uniq - - @emails.each do |mail| - fs = FourrureSender.new(:email => mail, :cgv => true, :name => "NA", :firstname => "NA", :imported => true) - fs.save - puts mail - end - - end - - -end