Compare commits
	
		
			4 Commits
		
	
	
		
			master
			...
			0913_ntu_g
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								 | 
						f9485c1f86 | |
| 
							
							
								 | 
						cd26b880fb | |
| 
							
							
								 | 
						7c398ce4fe | |
| 
							
							
								 | 
						d766eea9f4 | 
| 
						 | 
				
			
			@ -4,6 +4,8 @@
 | 
			
		|||
.rvmrc
 | 
			
		||||
 | 
			
		||||
Gemfile.lock
 | 
			
		||||
Procfile
 | 
			
		||||
log/*
 | 
			
		||||
 | 
			
		||||
db/*.sqlite3
 | 
			
		||||
log/*.log
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.1 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 4.0 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.0 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 44 KiB  | 
| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
!function ($) {
 | 
			
		||||
	$.fn.cardCheck = function(param) {
 | 
			
		||||
		_defaultSettings = {
 | 
			
		||||
			check: '',
 | 
			
		||||
		};
 | 
			
		||||
		_set = $.extend(_defaultSettings, param);
 | 
			
		||||
		$card = $(this);
 | 
			
		||||
		$check = _set.check;
 | 
			
		||||
		$check.each(function(){
 | 
			
		||||
			if($(this).attr('checked')) {
 | 
			
		||||
			$(this).parent($card).addClass("active");
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
		$card.on('click', function() {
 | 
			
		||||
			$(this).toggleClass('active')
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}(window.jQuery);
 | 
			
		||||
$(function(){
 | 
			
		||||
	$('.checkbox-card > li').cardCheck({
 | 
			
		||||
		check: $('.checkbox-card > li input[type="checkbox"]'),
 | 
			
		||||
	});
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,752 @@
 | 
			
		|||
/*! nanoScrollerJS - v0.7.2
 | 
			
		||||
* http://jamesflorentino.github.com/nanoScrollerJS/
 | 
			
		||||
* Copyright (c) 2013 James Florentino; Licensed MIT */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
(function($, window, document) {
 | 
			
		||||
  "use strict";
 | 
			
		||||
 | 
			
		||||
  var BROWSER_IS_IE7, BROWSER_SCROLLBAR_WIDTH, DOMSCROLL, DOWN, DRAG, KEYDOWN, KEYUP, MOUSEDOWN, MOUSEMOVE, MOUSEUP, MOUSEWHEEL, NanoScroll, PANEDOWN, RESIZE, SCROLL, SCROLLBAR, TOUCHMOVE, UP, WHEEL, defaults, getBrowserScrollbarWidth;
 | 
			
		||||
  defaults = {
 | 
			
		||||
    /**
 | 
			
		||||
      a classname for the pane element.
 | 
			
		||||
      @property paneClass
 | 
			
		||||
      @type String
 | 
			
		||||
      @default 'pane'
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    paneClass: 'pane',
 | 
			
		||||
    /**
 | 
			
		||||
      a classname for the slider element.
 | 
			
		||||
      @property sliderClass
 | 
			
		||||
      @type String
 | 
			
		||||
      @default 'slider'
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    sliderClass: 'slider',
 | 
			
		||||
    /**
 | 
			
		||||
      a classname for the content element.
 | 
			
		||||
      @property contentClass
 | 
			
		||||
      @type String
 | 
			
		||||
      @default 'content'
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    contentClass: 'content',
 | 
			
		||||
    /**
 | 
			
		||||
      a setting to enable native scrolling in iOS devices.
 | 
			
		||||
      @property iOSNativeScrolling
 | 
			
		||||
      @type Boolean
 | 
			
		||||
      @default false
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    iOSNativeScrolling: false,
 | 
			
		||||
    /**
 | 
			
		||||
      a setting to prevent the rest of the page being
 | 
			
		||||
      scrolled when user scrolls the `.content` element.
 | 
			
		||||
      @property preventPageScrolling
 | 
			
		||||
      @type Boolean
 | 
			
		||||
      @default false
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    preventPageScrolling: false,
 | 
			
		||||
    /**
 | 
			
		||||
      a setting to disable binding to the resize event.
 | 
			
		||||
      @property disableResize
 | 
			
		||||
      @type Boolean
 | 
			
		||||
      @default false
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    disableResize: false,
 | 
			
		||||
    /**
 | 
			
		||||
      a setting to make the scrollbar always visible.
 | 
			
		||||
      @property alwaysVisible
 | 
			
		||||
      @type Boolean
 | 
			
		||||
      @default false
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    alwaysVisible: false,
 | 
			
		||||
    /**
 | 
			
		||||
      a default timeout for the `flash()` method.
 | 
			
		||||
      @property flashDelay
 | 
			
		||||
      @type Number
 | 
			
		||||
      @default 1500
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    flashDelay: 1500,
 | 
			
		||||
    /**
 | 
			
		||||
      a minimum height for the `.slider` element.
 | 
			
		||||
      @property sliderMinHeight
 | 
			
		||||
      @type Number
 | 
			
		||||
      @default 20
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    sliderMinHeight: 20,
 | 
			
		||||
    /**
 | 
			
		||||
      a maximum height for the `.slider` element.
 | 
			
		||||
      @property sliderMaxHeight
 | 
			
		||||
      @type Number
 | 
			
		||||
      @default null
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    sliderMaxHeight: null
 | 
			
		||||
  };
 | 
			
		||||
  /**
 | 
			
		||||
    @property SCROLLBAR
 | 
			
		||||
    @type String
 | 
			
		||||
    @static
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  SCROLLBAR = 'scrollbar';
 | 
			
		||||
  /**
 | 
			
		||||
    @property SCROLL
 | 
			
		||||
    @type String
 | 
			
		||||
    @static
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  SCROLL = 'scroll';
 | 
			
		||||
  /**
 | 
			
		||||
    @property MOUSEDOWN
 | 
			
		||||
    @type String
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  MOUSEDOWN = 'mousedown';
 | 
			
		||||
  /**
 | 
			
		||||
    @property MOUSEMOVE
 | 
			
		||||
    @type String
 | 
			
		||||
    @static
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  MOUSEMOVE = 'mousemove';
 | 
			
		||||
  /**
 | 
			
		||||
    @property MOUSEWHEEL
 | 
			
		||||
    @type String
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  MOUSEWHEEL = 'mousewheel';
 | 
			
		||||
  /**
 | 
			
		||||
    @property MOUSEUP
 | 
			
		||||
    @type String
 | 
			
		||||
    @static
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  MOUSEUP = 'mouseup';
 | 
			
		||||
  /**
 | 
			
		||||
    @property RESIZE
 | 
			
		||||
    @type String
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  RESIZE = 'resize';
 | 
			
		||||
  /**
 | 
			
		||||
    @property DRAG
 | 
			
		||||
    @type String
 | 
			
		||||
    @static
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  DRAG = 'drag';
 | 
			
		||||
  /**
 | 
			
		||||
    @property UP
 | 
			
		||||
    @type String
 | 
			
		||||
    @static
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  UP = 'up';
 | 
			
		||||
  /**
 | 
			
		||||
    @property PANEDOWN
 | 
			
		||||
    @type String
 | 
			
		||||
    @static
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  PANEDOWN = 'panedown';
 | 
			
		||||
  /**
 | 
			
		||||
    @property DOMSCROLL
 | 
			
		||||
    @type String
 | 
			
		||||
    @static
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  DOMSCROLL = 'DOMMouseScroll';
 | 
			
		||||
  /**
 | 
			
		||||
    @property DOWN
 | 
			
		||||
    @type String
 | 
			
		||||
    @static
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  DOWN = 'down';
 | 
			
		||||
  /**
 | 
			
		||||
    @property WHEEL
 | 
			
		||||
    @type String
 | 
			
		||||
    @static
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  WHEEL = 'wheel';
 | 
			
		||||
  /**
 | 
			
		||||
    @property KEYDOWN
 | 
			
		||||
    @type String
 | 
			
		||||
    @static
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  KEYDOWN = 'keydown';
 | 
			
		||||
  /**
 | 
			
		||||
    @property KEYUP
 | 
			
		||||
    @type String
 | 
			
		||||
    @static
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  KEYUP = 'keyup';
 | 
			
		||||
  /**
 | 
			
		||||
    @property TOUCHMOVE
 | 
			
		||||
    @type String
 | 
			
		||||
    @static
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  TOUCHMOVE = 'touchmove';
 | 
			
		||||
  /**
 | 
			
		||||
    @property BROWSER_IS_IE7
 | 
			
		||||
    @type Boolean
 | 
			
		||||
    @static
 | 
			
		||||
    @final
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  BROWSER_IS_IE7 = window.navigator.appName === 'Microsoft Internet Explorer' && /msie 7./i.test(window.navigator.appVersion) && window.ActiveXObject;
 | 
			
		||||
  /**
 | 
			
		||||
    @property BROWSER_SCROLLBAR_WIDTH
 | 
			
		||||
    @type Number
 | 
			
		||||
    @static
 | 
			
		||||
    @default null
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  BROWSER_SCROLLBAR_WIDTH = null;
 | 
			
		||||
  /**
 | 
			
		||||
    Returns browser's native scrollbar width
 | 
			
		||||
    @method getBrowserScrollbarWidth
 | 
			
		||||
    @return {Number} the scrollbar width in pixels
 | 
			
		||||
    @static
 | 
			
		||||
    @private
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  getBrowserScrollbarWidth = function() {
 | 
			
		||||
    var outer, outerStyle, scrollbarWidth;
 | 
			
		||||
    outer = document.createElement('div');
 | 
			
		||||
    outerStyle = outer.style;
 | 
			
		||||
    outerStyle.position = 'absolute';
 | 
			
		||||
    outerStyle.width = '100px';
 | 
			
		||||
    outerStyle.height = '100px';
 | 
			
		||||
    outerStyle.overflow = SCROLL;
 | 
			
		||||
    outerStyle.top = '-9999px';
 | 
			
		||||
    document.body.appendChild(outer);
 | 
			
		||||
    scrollbarWidth = outer.offsetWidth - outer.clientWidth;
 | 
			
		||||
    document.body.removeChild(outer);
 | 
			
		||||
    return scrollbarWidth;
 | 
			
		||||
  };
 | 
			
		||||
  /**
 | 
			
		||||
    @class NanoScroll
 | 
			
		||||
    @param element {HTMLElement|Node} the main element
 | 
			
		||||
    @param options {Object} nanoScroller's options
 | 
			
		||||
    @constructor
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  NanoScroll = (function() {
 | 
			
		||||
 | 
			
		||||
    function NanoScroll(el, options) {
 | 
			
		||||
      this.el = el;
 | 
			
		||||
      this.options = options;
 | 
			
		||||
      BROWSER_SCROLLBAR_WIDTH || (BROWSER_SCROLLBAR_WIDTH = getBrowserScrollbarWidth());
 | 
			
		||||
      this.$el = $(this.el);
 | 
			
		||||
      this.doc = $(document);
 | 
			
		||||
      this.win = $(window);
 | 
			
		||||
      this.$content = this.$el.children("." + options.contentClass);
 | 
			
		||||
      this.$content.attr('tabindex', 0);
 | 
			
		||||
      this.content = this.$content[0];
 | 
			
		||||
      if (this.options.iOSNativeScrolling && (this.el.style.WebkitOverflowScrolling != null)) {
 | 
			
		||||
        this.nativeScrolling();
 | 
			
		||||
      } else {
 | 
			
		||||
        this.generate();
 | 
			
		||||
      }
 | 
			
		||||
      this.createEvents();
 | 
			
		||||
      this.addEvents();
 | 
			
		||||
      this.reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      Prevents the rest of the page being scrolled
 | 
			
		||||
      when user scrolls the `.content` element.
 | 
			
		||||
      @method preventScrolling
 | 
			
		||||
      @param event {Event}
 | 
			
		||||
      @param direction {String} Scroll direction (up or down)
 | 
			
		||||
      @private
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    NanoScroll.prototype.preventScrolling = function(e, direction) {
 | 
			
		||||
      if (!this.isActive) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      if (e.type === DOMSCROLL) {
 | 
			
		||||
        if (direction === DOWN && e.originalEvent.detail > 0 || direction === UP && e.originalEvent.detail < 0) {
 | 
			
		||||
          e.preventDefault();
 | 
			
		||||
        }
 | 
			
		||||
      } else if (e.type === MOUSEWHEEL) {
 | 
			
		||||
        if (!e.originalEvent || !e.originalEvent.wheelDelta) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        if (direction === DOWN && e.originalEvent.wheelDelta < 0 || direction === UP && e.originalEvent.wheelDelta > 0) {
 | 
			
		||||
          e.preventDefault();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      Enable iOS native scrolling
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    NanoScroll.prototype.nativeScrolling = function() {
 | 
			
		||||
      this.$content.css({
 | 
			
		||||
        WebkitOverflowScrolling: 'touch'
 | 
			
		||||
      });
 | 
			
		||||
      this.iOSNativeScrolling = true;
 | 
			
		||||
      this.isActive = true;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      Updates those nanoScroller properties that
 | 
			
		||||
      are related to current scrollbar position.
 | 
			
		||||
      @method updateScrollValues
 | 
			
		||||
      @private
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    NanoScroll.prototype.updateScrollValues = function() {
 | 
			
		||||
      var content;
 | 
			
		||||
      content = this.content;
 | 
			
		||||
      this.maxScrollTop = content.scrollHeight - content.clientHeight;
 | 
			
		||||
      this.contentScrollTop = content.scrollTop;
 | 
			
		||||
      if (!this.iOSNativeScrolling) {
 | 
			
		||||
        this.maxSliderTop = this.paneHeight - this.sliderHeight;
 | 
			
		||||
        this.sliderTop = this.contentScrollTop * this.maxSliderTop / this.maxScrollTop;
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      Creates event related methods
 | 
			
		||||
      @method createEvents
 | 
			
		||||
      @private
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    NanoScroll.prototype.createEvents = function() {
 | 
			
		||||
      var _this = this;
 | 
			
		||||
      this.events = {
 | 
			
		||||
        down: function(e) {
 | 
			
		||||
          _this.isBeingDragged = true;
 | 
			
		||||
          _this.offsetY = e.pageY - _this.slider.offset().top;
 | 
			
		||||
          _this.pane.addClass('active');
 | 
			
		||||
          _this.doc.bind(MOUSEMOVE, _this.events[DRAG]).bind(MOUSEUP, _this.events[UP]);
 | 
			
		||||
          return false;
 | 
			
		||||
        },
 | 
			
		||||
        drag: function(e) {
 | 
			
		||||
          _this.sliderY = e.pageY - _this.$el.offset().top - _this.offsetY;
 | 
			
		||||
          _this.scroll();
 | 
			
		||||
          _this.updateScrollValues();
 | 
			
		||||
          if (_this.contentScrollTop >= _this.maxScrollTop) {
 | 
			
		||||
            _this.$el.trigger('scrollend');
 | 
			
		||||
          } else if (_this.contentScrollTop === 0) {
 | 
			
		||||
            _this.$el.trigger('scrolltop');
 | 
			
		||||
          }
 | 
			
		||||
          return false;
 | 
			
		||||
        },
 | 
			
		||||
        up: function(e) {
 | 
			
		||||
          _this.isBeingDragged = false;
 | 
			
		||||
          _this.pane.removeClass('active');
 | 
			
		||||
          _this.doc.unbind(MOUSEMOVE, _this.events[DRAG]).unbind(MOUSEUP, _this.events[UP]);
 | 
			
		||||
          return false;
 | 
			
		||||
        },
 | 
			
		||||
        resize: function(e) {
 | 
			
		||||
          _this.reset();
 | 
			
		||||
        },
 | 
			
		||||
        panedown: function(e) {
 | 
			
		||||
          _this.sliderY = (e.offsetY || e.originalEvent.layerY) - (_this.sliderHeight * 0.5);
 | 
			
		||||
          _this.scroll();
 | 
			
		||||
          _this.events.down(e);
 | 
			
		||||
          return false;
 | 
			
		||||
        },
 | 
			
		||||
        scroll: function(e) {
 | 
			
		||||
          if (_this.isBeingDragged) {
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
          _this.updateScrollValues();
 | 
			
		||||
          if (!_this.iOSNativeScrolling) {
 | 
			
		||||
            _this.sliderY = _this.sliderTop;
 | 
			
		||||
            _this.slider.css({
 | 
			
		||||
              top: _this.sliderTop
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
          if (e == null) {
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
          if (_this.contentScrollTop >= _this.maxScrollTop) {
 | 
			
		||||
            if (_this.options.preventPageScrolling) {
 | 
			
		||||
              _this.preventScrolling(e, DOWN);
 | 
			
		||||
            }
 | 
			
		||||
            _this.$el.trigger('scrollend');
 | 
			
		||||
          } else if (_this.contentScrollTop === 0) {
 | 
			
		||||
            if (_this.options.preventPageScrolling) {
 | 
			
		||||
              _this.preventScrolling(e, UP);
 | 
			
		||||
            }
 | 
			
		||||
            _this.$el.trigger('scrolltop');
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        wheel: function(e) {
 | 
			
		||||
          if (e == null) {
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
          _this.sliderY += -e.wheelDeltaY || -e.delta;
 | 
			
		||||
          _this.scroll();
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      Adds event listeners with jQuery.
 | 
			
		||||
      @method addEvents
 | 
			
		||||
      @private
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    NanoScroll.prototype.addEvents = function() {
 | 
			
		||||
      var events;
 | 
			
		||||
      this.removeEvents();
 | 
			
		||||
      events = this.events;
 | 
			
		||||
      if (!this.options.disableResize) {
 | 
			
		||||
        this.win.bind(RESIZE, events[RESIZE]);
 | 
			
		||||
      }
 | 
			
		||||
      if (!this.iOSNativeScrolling) {
 | 
			
		||||
        this.slider.bind(MOUSEDOWN, events[DOWN]);
 | 
			
		||||
        this.pane.bind(MOUSEDOWN, events[PANEDOWN]).bind("" + MOUSEWHEEL + " " + DOMSCROLL, events[WHEEL]);
 | 
			
		||||
      }
 | 
			
		||||
      this.$content.bind("" + SCROLL + " " + MOUSEWHEEL + " " + DOMSCROLL + " " + TOUCHMOVE, events[SCROLL]);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      Removes event listeners with jQuery.
 | 
			
		||||
      @method removeEvents
 | 
			
		||||
      @private
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    NanoScroll.prototype.removeEvents = function() {
 | 
			
		||||
      var events;
 | 
			
		||||
      events = this.events;
 | 
			
		||||
      this.win.unbind(RESIZE, events[RESIZE]);
 | 
			
		||||
      if (!this.iOSNativeScrolling) {
 | 
			
		||||
        this.slider.unbind();
 | 
			
		||||
        this.pane.unbind();
 | 
			
		||||
      }
 | 
			
		||||
      this.$content.unbind("" + SCROLL + " " + MOUSEWHEEL + " " + DOMSCROLL + " " + TOUCHMOVE, events[SCROLL]);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      Generates nanoScroller's scrollbar and elements for it.
 | 
			
		||||
      @method generate
 | 
			
		||||
      @chainable
 | 
			
		||||
      @private
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    NanoScroll.prototype.generate = function() {
 | 
			
		||||
      var contentClass, cssRule, options, paneClass, sliderClass;
 | 
			
		||||
      options = this.options;
 | 
			
		||||
      paneClass = options.paneClass, sliderClass = options.sliderClass, contentClass = options.contentClass;
 | 
			
		||||
      if (!this.$el.find("" + paneClass).length && !this.$el.find("" + sliderClass).length) {
 | 
			
		||||
        this.$el.append("<div class=\"" + paneClass + "\"><div class=\"" + sliderClass + "\" /></div>");
 | 
			
		||||
      }
 | 
			
		||||
      this.pane = this.$el.children("." + paneClass);
 | 
			
		||||
      this.slider = this.pane.find("." + sliderClass);
 | 
			
		||||
      if (BROWSER_SCROLLBAR_WIDTH) {
 | 
			
		||||
        cssRule = this.$el.css('direction') === 'rtl' ? {
 | 
			
		||||
          left: -BROWSER_SCROLLBAR_WIDTH
 | 
			
		||||
        } : {
 | 
			
		||||
          right: -BROWSER_SCROLLBAR_WIDTH
 | 
			
		||||
        };
 | 
			
		||||
        this.$el.addClass('has-scrollbar');
 | 
			
		||||
      }
 | 
			
		||||
      if (cssRule != null) {
 | 
			
		||||
        this.$content.css(cssRule);
 | 
			
		||||
      }
 | 
			
		||||
      return this;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      @method restore
 | 
			
		||||
      @private
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    NanoScroll.prototype.restore = function() {
 | 
			
		||||
      this.stopped = false;
 | 
			
		||||
      this.pane.show();
 | 
			
		||||
      this.addEvents();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      Resets nanoScroller's scrollbar.
 | 
			
		||||
      @method reset
 | 
			
		||||
      @chainable
 | 
			
		||||
      @example
 | 
			
		||||
          $(".nano").nanoScroller();
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    NanoScroll.prototype.reset = function() {
 | 
			
		||||
      var content, contentHeight, contentStyle, contentStyleOverflowY, paneBottom, paneHeight, paneOuterHeight, paneTop, sliderHeight;
 | 
			
		||||
      if (this.iOSNativeScrolling) {
 | 
			
		||||
        this.contentHeight = this.content.scrollHeight;
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      if (!this.$el.find("." + this.options.paneClass).length) {
 | 
			
		||||
        this.generate().stop();
 | 
			
		||||
      }
 | 
			
		||||
      if (this.stopped) {
 | 
			
		||||
        this.restore();
 | 
			
		||||
      }
 | 
			
		||||
      content = this.content;
 | 
			
		||||
      contentStyle = content.style;
 | 
			
		||||
      contentStyleOverflowY = contentStyle.overflowY;
 | 
			
		||||
      if (BROWSER_IS_IE7) {
 | 
			
		||||
        this.$content.css({
 | 
			
		||||
          height: this.$content.height()
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
      contentHeight = content.scrollHeight + BROWSER_SCROLLBAR_WIDTH;
 | 
			
		||||
      paneHeight = this.pane.outerHeight();
 | 
			
		||||
      paneTop = parseInt(this.pane.css('top'), 10);
 | 
			
		||||
      paneBottom = parseInt(this.pane.css('bottom'), 10);
 | 
			
		||||
      paneOuterHeight = paneHeight + paneTop + paneBottom;
 | 
			
		||||
      sliderHeight = Math.round(paneOuterHeight / contentHeight * paneOuterHeight);
 | 
			
		||||
      if (sliderHeight < this.options.sliderMinHeight) {
 | 
			
		||||
        sliderHeight = this.options.sliderMinHeight;
 | 
			
		||||
      } else if ((this.options.sliderMaxHeight != null) && sliderHeight > this.options.sliderMaxHeight) {
 | 
			
		||||
        sliderHeight = this.options.sliderMaxHeight;
 | 
			
		||||
      }
 | 
			
		||||
      if (contentStyleOverflowY === SCROLL && contentStyle.overflowX !== SCROLL) {
 | 
			
		||||
        sliderHeight += BROWSER_SCROLLBAR_WIDTH;
 | 
			
		||||
      }
 | 
			
		||||
      this.maxSliderTop = paneOuterHeight - sliderHeight;
 | 
			
		||||
      this.contentHeight = contentHeight;
 | 
			
		||||
      this.paneHeight = paneHeight;
 | 
			
		||||
      this.paneOuterHeight = paneOuterHeight;
 | 
			
		||||
      this.sliderHeight = sliderHeight;
 | 
			
		||||
      this.slider.height(sliderHeight);
 | 
			
		||||
      this.events.scroll();
 | 
			
		||||
      this.pane.show();
 | 
			
		||||
      this.isActive = true;
 | 
			
		||||
      if ((content.scrollHeight === content.clientHeight) || (this.pane.outerHeight(true) >= content.scrollHeight && contentStyleOverflowY !== SCROLL)) {
 | 
			
		||||
        this.pane.hide();
 | 
			
		||||
        this.isActive = false;
 | 
			
		||||
      } else if (this.el.clientHeight === content.scrollHeight && contentStyleOverflowY === SCROLL) {
 | 
			
		||||
        this.slider.hide();
 | 
			
		||||
      } else {
 | 
			
		||||
        this.slider.show();
 | 
			
		||||
      }
 | 
			
		||||
      this.pane.css({
 | 
			
		||||
        opacity: (this.options.alwaysVisible ? 1 : ''),
 | 
			
		||||
        visibility: (this.options.alwaysVisible ? 'visible' : '')
 | 
			
		||||
      });
 | 
			
		||||
      return this;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      @method scroll
 | 
			
		||||
      @private
 | 
			
		||||
      @example
 | 
			
		||||
          $(".nano").nanoScroller({ scroll: 'top' });
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    NanoScroll.prototype.scroll = function() {
 | 
			
		||||
      if (!this.isActive) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      this.sliderY = Math.max(0, this.sliderY);
 | 
			
		||||
      this.sliderY = Math.min(this.maxSliderTop, this.sliderY);
 | 
			
		||||
      this.$content.scrollTop((this.paneHeight - this.contentHeight + BROWSER_SCROLLBAR_WIDTH) * this.sliderY / this.maxSliderTop * -1);
 | 
			
		||||
      if (!this.iOSNativeScrolling) {
 | 
			
		||||
        this.slider.css({
 | 
			
		||||
          top: this.sliderY
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
      return this;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      Scroll at the bottom with an offset value
 | 
			
		||||
      @method scrollBottom
 | 
			
		||||
      @param offsetY {Number}
 | 
			
		||||
      @chainable
 | 
			
		||||
      @example
 | 
			
		||||
          $(".nano").nanoScroller({ scrollBottom: value });
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    NanoScroll.prototype.scrollBottom = function(offsetY) {
 | 
			
		||||
      if (!this.isActive) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.$content.scrollTop(this.contentHeight - this.$content.height() - offsetY).trigger(MOUSEWHEEL);
 | 
			
		||||
      return this;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      Scroll at the top with an offset value
 | 
			
		||||
      @method scrollTop
 | 
			
		||||
      @param offsetY {Number}
 | 
			
		||||
      @chainable
 | 
			
		||||
      @example
 | 
			
		||||
          $(".nano").nanoScroller({ scrollTop: value });
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    NanoScroll.prototype.scrollTop = function(offsetY) {
 | 
			
		||||
      if (!this.isActive) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.$content.scrollTop(+offsetY).trigger(MOUSEWHEEL);
 | 
			
		||||
      return this;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      Scroll to an element
 | 
			
		||||
      @method scrollTo
 | 
			
		||||
      @param node {Node} A node to scroll to.
 | 
			
		||||
      @chainable
 | 
			
		||||
      @example
 | 
			
		||||
          $(".nano").nanoScroller({ scrollTo: $('#a_node') });
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    NanoScroll.prototype.scrollTo = function(node) {
 | 
			
		||||
      if (!this.isActive) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.scrollTop($(node).get(0).offsetTop);
 | 
			
		||||
      return this;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      To stop the operation.
 | 
			
		||||
      This option will tell the plugin to disable all event bindings and hide the gadget scrollbar from the UI.
 | 
			
		||||
      @method stop
 | 
			
		||||
      @chainable
 | 
			
		||||
      @example
 | 
			
		||||
          $(".nano").nanoScroller({ stop: true });
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    NanoScroll.prototype.stop = function() {
 | 
			
		||||
      this.stopped = true;
 | 
			
		||||
      this.removeEvents();
 | 
			
		||||
      this.pane.hide();
 | 
			
		||||
      return this;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
      To flash the scrollbar gadget for an amount of time defined in plugin settings (defaults to 1,5s).
 | 
			
		||||
      Useful if you want to show the user (e.g. on pageload) that there is more content waiting for him.
 | 
			
		||||
      @method flash
 | 
			
		||||
      @chainable
 | 
			
		||||
      @example
 | 
			
		||||
          $(".nano").nanoScroller({ flash: true });
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    NanoScroll.prototype.flash = function() {
 | 
			
		||||
      var _this = this;
 | 
			
		||||
      if (!this.isActive) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.pane.addClass('flashed');
 | 
			
		||||
      setTimeout(function() {
 | 
			
		||||
        _this.pane.removeClass('flashed');
 | 
			
		||||
      }, this.options.flashDelay);
 | 
			
		||||
      return this;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return NanoScroll;
 | 
			
		||||
 | 
			
		||||
  })();
 | 
			
		||||
  $.fn.nanoScroller = function(settings) {
 | 
			
		||||
    return this.each(function() {
 | 
			
		||||
      var options, scrollbar;
 | 
			
		||||
      if (!(scrollbar = this.nanoscroller)) {
 | 
			
		||||
        options = $.extend({}, defaults, settings);
 | 
			
		||||
        this.nanoscroller = scrollbar = new NanoScroll(this, options);
 | 
			
		||||
      }
 | 
			
		||||
      if (settings && typeof settings === "object") {
 | 
			
		||||
        $.extend(scrollbar.options, settings);
 | 
			
		||||
        if (settings.scrollBottom) {
 | 
			
		||||
          return scrollbar.scrollBottom(settings.scrollBottom);
 | 
			
		||||
        }
 | 
			
		||||
        if (settings.scrollTop) {
 | 
			
		||||
          return scrollbar.scrollTop(settings.scrollTop);
 | 
			
		||||
        }
 | 
			
		||||
        if (settings.scrollTo) {
 | 
			
		||||
          return scrollbar.scrollTo(settings.scrollTo);
 | 
			
		||||
        }
 | 
			
		||||
        if (settings.scroll === 'bottom') {
 | 
			
		||||
          return scrollbar.scrollBottom(0);
 | 
			
		||||
        }
 | 
			
		||||
        if (settings.scroll === 'top') {
 | 
			
		||||
          return scrollbar.scrollTop(0);
 | 
			
		||||
        }
 | 
			
		||||
        if (settings.scroll && settings.scroll instanceof $) {
 | 
			
		||||
          return scrollbar.scrollTo(settings.scroll);
 | 
			
		||||
        }
 | 
			
		||||
        if (settings.stop) {
 | 
			
		||||
          return scrollbar.stop();
 | 
			
		||||
        }
 | 
			
		||||
        if (settings.flash) {
 | 
			
		||||
          return scrollbar.flash();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return scrollbar.reset();
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
})(jQuery, window, document);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
$(document).ready(function() {  
 | 
			
		||||
  $(".select_user_modal").on('click', function(){
 | 
			
		||||
    var ids = [];
 | 
			
		||||
    var users = $(this).siblings('#selected_users').children('span.selected_user');
 | 
			
		||||
    users.each(function(i) {
 | 
			
		||||
      ids.push(users.eq(i).attr('user_id'));
 | 
			
		||||
    });
 | 
			
		||||
    $("#main-wrap").after("<span id='select_user'></span>");
 | 
			
		||||
    $.ajax({
 | 
			
		||||
      type: 'GET',
 | 
			
		||||
      url: $(this).attr("rel"),
 | 
			
		||||
      dataType: 'script',
 | 
			
		||||
      data: {field: $(this).attr("field"), ids: ids},
 | 
			
		||||
      success: function (msg) {
 | 
			
		||||
        $("#select_user_modal").modal('show'); },
 | 
			
		||||
      error: function(){
 | 
			
		||||
        alert("ERROR");
 | 
			
		||||
      }
 | 
			
		||||
    });  
 | 
			
		||||
    return false;
 | 
			
		||||
  });
 | 
			
		||||
  $(document).on('click', ".remove_user", function(){
 | 
			
		||||
    $(this).parent().remove();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -9,7 +9,7 @@ function load_tinymce() {
 | 
			
		|||
    // Theme options
 | 
			
		||||
    theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,formatselect,fontselect,fontsizeselect",
 | 
			
		||||
    theme_advanced_buttons2 : "cut,copy,paste,pastetext,pasteword,|,bullist,numlist,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,forecolor,backcolor",
 | 
			
		||||
    theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,fullscreen",
 | 
			
		||||
    theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,fullscreen,|,template",
 | 
			
		||||
    theme_advanced_toolbar_location : "top",
 | 
			
		||||
    theme_advanced_toolbar_align : "left",
 | 
			
		||||
    theme_advanced_statusbar_location : "bottom",
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ function load_tinymce() {
 | 
			
		|||
    skin_variant : "silver",
 | 
			
		||||
    font_size_style_values : "xx-small,x-small,small,medium,large,x-large,xx-large",
 | 
			
		||||
    // Drop lists for link/image/media/template dialogs
 | 
			
		||||
    template_external_list_url : "js/template_list.js",
 | 
			
		||||
    template_external_list_url : "/tinymce/lists/template_list.js",
 | 
			
		||||
    // external_link_list_url : "js/link_list.js",
 | 
			
		||||
    // external_image_list_url : "js/image_list.js",
 | 
			
		||||
    // media_external_list_url : "js/media_list.js"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,230 @@
 | 
			
		|||
/* Member Filter */
 | 
			
		||||
#select_user #select_user_modal.modal {
 | 
			
		||||
  width: 80%;
 | 
			
		||||
  margin-left: -40%;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .modal-body {
 | 
			
		||||
  max-height: 425px;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .modal-body form {
 | 
			
		||||
  margin-bottom: 0px;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .modal-body form fieldset {
 | 
			
		||||
  min-height: 360px;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .modal-body .radio.inline,
 | 
			
		||||
#select_user #select_user_modal .modal-body .checkbox.inline {
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  padding-top: 5px;
 | 
			
		||||
  margin-bottom: 0;
 | 
			
		||||
  vertical-align: middle;
 | 
			
		||||
  min-width: 100px;
 | 
			
		||||
  margin-left: 0;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .modal-body .form-actions {
 | 
			
		||||
  margin: 20px 0 0;
 | 
			
		||||
  padding: 10px 0 0;
 | 
			
		||||
  background-color: transparent;
 | 
			
		||||
  text-align: right;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .modal-body .tabs-left > .nano {
 | 
			
		||||
  width: 160px;
 | 
			
		||||
  min-height: 425px;
 | 
			
		||||
  float: left;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .modal-body .tabs-left > .nano .pane {
 | 
			
		||||
  right: 6px;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .modal-body .tabs-left > .nano > .content > .nav-tabs {
 | 
			
		||||
  width: 140px;
 | 
			
		||||
  float: left;
 | 
			
		||||
  margin-bottom: 0;
 | 
			
		||||
  margin-right: 0;
 | 
			
		||||
  border-right: 1px solid #ddd;
 | 
			
		||||
  border-bottom: none;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .modal-body .tabs-left > .nano > .content > .nav-tabs > li {
 | 
			
		||||
  float: none;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .modal-body .tabs-left > .nano > .content > .nav-tabs > li > a {
 | 
			
		||||
  min-width: 74px;
 | 
			
		||||
  margin-right: 0;
 | 
			
		||||
  margin-bottom: 3px;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .modal-body .tabs-left > .nano > .content > .nav-tabs > li > a {
 | 
			
		||||
  margin-right: -1px;
 | 
			
		||||
  -webkit-border-radius: 4px 0 0 4px;
 | 
			
		||||
     -moz-border-radius: 4px 0 0 4px;
 | 
			
		||||
          border-radius: 4px 0 0 4px;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .modal-body .tabs-left > .nano > .content > .nav-tabs > li > a:hover {
 | 
			
		||||
  border-color: #eeeeee #dddddd #eeeeee #eeeeee;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .modal-body .tabs-left > .nano > .content > .nav-tabs .active > a,
 | 
			
		||||
#select_user #select_user_modal .modal-body .tabs-left > .nano > .content > .nav-tabs .active > a:hover {
 | 
			
		||||
  border-color: #ddd transparent #ddd #ddd;
 | 
			
		||||
  *border-right-color: #ffffff;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .member-filter-options {
 | 
			
		||||
  float: left;
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  width: 175px;
 | 
			
		||||
  min-height: 425px;
 | 
			
		||||
  margin-right: 10px;
 | 
			
		||||
  padding: 0 10px 0 0;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .member-filter-options select {
 | 
			
		||||
  width: 165px; 
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .member-filter-options .btn {
 | 
			
		||||
  display: block;
 | 
			
		||||
}
 | 
			
		||||
#select_user #select_user_modal .member-filter-result {
 | 
			
		||||
  padding-left: 15px;
 | 
			
		||||
  min-height: 360px;
 | 
			
		||||
  width: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Check Box Card */
 | 
			
		||||
.checkbox-card {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
}
 | 
			
		||||
.checkbox-card li {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  list-style: none;
 | 
			
		||||
  color: #FFFFFF;
 | 
			
		||||
  width: 180px;
 | 
			
		||||
  height: 40px;
 | 
			
		||||
  margin: 0 10px 10px 0;
 | 
			
		||||
  float: left;
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  background-color: #cccccc;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  -webkit-border-radius: 3px;
 | 
			
		||||
     -moz-border-radius: 3px;
 | 
			
		||||
      border-radius: 3px;
 | 
			
		||||
  -webkit-transition: all .2s linear;
 | 
			
		||||
     -moz-transition: all .2s linear;
 | 
			
		||||
     -o-transition: all .2s linear;
 | 
			
		||||
      transition: all .2s linear;
 | 
			
		||||
}
 | 
			
		||||
.checkbox-card li.mark {
 | 
			
		||||
  width: 0;
 | 
			
		||||
  height: 0;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
 | 
			
		||||
  filter: alpha(opacity=0);
 | 
			
		||||
  opacity: 0;
 | 
			
		||||
  visibility: hidden;
 | 
			
		||||
}
 | 
			
		||||
.checkbox-card li:hover {
 | 
			
		||||
  background-color: #0088cc;
 | 
			
		||||
}
 | 
			
		||||
.checkbox-card li:after {
 | 
			
		||||
  content: "";
 | 
			
		||||
  display: block;
 | 
			
		||||
  clear: both;
 | 
			
		||||
  height: 0;
 | 
			
		||||
  visibility: hidden;
 | 
			
		||||
}
 | 
			
		||||
.checkbox-card li.active:before {
 | 
			
		||||
  -webkit-text-size-adjust : none;
 | 
			
		||||
  font-family: FontAwesome;
 | 
			
		||||
  font-weight: normal;
 | 
			
		||||
  font-style: normal;
 | 
			
		||||
  color: #FFF;
 | 
			
		||||
  text-decoration: inherit;
 | 
			
		||||
  content: "\f00c";
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  right: 0px;
 | 
			
		||||
  top: 0px;
 | 
			
		||||
  line-height: 14px;
 | 
			
		||||
  text-indent: 10px;
 | 
			
		||||
  font-size: 10px;
 | 
			
		||||
  width: 0px;
 | 
			
		||||
  height: 0px;
 | 
			
		||||
  border-style: solid;
 | 
			
		||||
  border-width: 0 22px 22px 0;
 | 
			
		||||
  border-color: transparent #51a351 transparent transparent;
 | 
			
		||||
}
 | 
			
		||||
.checkbox-card li.active label {
 | 
			
		||||
}
 | 
			
		||||
.checkbox-card li label {
 | 
			
		||||
  margin-bottom: 0px;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  -webkit-border-radius: 3px;
 | 
			
		||||
     -moz-border-radius: 3px;
 | 
			
		||||
      border-radius: 3px;
 | 
			
		||||
}
 | 
			
		||||
.checkbox-card li input {
 | 
			
		||||
  opacity: 0;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 0;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  z-index: 10;
 | 
			
		||||
}
 | 
			
		||||
.checkbox-card li label span {
 | 
			
		||||
  -webkit-text-size-adjust : none;
 | 
			
		||||
  font-size: 10px;
 | 
			
		||||
  display: block;
 | 
			
		||||
  width: 130px;
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
  color: #666666;
 | 
			
		||||
  margin-top: -3px;
 | 
			
		||||
}
 | 
			
		||||
.checkbox-card li:hover label span,
 | 
			
		||||
.checkbox-card li:hover label span.user-name {
 | 
			
		||||
  color: #FFFFFF;
 | 
			
		||||
}
 | 
			
		||||
.checkbox-card li label span.user-name {
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  color: #363636;
 | 
			
		||||
  padding: 2px 0 0;
 | 
			
		||||
  margin-top: 0;
 | 
			
		||||
}
 | 
			
		||||
.checkbox-card li .user-pic {
 | 
			
		||||
  float: left;
 | 
			
		||||
  margin-right: 5px;
 | 
			
		||||
  width: 40px;
 | 
			
		||||
  height: 40px;
 | 
			
		||||
}
 | 
			
		||||
#selected_users .selected_user {
 | 
			
		||||
  display: block;
 | 
			
		||||
  margin-bottom: 5px;
 | 
			
		||||
}
 | 
			
		||||
#selected_users .selected_user .remove_user {
 | 
			
		||||
  font-size: 15px;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
.promoter {
 | 
			
		||||
  border-color: #CCCCCC;
 | 
			
		||||
  border-style: solid;
 | 
			
		||||
  border-width: 0 1px;
 | 
			
		||||
  padding: 0 10px 5px 10px;
 | 
			
		||||
}
 | 
			
		||||
.promoter > div {
 | 
			
		||||
  border-bottom: 1px solid #CCCCCC;
 | 
			
		||||
}
 | 
			
		||||
.promoter > div:after {
 | 
			
		||||
  content: "";
 | 
			
		||||
  clear: both;
 | 
			
		||||
  display: block;
 | 
			
		||||
  visibility: hidden;
 | 
			
		||||
}
 | 
			
		||||
.promoter > div > span {
 | 
			
		||||
  display: block;
 | 
			
		||||
  margin-left: 70px;
 | 
			
		||||
  padding-bottom: 5px;
 | 
			
		||||
}
 | 
			
		||||
.promoter p {
 | 
			
		||||
  width: 70px;
 | 
			
		||||
  float: left;
 | 
			
		||||
  text-align:right;
 | 
			
		||||
}*/
 | 
			
		||||
| 
						 | 
				
			
			@ -55,9 +55,9 @@
 | 
			
		|||
	width:100%;
 | 
			
		||||
}
 | 
			
		||||
#orbit-bar .orbit-logo .brand {
 | 
			
		||||
	background:url(<%= asset_path 'orbit-bar.png' %>) no-repeat -162px -5px;
 | 
			
		||||
	text-indent:-9999px;
 | 
			
		||||
	padding:5px 20px 4px;
 | 
			
		||||
	background: url(<%= asset_path 'ga-logo.png' %>) no-repeat center center;
 | 
			
		||||
	text-indent: -9999px;
 | 
			
		||||
	padding: 5px 20px 4px;
 | 
			
		||||
}
 | 
			
		||||
#orbit-bar .orbit-logo .brand:hover {
 | 
			
		||||
	background-color:#009ddc;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
/*style*/
 | 
			
		||||
 | 
			
		||||
* {
 | 
			
		||||
	outline: none;
 | 
			
		||||
}
 | 
			
		||||
@font-face{ 
 | 
			
		||||
	font-family: 'WebSymbolsRegular';
 | 
			
		||||
	src: url(<%= asset_path 'websymbols-regular-webfont.eot' %>);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -70,4 +70,30 @@ class Admin::MemberSelectsController < OrbitBackendController
 | 
			
		|||
	
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def select_members
 | 
			
		||||
    selected_users = User.find(params[:ids]) rescue []
 | 
			
		||||
    @field = params[:field]
 | 
			
		||||
    roles = Role.all
 | 
			
		||||
    @sorted_users = roles.inject({}) do |users, role|
 | 
			
		||||
      users[role] = role.users.where(:email.not => /guest|rulingcom/) - selected_users
 | 
			
		||||
      users
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_roles
 | 
			
		||||
    roles = Role.find(params[:role_ids]) rescue []
 | 
			
		||||
    @field = params[:field]
 | 
			
		||||
    @users = roles.inject([]) do |users, role|
 | 
			
		||||
      users += role.users.where(:email.not => /guest|rulingcom/).entries
 | 
			
		||||
      users
 | 
			
		||||
    end
 | 
			
		||||
    render 'admin/member_selects/update_selected_users'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_users
 | 
			
		||||
    @users = User.find(params[:user_ids]) rescue []
 | 
			
		||||
    @field = params[:field]
 | 
			
		||||
    render 'admin/member_selects/update_selected_users'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
class SamlLoginsController < ApplicationController
 | 
			
		||||
 | 
			
		||||
  require "net/http"
 | 
			
		||||
  require "uri"
 | 
			
		||||
  require 'rexml/document'
 | 
			
		||||
  include REXML
 | 
			
		||||
 | 
			
		||||
  def index 
 | 
			
		||||
  
 | 
			
		||||
    if params[:wa] == "wsignoutcleanup1.0" #logout
 | 
			
		||||
 | 
			
		||||
      redirect_to :root
 | 
			
		||||
 | 
			
		||||
    else  #login
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @wresult = params[:wresult]
 | 
			
		||||
    @wctx = params[:wctx]
 | 
			
		||||
 | 
			
		||||
    @main_url = LIST[:sites][@wctx]['url']
 | 
			
		||||
    @main_public_key = LIST[:sites][@wctx]['key']
 | 
			
		||||
 | 
			
		||||
    @doc = REXML::Document.new @wresult
 | 
			
		||||
 | 
			
		||||
    @main_public_key = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzKawlFWAMzA/uV/kcewd\nmtj8PcqxosmnSh7ZzJ0DumG2ieeP9oDBicqbqIEaeJVvrRzYJD2a+u8x5KKMKB8J\nHbMUpCBFlIpkDMjU/oZVMcYT9pcH51QWNvCgHG7prVykSGFz1JRvjSP6cwuZKBFd\nFFneOViETqoMIO1DbRLXsGfPvMOJY9C1xDwv1dLv0Wbj7M9N6eNz06a50bu3I4gl\nMumxWnZUabXL3G62S/Si4NM7J2jOUnkEOxJWOhcAX/iiqS9T8AHu84um2+mLQpfB\nJJFFIWCIAtU78VnIN5JSWwjFU5TsiSyCFYpGXKxUFD25cFmt3SfG0gwmrFis5Pdn\nhwIDAQAB\n-----END PUBLIC KEY-----\n"
 | 
			
		||||
    
 | 
			
		||||
    public_key = OpenSSL::PKey::RSA.new(@main_public_key)
 | 
			
		||||
    encrypted_data = public_key.public_encrypt(@doc.elements["//saml:AttributeValue"].text)
 | 
			
		||||
    
 | 
			
		||||
    redirect_to "http://#{@main_url}/user_login?" + { :wresult => encrypted_data }.to_param
 | 
			
		||||
 | 
			
		||||
   end
 | 
			
		||||
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
# encoding: utf-8
 | 
			
		||||
 | 
			
		||||
class SessionsController < Devise::SessionsController
 | 
			
		||||
	prepend_before_filter :require_no_authentication, :only => [ :new, :create ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  def create 
 | 
			
		||||
	  @site = Site.first
 | 
			
		||||
 | 
			
		||||
      private_key = OpenSSL::PKey::RSA.new(@site.private_key)
 | 
			
		||||
      wresult = private_key.private_decrypt(request.params['wresult'])
 | 
			
		||||
 | 
			
		||||
  	  @ids = wresult.split("@")
 | 
			
		||||
 | 
			
		||||
      login_uid = @ids[0]
 | 
			
		||||
 | 
			
		||||
  	  resource = User.first(conditions:{user_id: login_uid})
 | 
			
		||||
 | 
			
		||||
	  if !resource.blank?
 | 
			
		||||
	     resource_name = resource.class.to_s.downcase
 | 
			
		||||
	     sign_in(resource_name, resource)
 | 
			
		||||
	     session[:user_id_type] = "myntu"
 | 
			
		||||
	     redirect_to after_sign_in_path_for(resource)
 | 
			
		||||
	  else
 | 
			
		||||
	     flash[:error] = "很抱歉,您無此權限或帳號登入本站,請洽本站管理員<br />Sorry, you don't have the account or authority to login. Please contact the website administrator."
 | 
			
		||||
	     redirect_to :root
 | 
			
		||||
	  end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def destroy
 | 
			
		||||
  	@user_id_type = session[:user_id_type]
 | 
			
		||||
    sign_out
 | 
			
		||||
    if @user_id_type == "myntu"
 | 
			
		||||
      redirect_to "https://adfs.ntu.edu.tw/adfs/ls/?wa=wsignout1.0&wreply=https://galogin.ntu.edu.tw"
 | 
			
		||||
    else
 | 
			
		||||
      redirect_to root_path
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -303,7 +303,7 @@ module ApplicationHelper
 | 
			
		|||
 | 
			
		||||
  # NTU link
 | 
			
		||||
  def get_link(site_number)
 | 
			
		||||
    "http://#{request.host}:2#{site_number}00"
 | 
			
		||||
    "http://#{site_number}.#{request.domain(3)}"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def sortable(column, title = nil, options = {})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
class GetAnnouncementFromRss 
 | 
			
		||||
  @queue = :high
 | 
			
		||||
 | 
			
		||||
  def self.perform()
 | 
			
		||||
    %x(ruby "#{Rails.root}/lib/rss_ntu_job.rb")
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +10,7 @@ class Role < Attribute
 | 
			
		|||
  field :title, localize: true
 | 
			
		||||
  
 | 
			
		||||
  has_many :sub_roles, :autosave => true, :dependent => :destroy
 | 
			
		||||
  has_many :users
 | 
			
		||||
  has_and_belongs_to_many :users
 | 
			
		||||
  # has_many :statuses, :autosave => true, :dependent => :destroy
 | 
			
		||||
  # has_many :attribute_fields, :autosave => true, :dependent => :destroy
 | 
			
		||||
  has_many :role_statuses, :autosave => true, :dependent => :destroy
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,86 @@
 | 
			
		|||
<div id="select_user_modal" class="modal hide fade">
 | 
			
		||||
  <div class="modal-header">
 | 
			
		||||
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
 | 
			
		||||
    <h3><%= t('list.user') %></h3>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="modal-body">
 | 
			
		||||
    <div class="tabbable tabs-left">
 | 
			
		||||
      <div class="nano">
 | 
			
		||||
        <div class="content">
 | 
			
		||||
          <ul class="nav nav-tabs">
 | 
			
		||||
            <li class="active"><a href="#all" data-toggle="tab"><%= t('list.role') %></a></li>
 | 
			
		||||
            <% @sorted_users.each_key do |role| %>
 | 
			
		||||
              <li class=""><a href="#r_<%= role.id %>" data-toggle="tab"><%= role.title %></a></li>
 | 
			
		||||
            <% end %>
 | 
			
		||||
          </ul>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="tab-content">
 | 
			
		||||
        <div class="tab-pane fade in active" id="all">
 | 
			
		||||
          <%= form_tag set_roles_admin_member_selects_path(field: @field), remote: true do %>
 | 
			
		||||
            <fieldset>
 | 
			
		||||
              <% @sorted_users.each_key do |role| %>
 | 
			
		||||
                <label class="checkbox inline">
 | 
			
		||||
                  <%= check_box_tag 'role_ids[]', role.id , false %> <%= role.title %>
 | 
			
		||||
                </label>
 | 
			
		||||
              <% end %>
 | 
			
		||||
            </fieldset>
 | 
			
		||||
            <div class="form-actions">
 | 
			
		||||
              <button type="button" class="btn" data-dismiss="modal"><%= t(:cancel) %></button>
 | 
			
		||||
              <%= submit_tag t(:submit), class: "btn btn-primary" %>
 | 
			
		||||
            </div>
 | 
			
		||||
          <% end %>
 | 
			
		||||
        </div>
 | 
			
		||||
        <% @sorted_users.each do |role, users| %>
 | 
			
		||||
          <div class="tab-pane fade" id="r_<%= role.id %>">
 | 
			
		||||
            <%= form_tag set_users_admin_member_selects_path(field: @field), remote: true do %>
 | 
			
		||||
              <fieldset class="clearfix">
 | 
			
		||||
                <div class="member-filter-result nano">
 | 
			
		||||
                  <div class="content">
 | 
			
		||||
                    <ul class="checkbox-card clearfix">
 | 
			
		||||
                      <% users.each do |user| %>
 | 
			
		||||
                        <li>
 | 
			
		||||
                          <label>
 | 
			
		||||
                            <%= image_tag (user.avatar.file ? user.avatar : "menber-pic.png"), class: "user-pic" %>
 | 
			
		||||
                            <span class="user-name"><%= user.name %></span>
 | 
			
		||||
                          </label>
 | 
			
		||||
                          <%= check_box_tag 'user_ids[]', user.id , false %>
 | 
			
		||||
                        </li>
 | 
			
		||||
                      <% end %>
 | 
			
		||||
                    </ul>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="form-actions condition">
 | 
			
		||||
                  <button type="button" class="btn" data-dismiss="modal"><%= t(:cancel) %></button>
 | 
			
		||||
                  <%= submit_tag t(:submit), class: "btn btn-primary" %>
 | 
			
		||||
                </div>
 | 
			
		||||
              </fieldset>
 | 
			
		||||
            <% end %>
 | 
			
		||||
          </div>
 | 
			
		||||
        <% end %>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
  $(document).ready(function() {
 | 
			
		||||
    $(".modal").on("hidden", function () {
 | 
			
		||||
      $("#select_user").remove();
 | 
			
		||||
      $('#select_user_modal').on('shown', function() {
 | 
			
		||||
        $(this).find('.nano').nanoScroller({ scrollTop: 0, iOSNativeScrolling: true });
 | 
			
		||||
        $(this).find('.checkbox-card > li').cardCheck({
 | 
			
		||||
          check: $(this).find('.checkbox-card > li input[type="checkbox"]'),
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
    $('#select_user_modal').on('shown', function() {
 | 
			
		||||
      $('#select_user_modal').off('shown')
 | 
			
		||||
      $(this).find('.nano').nanoScroller({ scrollTop: 0, iOSNativeScrolling: true });
 | 
			
		||||
      $(this).find('.checkbox-card > li').cardCheck({
 | 
			
		||||
        check: $(this).find('.checkbox-card > li input[type="checkbox"]'),
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
<% unless users.blank? %>
 | 
			
		||||
  <div class="promoter-block">
 | 
			
		||||
    <p class="promoter-title"><%= t(:promoter) %>:</p>
 | 
			
		||||
    <ul>
 | 
			
		||||
      <% users.each do |user| %>
 | 
			
		||||
        <li class="promoter">
 | 
			
		||||
          <p>
 | 
			
		||||
              <%= link_to user.name, "mailto:#{user.email}", class: "promoter-name" %> / <span class="promoter-phone"><%= user.office_tel %></span>
 | 
			
		||||
          </p>
 | 
			
		||||
        </li>
 | 
			
		||||
      <% end %>
 | 
			
		||||
    </ul>
 | 
			
		||||
  </div>
 | 
			
		||||
<% end %>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
<% content_for :page_specific_javascript do -%>
 | 
			
		||||
  <%= javascript_include_tag "member-selection" %>
 | 
			
		||||
  <%= javascript_include_tag "lib/jquery.nanoscroller" %>
 | 
			
		||||
  <%= javascript_include_tag "lib/checkbox.card" %>
 | 
			
		||||
<% end -%>
 | 
			
		||||
<% content_for :page_specific_css do -%>
 | 
			
		||||
  <%= stylesheet_link_tag "member_select" %>
 | 
			
		||||
<% end %>
 | 
			
		||||
 | 
			
		||||
<div>
 | 
			
		||||
  <div id="selected_users">
 | 
			
		||||
    <%= render partial: 'admin/member_selects/user', collection: users, locals: {field: field} %>
 | 
			
		||||
    <%= hidden_field_tag field %>
 | 
			
		||||
  </div>
 | 
			
		||||
  <%= link_to t(:add), '#', class: 'btn btn-primary btn-small select_user_modal', rel: select_members_admin_member_selects_path, field: field %>
 | 
			
		||||
</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
<span class="alert alert-info selected_user" user_id="<%= user.id %>">
 | 
			
		||||
  <%= user.name %>
 | 
			
		||||
  <%= hidden_field_tag field, user.id %>
 | 
			
		||||
  <%= content_tag :span, '×', class: 'close remove_user' %>
 | 
			
		||||
</span>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
$("#select_user").html("<%= j render partial: 'admin/member_selects/modal_select', locals: {field: 'bulletin[user_ids][]'} %>");
 | 
			
		||||
$("#select_user_modal").modal();
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
$("#selected_users").append("<%= j render partial: 'user', collection: @users, locals: {field: @field} %>");
 | 
			
		||||
$("#select_user_modal").modal('hide');
 | 
			
		||||
| 
						 | 
				
			
			@ -17,4 +17,4 @@
 | 
			
		|||
        <%= render :partial=> "widget_ext_options" %>  
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <% end %>
 | 
			
		||||
    <% end %>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,15 +9,20 @@
 | 
			
		|||
		    <%= content_tag :span, msg, :class => [key, "notice label label-warning"] %>
 | 
			
		||||
		  <% end %>
 | 
			
		||||
			<p class="alert hide">You need to sign in or sign up before continuing.</p>
 | 
			
		||||
			<% @request_hosts = request.host_with_port.split(".") %>
 | 
			
		||||
			<a href="https://adfs.ntu.edu.tw/adfs/ls/?wa=wsignin1.0&wtrealm=https://galogin.ntu.edu.tw/saml_login&wctx=<%= @request_hosts[0] %>" class="btn btn-primary" style="width: 310px;margin-top: 10px;">使用計中帳號登入</a>
 | 
			
		||||
			<p style="margin: 40px 0 20px; position: relative; border-bottom: 1px solid #DDD;">
 | 
			
		||||
				<span style="position: absolute; width: 140px; left: 50%; margin-left: -70px; font-size: 14px; top: -9px; background-color: #fff; text-align: center;">或使用本站帳號登入</span>
 | 
			
		||||
			</p>
 | 
			
		||||
			<div class="main">
 | 
			
		||||
				<div class="control-group clear">
 | 
			
		||||
					<%= f.label :user_id ,t("users.user_id")%>
 | 
			
		||||
					<%= f.text_field :user_id, :placeholder => t("users.user_id"), :style => "width: 330px;" %>
 | 
			
		||||
					<%= f.text_field :user_id, :placeholder => t("users.user_id"), :style => "width: 326px;" %>
 | 
			
		||||
					<span class="help-inline">Please correct the error</span>
 | 
			
		||||
				</div>
 | 
			
		||||
				<div class="control-group clear">
 | 
			
		||||
					<%= f.label :password,t("password") %>
 | 
			
		||||
					<%= f.password_field :password, :placeholder => t(:dots), :style => "width: 330px;" %>
 | 
			
		||||
					<%= f.password_field :password, :placeholder => t(:dots), :style => "width: 326px;" %>
 | 
			
		||||
					<span class="help-inline">Please correct the error</span>
 | 
			
		||||
					<%= link_to t(:forgot_password), new_user_password_path, :class => 'pull-right forgot hide' %>
 | 
			
		||||
				</div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,19 +10,10 @@
 | 
			
		|||
    </div>
 | 
			
		||||
    <ul class="nav">
 | 
			
		||||
      <li><a href="<%= root_path %>" data-icons=""></a></li>
 | 
			
		||||
      <li><a href="<%= desktop_path %>" data-icons=""></a></li>
 | 
			
		||||
      <!-- <li><a href="<%#= desktop_path %>" data-icons=""></a></li> -->
 | 
			
		||||
    </ul>
 | 
			
		||||
    <ul class="nav pull-right">
 | 
			
		||||
      <!--
 | 
			
		||||
      <li class="dropdown">
 | 
			
		||||
          <a class="dropdown-toggle" data-icons="" href="#" data-toggle="dropdown"></a>
 | 
			
		||||
          <ul class="dropdown-menu">
 | 
			
		||||
            <% #t('ntu.site_names').each do |site| %>
 | 
			
		||||
              <li><%#= link_to site[1], get_link(site[0]) %></li>
 | 
			
		||||
            <%# end %>
 | 
			
		||||
          </ul>
 | 
			
		||||
      </li>
 | 
			
		||||
      -->
 | 
			
		||||
      
 | 
			
		||||
      <li class="search clear" title="<%= t :search_google %>">
 | 
			
		||||
      <a class="orbit-bar-search" href="#" data-icons=""></a>
 | 
			
		||||
      <form class="navbar-search" method="get" action="http://www.google.com/custom">
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +25,17 @@
 | 
			
		|||
        <input type='hidden' name='sitesearch' value='<%= @site.search["sitesearch"] rescue '' %>'>
 | 
			
		||||
        <%= text_field_tag 'q','',{:class => "search-query span3",:placeholder=> t(:search_google) ,:disabled=> ((@site.search["sitesearch"] || @site.search["domains"] ).blank? rescue true)}%>
 | 
			
		||||
      </form>
 | 
			
		||||
 | 
			
		||||
      <li class="dropdown language">
 | 
			
		||||
          <a class="dropdown-toggle orbit-bar-language" data-icons="" href="#" data-toggle="dropdown"></a>
 | 
			
		||||
          <ul class="dropdown-menu language-menu">
 | 
			
		||||
            <% t('ntu.site_names').each do |site| %>
 | 
			
		||||
              <li><%= link_to site[1], get_link(site[0]) %></li>
 | 
			
		||||
            <% end %>
 | 
			
		||||
          </ul>
 | 
			
		||||
      </li>
 | 
			
		||||
      
 | 
			
		||||
 | 
			
		||||
      </li>
 | 
			
		||||
      <li class="dropdown language">
 | 
			
		||||
        <a class="dropdown-toggle orbit-bar-language" href="#" data-toggle="dropdown" data-icons=""></a>
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +55,7 @@
 | 
			
		|||
        <ul class="dropdown-menu account-menu">
 | 
			
		||||
          <!-- <li><%= link_to content_tag(:i, nil, :class => 'icons-tools') + ' ' +  t(:account_setting), desktop_path+"#settings-account" %></li> -->
 | 
			
		||||
          <!-- <li><%= link_to content_tag(:i, nil, :class => 'icons-screen') + ' ' +  t(:desktop), desktop_path %></li> -->
 | 
			
		||||
          <li><%= link_to content_tag(:i, nil, :class => 'icons-logout') + ' ' +  t(:logout), destroy_user_session_path %></li>
 | 
			
		||||
          <li><%= link_to content_tag(:i, nil, :class => 'icons-logout') + ' ' +  t(:logout), user_logout_path %></li>
 | 
			
		||||
          <li class="divider"></li>
 | 
			
		||||
          <li>
 | 
			
		||||
          <a href="#">
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +70,13 @@
 | 
			
		|||
        <a class="dropdown-toggle orbit-bar-member" href="#" data-icons=""></a>
 | 
			
		||||
        <div class="dropdown-menu">
 | 
			
		||||
          <ul class="log">
 | 
			
		||||
            <li class="title hide"></li>
 | 
			
		||||
            <li style="margin-top: 30px;">
 | 
			
		||||
              <% @request_hosts = request.host_with_port.split(".") %>
 | 
			
		||||
              <a class="btn btn-primary" href="https://adfs.ntu.edu.tw/adfs/ls/?wa=wsignin1.0&wtrealm=https://galogin.ntu.edu.tw/saml_login&wctx=<%= @request_hosts[0] %>" style="padding: 3px 0;color: #fff;">使用計中帳號登入</a>
 | 
			
		||||
            </li>
 | 
			
		||||
            <li class="divider" style="margin: 40px 0 0;">
 | 
			
		||||
              <span style="width: 140px;left: 50%;margin-left: -70px;font-size: 14px;">或使用本站帳號登入</span>
 | 
			
		||||
            </li>
 | 
			
		||||
 | 
			
		||||
            <%= form_for :user, :url => user_session_path do |f| %>
 | 
			
		||||
              <li>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
<head>
 | 
			
		||||
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 | 
			
		||||
  <title><%= @title || APP_CONFIG['orbit'] %></title>
 | 
			
		||||
  <link rel="shortcut icon" href="<%= asset_path "ncculogo.ico" %>">
 | 
			
		||||
  <link rel="shortcut icon" href="<%= asset_path "favicon.ico" %>">
 | 
			
		||||
  <%= yield :page_specific_link %>
 | 
			
		||||
  <%= stylesheet_link_tag "new_admin" %>
 | 
			
		||||
  <%= javascript_include_tag "new_admin" %>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
<head>
 | 
			
		||||
<meta charset="utf-8">
 | 
			
		||||
	<title><%= @title || APP_CONFIG['orbit'] %></title>
 | 
			
		||||
	<link rel="shortcut icon" href="<%= asset_path "ncculogo.ico" %>">
 | 
			
		||||
	<link rel="shortcut icon" href="<%= asset_path "favicon.ico" %>">
 | 
			
		||||
	<!--[if lt IE 9]>
 | 
			
		||||
	   <%= javascript_include_tag "html5" %>
 | 
			
		||||
	<![endif]-->
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,22 @@
 | 
			
		|||
<!DOCTYPE HTML>
 | 
			
		||||
<html class="<%= I18n.locale.to_s %>">
 | 
			
		||||
<head>
 | 
			
		||||
  <script type="text/javascript">
 | 
			
		||||
  var _gaq = _gaq || [];
 | 
			
		||||
  _gaq.push(['_setAccount', 'UA-36964512-1']);
 | 
			
		||||
  _gaq.push(['_setDomainName', 'ga.ntu.edu.tw']);
 | 
			
		||||
  _gaq.push(['_setAllowLinker', true]);
 | 
			
		||||
  _gaq.push(['_trackPageview']);
 | 
			
		||||
 | 
			
		||||
  (function() {
 | 
			
		||||
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
 | 
			
		||||
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
 | 
			
		||||
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
 | 
			
		||||
  })();
 | 
			
		||||
</script>
 | 
			
		||||
<meta charset="utf-8">
 | 
			
		||||
	<%= page_title(@item).html_safe %>
 | 
			
		||||
	<link rel="shortcut icon" href="<%= asset_path "ncculogo.ico" %>">
 | 
			
		||||
	<link rel="shortcut icon" href="<%= asset_path "favicon.ico" %>">
 | 
			
		||||
	<%= page_metas(@item).html_safe %>
 | 
			
		||||
	<!--[if lt IE 9]>
 | 
			
		||||
	   <%= javascript_include_tag "html5" %>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
<head>
 | 
			
		||||
<meta charset="utf-8">
 | 
			
		||||
  <%= page_title(@item).html_safe %>
 | 
			
		||||
  <link rel="shortcut icon" href="<%= asset_path "ncculogo.ico" %>">
 | 
			
		||||
  <link rel="shortcut icon" href="<%= asset_path "favicon.ico" %>">
 | 
			
		||||
  <%= page_metas(@item).html_safe %>
 | 
			
		||||
  <!--[if lt IE 9]>
 | 
			
		||||
     <%= javascript_include_tag "html5" %>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,9 +3,7 @@
 | 
			
		|||
<% end %>
 | 
			
		||||
 | 
			
		||||
<ul>
 | 
			
		||||
  <li>總機電話:<a href="tel:+886229393091">02-29393091</a></li>
 | 
			
		||||
  <li>傳真:02-29379611</li>
 | 
			
		||||
  <li>緊急重大事件通聯窗口:校內分機 66119、66110</li>
 | 
			
		||||
  <li>總值日室:<a href="tel:+88229387132">02-29387132</a></li>
 | 
			
		||||
  <li>駐警衛室:<a href="tel:+88229387129">02-29387129</a></li>
 | 
			
		||||
  <li>總務處電話:<a href="tel:+886229393091">02-29393091</a></li>
 | 
			
		||||
  <li>總務處傳真:02-29379611</li>
 | 
			
		||||
  <li>總務處單一窗口 李梅森專員:<a href="tel:+886233662233">02-33662233</a></li>
 | 
			
		||||
</ul>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,6 @@
 | 
			
		|||
<div id='map_canvas'></div>
 | 
			
		||||
 | 
			
		||||
<script type='text/javascript'>
 | 
			
		||||
  var $map_center = "24.987449, 121.576117"
 | 
			
		||||
  var $map_center = "25.015205, 121.535491"
 | 
			
		||||
  var $map_zoom = 17
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			@ -335,6 +335,7 @@ en:
 | 
			
		|||
  posted_by: Posted by
 | 
			
		||||
  preview: Preview
 | 
			
		||||
  profile: Profile
 | 
			
		||||
  promoter: Promoter
 | 
			
		||||
  publications: Publications
 | 
			
		||||
  purchase: Purchase
 | 
			
		||||
  quantity: Quantity
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,5 +9,5 @@ en:
 | 
			
		|||
    home: Home
 | 
			
		||||
    language: Language
 | 
			
		||||
    location: Location
 | 
			
		||||
    location_description: '<h3>This University</h3>No.101,Sec. 2, Jiafeng S Road, Zhubei City, Hsinchu County 302, Taiwan'
 | 
			
		||||
    location_description: '<h3>OFFICE OF GENERAL AFFAIRS, NTU</h3>No. 1, Sec. 4, Roosevelt Road, Taipei, 10617 Taiwan (R.O.C)'
 | 
			
		||||
    page: Page
 | 
			
		||||
| 
						 | 
				
			
			@ -9,5 +9,5 @@ zh_tw:
 | 
			
		|||
    home: 首頁
 | 
			
		||||
    language: 語言
 | 
			
		||||
    location: 地理位置
 | 
			
		||||
    location_description: '<h3>本大學</h3>302新竹縣竹北市嘉豐南路二段101號'
 | 
			
		||||
    location_description: '<h3>臺灣大學總務處 版權所有</h3>10617 臺北市大安區羅斯福路四段一號'
 | 
			
		||||
    page: 頁面
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
en: 
 | 
			
		||||
 | 
			
		||||
  ntu:
 | 
			
		||||
    rss_origin: Back to NTU Announcements
 | 
			
		||||
    site_names:
 | 
			
		||||
      "www": "Dean of General Affairs"
 | 
			
		||||
      "sec": "Office of the Dean and Secretariat"
 | 
			
		||||
      "doc": "Documentation Division"
 | 
			
		||||
      "general": "General Service Division"
 | 
			
		||||
      "property": "Property Management Division"
 | 
			
		||||
      "construction": "Construction and Maintenance Division"
 | 
			
		||||
      "cashier": "Cashier Division"
 | 
			
		||||
      "procurement": "Procurement Division"
 | 
			
		||||
      "fss": "Facilities Service Division"
 | 
			
		||||
      "police": "Campus Security"
 | 
			
		||||
      "social": "General Affairs Division, College of Social Science"
 | 
			
		||||
      "medicine": "General Service Division, College of Medicine"
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
zh_tw: 
 | 
			
		||||
 | 
			
		||||
  ntu:
 | 
			
		||||
    rss_origin: 回臺大校園公佈欄
 | 
			
		||||
    site_names:
 | 
			
		||||
      "www": "總務處"
 | 
			
		||||
      "sec": "總務長室暨總務處秘書室"
 | 
			
		||||
      "doc": "文書組"
 | 
			
		||||
      "general": "事務組"
 | 
			
		||||
      "property": "保管組"
 | 
			
		||||
      "construction": "營繕組"
 | 
			
		||||
      "cashier": "出納組"
 | 
			
		||||
      "procurement": "採購組"
 | 
			
		||||
      "fss": "經營管理組"
 | 
			
		||||
      "police": "駐警隊"
 | 
			
		||||
      "social": "社科院總務分處"
 | 
			
		||||
      "medicine": "醫學院總務分處"
 | 
			
		||||
| 
						 | 
				
			
			@ -336,6 +336,7 @@ zh_tw:
 | 
			
		|||
  posted_by: 張貼人
 | 
			
		||||
  preview: 預覽
 | 
			
		||||
  profile: 基本資料
 | 
			
		||||
  promoter: 承辦人
 | 
			
		||||
  publications: 著作
 | 
			
		||||
  purchase: 購買
 | 
			
		||||
  quantity: 數量
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ backup_server:
 | 
			
		|||
  description: BackupServer and remove old backups
 | 
			
		||||
 | 
			
		||||
update_tag_cloud:
 | 
			
		||||
  cron: 0 0 [0,12] * * *
 | 
			
		||||
  cron: 0 30 2 * * *
 | 
			
		||||
  class: UpdateTagCloud
 | 
			
		||||
  args:
 | 
			
		||||
  description: UpdateTagCloud
 | 
			
		||||
| 
						 | 
				
			
			@ -27,3 +27,9 @@ email_cron:
 | 
			
		|||
  class: EmailCron
 | 
			
		||||
  args:
 | 
			
		||||
  description: EmailCron
 | 
			
		||||
 | 
			
		||||
get_announcement_from_rss:
 | 
			
		||||
  cron: 0 0 [2,12] * * *
 | 
			
		||||
  class: GetAnnouncementFromRss
 | 
			
		||||
  args:
 | 
			
		||||
  description: Loop through the announcement RSS until 24h ago
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,13 @@ Orbit::Application.routes.draw do
 | 
			
		|||
    match "/users_passwd" => "desktop/registrations#update", :as => :users_passwd, :via => :put
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  devise_scope :user do
 | 
			
		||||
    get 'user_login' => 'sessions#create'
 | 
			
		||||
    match 'user_logout' => 'sessions#destroy'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  match "saml_login" => 'saml_logins#index'
 | 
			
		||||
 | 
			
		||||
  mount Resque::Server, :at => "/admin/resque"
 | 
			
		||||
  mount Rack::GridFS::Endpoint.new(:db => Mongoid.database,:lookup=>:path), :at => "gridfs"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -188,6 +195,11 @@ Orbit::Application.routes.draw do
 | 
			
		|||
    resources :member_selects do
 | 
			
		||||
      match 'member_select_search' => "member_selects#member_select_search" ,:as => :member_select_search,:via => "post"
 | 
			
		||||
      match 'member_select_add' => "member_selects#member_select_add" ,:as => :member_select_add,:via => "post"
 | 
			
		||||
      collection do
 | 
			
		||||
        get 'select_members'
 | 
			
		||||
        post 'set_roles'
 | 
			
		||||
        post 'set_users'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    match 'module_store' => 'module_store#index'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,144 @@
 | 
			
		|||
# encoding : utf-8
 | 
			
		||||
 | 
			
		||||
# Usage ===============
 | 
			
		||||
#
 | 
			
		||||
# ARGV[0] = folder path of xml files
 | 
			
		||||
# ARGV[1] = folder path of files
 | 
			
		||||
#
 | 
			
		||||
#======================
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
require 'mongo'
 | 
			
		||||
require 'nokogiri'
 | 
			
		||||
include Mongo
 | 
			
		||||
 | 
			
		||||
CSV_PATH = ARGV[0]
 | 
			
		||||
FILE_PATH = ARGV[1]
 | 
			
		||||
FIELDS = %w[title file createdate modifydate createuser modifyuser]
 | 
			
		||||
DB_BASE_NAME = "production"
 | 
			
		||||
 | 
			
		||||
TABLE = {
 | 
			
		||||
  "0" => ["gaTaco", "ntuga"],
 | 
			
		||||
  "1" => ["fdLai", "fdhome"],
 | 
			
		||||
  "5" => ["prLin", "property01"],
 | 
			
		||||
  "3" => ["gsTien", "ckh", "general01", "lynn"],
 | 
			
		||||
  "10" => ["cmChen", "construction01", "allen", "enAmeliaxu", "energy"],
 | 
			
		||||
#  "2" => ["caLin", "cashier01"],
 | 
			
		||||
  "6" => ["pcAmyok", "purchasing01", "purchasing02"],
 | 
			
		||||
  "7" => ["fmHsyu", "ntufss"],
 | 
			
		||||
  "4" => ["soChang", "social01"],
 | 
			
		||||
  "8" => ["meJune", "medicine01"],
 | 
			
		||||
  "9" => ["plKoa", "police"]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
which_site = {}
 | 
			
		||||
 | 
			
		||||
data = []
 | 
			
		||||
 | 
			
		||||
Dir.foreach(ARGV[0]) do |file|
 | 
			
		||||
  if file =~ /\w\.\w/
 | 
			
		||||
    doc = Nokogiri::XML(File.open(File.join(ARGV[0], file)))
 | 
			
		||||
    doc.xpath("//row").each { |row| 
 | 
			
		||||
      xml_fields = row.children.map{ |row| [row.name, row.content] }
 | 
			
		||||
      fields = FIELDS.inject([]) do |fields, field|
 | 
			
		||||
        xml_fields.each do |xf|
 | 
			
		||||
          if xf[0].include?(field)
 | 
			
		||||
            fields << xf[1] 
 | 
			
		||||
            break
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
        fields
 | 
			
		||||
      end
 | 
			
		||||
      data << fields + [File.basename(file, '.xml')]
 | 
			
		||||
    }
 | 
			
		||||
    data.each do |d|
 | 
			
		||||
      title, file, c_time, m_time, creator, modifier, category = d
 | 
			
		||||
      if file =~ /\w\.\w/
 | 
			
		||||
        file = File.join(File.join(ARGV[1], file))
 | 
			
		||||
        site = ""
 | 
			
		||||
        TABLE.each do |key, value|
 | 
			
		||||
          if value.include? modifier
 | 
			
		||||
            site = key
 | 
			
		||||
            break
 | 
			
		||||
          elsif value.include? creator
 | 
			
		||||
            site = key
 | 
			
		||||
            break
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
        site = "0" if site.empty?
 | 
			
		||||
        if which_site[site]
 | 
			
		||||
          if which_site[site][category]
 | 
			
		||||
            which_site[site][category] += [[title, file, c_time, m_time]]
 | 
			
		||||
          else
 | 
			
		||||
            which_site[site][category] = [[title, file, c_time, m_time]]
 | 
			
		||||
          end
 | 
			
		||||
        else
 | 
			
		||||
          which_site[site] = {category => [[title, file, c_time, m_time]]}
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def save_category archive_file_category, in_category
 | 
			
		||||
  category = {
 | 
			
		||||
    title: {"zh_tw" => in_category, "en" => in_category},
 | 
			
		||||
    key: "import_#{category}"
 | 
			
		||||
  }
 | 
			
		||||
  archive_file_category.save(category)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def save_file_multiples archive_file_multiples, grid ,archive_id,title, file, c_time, m_time
 | 
			
		||||
  a_file = File.open(file) rescue nil
 | 
			
		||||
  if a_file
 | 
			
		||||
    filename = File.basename(file)
 | 
			
		||||
    archive_file = {
 | 
			
		||||
      file_title: {"zh_tw" => title, "en" => title },
 | 
			
		||||
      choose_lang: ["zh_tw", "en"],
 | 
			
		||||
      file: filename,
 | 
			
		||||
      archive_file_id: archive_id,
 | 
			
		||||
      created_at: c_time,
 | 
			
		||||
      updated_at: m_time
 | 
			
		||||
    }
 | 
			
		||||
    a_file_id = archive_file_multiples.save(archive_file)
 | 
			
		||||
    grid.put(a_file, filename: "assets/archive_file_multiple/file/#{a_file_id}/#{filename}")
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def save_archive archive_files, category_id
 | 
			
		||||
  archive = {
 | 
			
		||||
    title: {"zh_tw" => " ", "en" => " "},
 | 
			
		||||
    archive_file_category_id: category_id,
 | 
			
		||||
    is_top: false,
 | 
			
		||||
    is_hot: false,
 | 
			
		||||
    is_hidden: false,
 | 
			
		||||
    created_at: c_time,
 | 
			
		||||
    updated_at: m_time
 | 
			
		||||
  }
 | 
			
		||||
  archive_files.save(archive)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
which_site.each do |site, categories|
 | 
			
		||||
 | 
			
		||||
  db = MongoClient.new("localhost", 27017).db("#{DB_BASE_NAME}_#{site}")
 | 
			
		||||
 | 
			
		||||
  categories.each do |category, data|
 | 
			
		||||
    archive_file_category = db.collection('archive_file_categories')
 | 
			
		||||
    category_id = save_category archive_file_category, category
 | 
			
		||||
 | 
			
		||||
    archive_files = db.collection('archive_files')
 | 
			
		||||
    archive_id = save_archive archive_files, category_id
 | 
			
		||||
 | 
			
		||||
    grid = Grid.new(db)
 | 
			
		||||
    archive_file_multiples = db.collection('archive_file_multiples')
 | 
			
		||||
    file_ids = []
 | 
			
		||||
 | 
			
		||||
    data.each do |file|
 | 
			
		||||
      save_file_multiples(archive_file_multiples, grid ,archive_id , *file)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
# encoding: utf-8
 | 
			
		||||
 | 
			
		||||
require 'mongo'
 | 
			
		||||
include Mongo
 | 
			
		||||
 | 
			
		||||
DB_BASE_NAME = "production"
 | 
			
		||||
 | 
			
		||||
main_db = MongoClient.new("localhost", 27017).db("#{DB_BASE_NAME}_#{0}")
 | 
			
		||||
main_bulletin = main_db["bulletins"]
 | 
			
		||||
main_cat =  main_db["bulletin_categories"]
 | 
			
		||||
 | 
			
		||||
copy_db = MongoClient.new("localhost", 27017).db("#{DB_BASE_NAME}_#{11}")
 | 
			
		||||
copy_bulletin = copy_db["bulletins"]
 | 
			
		||||
copy_cat =  copy_db["bulletin_categories"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
main_cat.find(key: /rss_/).each do |category|
 | 
			
		||||
  category_id = \
 | 
			
		||||
  if cat = copy_cat.find_one(key: category['key'])
 | 
			
		||||
    cat['_id']
 | 
			
		||||
  else
 | 
			
		||||
    copy_category = category.clone
 | 
			
		||||
    copy_category['_id'] = BSON::ObjectId.new
 | 
			
		||||
    copy_cat.save copy_category
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  main_bulletin.find(bulletin_category_id: category['_id']).each do |bulletin|
 | 
			
		||||
    unless copy_bulletin.find_one(rss_link: bulletin['rss_link'])
 | 
			
		||||
      copybulletin = bulletin.clone
 | 
			
		||||
      copybulletin['_id'] = BSON::ObjectId.new
 | 
			
		||||
      copybulletin['bulletin_category_id'] = category_id
 | 
			
		||||
      bulletin_id = copy_bulletin.save copybulletin
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,129 @@
 | 
			
		|||
# encoding: utf-8
 | 
			
		||||
 | 
			
		||||
require 'rss'
 | 
			
		||||
require 'mongo'
 | 
			
		||||
 | 
			
		||||
SITES = { "總務處-各單位公告" => "0",
 | 
			
		||||
          "總務處-文書組" => "1",
 | 
			
		||||
          "總務處-出納組" => "2",
 | 
			
		||||
          "總務處-事務組" => "3",
 | 
			
		||||
          "總務處-保管組" => "5",
 | 
			
		||||
          "總務處-採購組" => "6",
 | 
			
		||||
          "總務處-經營管理組" => "7",
 | 
			
		||||
          "總務處-駐衛警察隊" => "9",
 | 
			
		||||
          "總務處-營繕組" => "10",
 | 
			
		||||
          "總務處-總務處" => "11",
 | 
			
		||||
          "社會科學院-社會科學院總務分處" => "4",
 | 
			
		||||
          "醫學院-醫學院總務分處" => "8" }
 | 
			
		||||
 | 
			
		||||
SITE_KEYS = SITES.keys
 | 
			
		||||
 | 
			
		||||
DB_BASE_NAME = "production"
 | 
			
		||||
 | 
			
		||||
all = {}
 | 
			
		||||
continue = true
 | 
			
		||||
i = 1
 | 
			
		||||
yesterday = Time.now - 86400
 | 
			
		||||
 | 
			
		||||
while continue do
 | 
			
		||||
  open("http://ann.cc.ntu.edu.tw/asp/rss.asp?page=#{i}") do |rss|
 | 
			
		||||
    feed = RSS::Parser.parse(rss.read.encode('utf-8', 'big5', invalid: :replace, undef: :replace, replace: '').gsub('<pubDate>Wes,', '<pubDate>Wed,').gsub(/(encoding=\"big5\")/, 'encoding="utf-8"'))
 | 
			
		||||
    feed.items.each do |item|
 | 
			
		||||
      if item.pubDate > yesterday
 | 
			
		||||
        if SITE_KEYS.include?(item.author)
 | 
			
		||||
          author = item.author.strip
 | 
			
		||||
          category = item.category.to_s.gsub(/\<(\/)*category\>/, '')
 | 
			
		||||
          if all[author]
 | 
			
		||||
            all[author][item.link.strip] = {title: item.title.strip, author: author, link: item.link.strip, date: item.pubDate, category: category, description: item.description.gsub("\r\n", '<br/>').strip}
 | 
			
		||||
          else
 | 
			
		||||
            all[author] = {item.link.strip => {title: item.title.strip, author: author, link: item.link.strip, date: item.pubDate, category: category, description: item.description.gsub("\r\n", '<br/>').strip}}
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      else
 | 
			
		||||
        continue = false
 | 
			
		||||
        break
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  i += 1
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# Get corresponding category_id or create a new one
 | 
			
		||||
def get_category_id(category, categories, coll_cat)
 | 
			
		||||
  if categories.keys.include? "rss_#{category}"
 | 
			
		||||
    [categories["rss_#{category}"], categories]
 | 
			
		||||
  else
 | 
			
		||||
    cat = {
 | 
			
		||||
      _type: "BulletinCategory",
 | 
			
		||||
      key: "rss_#{category}",
 | 
			
		||||
      disable: false,
 | 
			
		||||
      title: {:zh_tw => category},
 | 
			
		||||
      created_at: Time.now,
 | 
			
		||||
      updated_at: Time.now
 | 
			
		||||
    }
 | 
			
		||||
    categories["rss_#{category}"] = result = coll_cat.save(cat)
 | 
			
		||||
    [result, categories]
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# Get categories and id based on a given site number
 | 
			
		||||
def get_mongo_and_categories(site_number="0")
 | 
			
		||||
  db = Mongo::Connection.new("localhost", 27017).db("#{DB_BASE_NAME}_#{site_number}")
 | 
			
		||||
  coll_bulletin = db["bulletins"]
 | 
			
		||||
  coll_cat =  db["bulletin_categories"]
 | 
			
		||||
 | 
			
		||||
  categories = coll_cat.find().to_a.inject({}) do |categories, category|
 | 
			
		||||
    categories[category['key']] = category['_id']
 | 
			
		||||
    categories
 | 
			
		||||
  end
 | 
			
		||||
  [categories, coll_bulletin, coll_cat]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# Get main site (總務處) categories
 | 
			
		||||
@main_categories, @main_coll_bulletin, @main_coll_cat = get_mongo_and_categories
 | 
			
		||||
@copy_categories, @copy_coll_bulletin, @copy_coll_cat = get_mongo_and_categories('11')
 | 
			
		||||
 | 
			
		||||
all.each do |key, value| # Loop through all the authors
 | 
			
		||||
  site_number = SITES[key]
 | 
			
		||||
  categories, coll_bulletin, coll_cat = get_mongo_and_categories(site_number) # Get current's site categories
 | 
			
		||||
  value.each_value do |bul| # Loop through all the items
 | 
			
		||||
    category_id, categories = get_category_id(bul[:category], categories, coll_cat)
 | 
			
		||||
    unless coll_bulletin.find_one(rss_link: bul[:link]) 
 | 
			
		||||
      bulletin = {  _type: "Bulletin",
 | 
			
		||||
                    postdate: bul[:date],
 | 
			
		||||
                    created_at: bul[:date],
 | 
			
		||||
                    updated_at: bul[:date],
 | 
			
		||||
                    is_checked: true,
 | 
			
		||||
                    is_pending: false,
 | 
			
		||||
                    is_rejected: false,
 | 
			
		||||
                    bulletin_category_id: category_id,
 | 
			
		||||
                    title: {:zh_tw => bul[:title]},
 | 
			
		||||
                    text: {:zh_tw => bul[:description]},
 | 
			
		||||
                    available_for_zh_tw: true,
 | 
			
		||||
                    rss_link: bul[:link],
 | 
			
		||||
                    is_top: false,
 | 
			
		||||
                    is_hot: false,
 | 
			
		||||
                    is_hidden: false }
 | 
			
		||||
      coll_bulletin.save(bulletin) 
 | 
			
		||||
 | 
			
		||||
      unless site_number.eql?("0") || @main_coll_bulletin.find_one(rss_link: bul[:link]) # Copy the item to the main site
 | 
			
		||||
 | 
			
		||||
        category_id, @main_categories = get_category_id(bul[:category], @main_categories, @main_coll_cat)
 | 
			
		||||
        main_bulletin = bulletin.clone
 | 
			
		||||
        main_bulletin['_id'] = BSON::ObjectId.new
 | 
			
		||||
        main_bulletin[:bulletin_category_id] = category_id
 | 
			
		||||
        @main_coll_bulletin.save(main_bulletin)
 | 
			
		||||
 | 
			
		||||
        category_id, @copy_categories = get_category_id(bul[:category], @copy_categories, @copy_coll_cat)
 | 
			
		||||
        copy_bulletin = bulletin.clone
 | 
			
		||||
        copy_bulletin['_id'] = BSON::ObjectId.new
 | 
			
		||||
        copy_bulletin[:bulletin_category_id] = category_id
 | 
			
		||||
        @copy_coll_bulletin.save(copy_bulletin)
 | 
			
		||||
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,113 @@
 | 
			
		|||
# encoding: utf-8
 | 
			
		||||
 | 
			
		||||
require 'rss'
 | 
			
		||||
require 'mongo'
 | 
			
		||||
 | 
			
		||||
SITES = { "總務處-各單位公告" => "0",
 | 
			
		||||
          "總務處-文書組" => "1",
 | 
			
		||||
          "總務處-出納組" => "2",
 | 
			
		||||
          "總務處-事務組" => "3",
 | 
			
		||||
          "總務處-保管組" => "5",
 | 
			
		||||
          "總務處-採購組" => "6",
 | 
			
		||||
          "總務處-經營管理組" => "7",
 | 
			
		||||
          "總務處-駐衛警察隊" => "9",
 | 
			
		||||
          "總務處-營繕組" => "10",
 | 
			
		||||
          "總務處-總務處" => "11",
 | 
			
		||||
          "社會科學院-社會科學院總務分處" => "4",
 | 
			
		||||
          "醫學院-醫學院總務分處" => "8" }
 | 
			
		||||
 | 
			
		||||
SITE_KEYS = SITES.keys
 | 
			
		||||
 | 
			
		||||
DB_BASE_NAME = "production"
 | 
			
		||||
 | 
			
		||||
all = {}
 | 
			
		||||
continue = true
 | 
			
		||||
i = 1
 | 
			
		||||
while continue do
 | 
			
		||||
  open("http://ann.cc.ntu.edu.tw/asp/rss.asp?page=#{i}") do |rss|
 | 
			
		||||
    feed = RSS::Parser.parse(rss.read.encode('utf-8', 'big5', invalid: :replace, undef: :replace, replace: '').gsub('<pubDate>Wes,', '<pubDate>Wed,').gsub(/(encoding=\"big5\")/, 'encoding="utf-8"'))
 | 
			
		||||
    feed.items.size
 | 
			
		||||
    feed.items.each do |item|
 | 
			
		||||
      if SITE_KEYS.include?(item.author)
 | 
			
		||||
        author = item.author.strip
 | 
			
		||||
        category = item.category.to_s.gsub(/\<(\/)*category\>/, '')
 | 
			
		||||
        if all[author]
 | 
			
		||||
          all[author][item.link.strip] = {title: item.title.strip, author: author, link: item.link.strip, date: item.pubDate, category: category, description: item.description.gsub("\r\n", '<br/>').strip}
 | 
			
		||||
        else
 | 
			
		||||
          all[author] = {item.link.strip => {title: item.title.strip, author: author, link: item.link.strip, date: item.pubDate, category: category, description: item.description.gsub("\r\n", '<br/>').strip}}
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    continue = false if feed.items.size < 100
 | 
			
		||||
  end
 | 
			
		||||
  i += 1
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# Get corresponding category_id or create a new one
 | 
			
		||||
def get_category_id(category, categories, coll_cat)
 | 
			
		||||
  if categories.keys.include? "rss_#{category}"
 | 
			
		||||
    [categories["rss_#{category}"], categories]
 | 
			
		||||
  else
 | 
			
		||||
    cat = {
 | 
			
		||||
      _type: "BulletinCategory",
 | 
			
		||||
      key: "rss_#{category}",
 | 
			
		||||
      disable: false,
 | 
			
		||||
      title: {:zh_tw => category},
 | 
			
		||||
      created_at: Time.now,
 | 
			
		||||
      updated_at: Time.now
 | 
			
		||||
    }
 | 
			
		||||
    categories["rss_#{category}"] = result = coll_cat.save(cat)
 | 
			
		||||
    [result, categories]
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# Get categories and id based on a given site number
 | 
			
		||||
def get_mongo_and_categories(site_number="0")
 | 
			
		||||
  db = Mongo::Connection.new("localhost", 27017).db("#{DB_BASE_NAME}_#{site_number}")
 | 
			
		||||
  coll_bulletin = db["bulletins"]
 | 
			
		||||
  coll_cat =  db["bulletin_categories"]
 | 
			
		||||
 | 
			
		||||
  categories = coll_cat.find().to_a.inject({}) do |categories, category|
 | 
			
		||||
    categories[category['key']] = category['_id']
 | 
			
		||||
    categories
 | 
			
		||||
  end
 | 
			
		||||
  [categories, coll_bulletin, coll_cat]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# Get main site (總務處) categories
 | 
			
		||||
@main_categories, @main_coll_bulletin, @main_coll_cat = get_mongo_and_categories
 | 
			
		||||
 | 
			
		||||
all.each do |key, value| # Loop through all the authors
 | 
			
		||||
  site_number = SITES[key]
 | 
			
		||||
  categories, coll_bulletin, coll_cat = get_mongo_and_categories(site_number) # Get current's site categories
 | 
			
		||||
  value.each_value do |bul| # Loop through all the items
 | 
			
		||||
    category_id, categories = get_category_id(bul[:category], categories, coll_cat)
 | 
			
		||||
    unless coll_bulletin.find_one(rss_link: bul[:link]) 
 | 
			
		||||
      bulletin = {  _type: "Bulletin",
 | 
			
		||||
                    postdate: bul[:date],
 | 
			
		||||
                    created_at: bul[:date],
 | 
			
		||||
                    updated_at: bul[:date],
 | 
			
		||||
                    is_checked: true,
 | 
			
		||||
                    is_pending: false,
 | 
			
		||||
                    is_rejected: false,
 | 
			
		||||
                    bulletin_category_id: category_id,
 | 
			
		||||
                    title: {:zh_tw => bul[:title]},
 | 
			
		||||
                    text: {:zh_tw => bul[:description]},
 | 
			
		||||
                    available_for_zh_tw: true,
 | 
			
		||||
                    rss_link: bul[:link],
 | 
			
		||||
                    is_top: false,
 | 
			
		||||
                    is_hot: false,
 | 
			
		||||
                    is_hidden: false }
 | 
			
		||||
      coll_bulletin.save(bulletin) 
 | 
			
		||||
      unless site_number.eql? "0" # Copy the item to the main site
 | 
			
		||||
        category_id, @main_categories = get_category_id(bul[:category], @main_categories, @main_coll_cat)
 | 
			
		||||
        main_bulletin = bulletin.clone
 | 
			
		||||
        main_bulletin['_id'] = BSON::ObjectId.new
 | 
			
		||||
        main_bulletin[:bulletin_category_id] = category_id
 | 
			
		||||
        @main_coll_bulletin.save(main_bulletin)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -310,6 +310,74 @@ namespace :migrate do
 | 
			
		|||
    Rake::Task["web_link_url:web_link_url_i18n"].execute
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  task :save_users => :environment do
 | 
			
		||||
    User.where(:email.not => /guest/).each{|s|s.save}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  task :fix_bulletin_rss_available_lang => :environment do
 | 
			
		||||
    Bulletin.all.each do |bull|
 | 
			
		||||
      if bull.create_user_id.nil?
 | 
			
		||||
        bull.update_attribute(:available_for_zh_tw, true)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  task :fix_imported_data => :environment do
 | 
			
		||||
    categories = BulletinCategory.where(key: /import_/).entries
 | 
			
		||||
    unless categories.blank?
 | 
			
		||||
      categories.each do |category|
 | 
			
		||||
        bulletins = category.bulletins
 | 
			
		||||
        unless bulletins.blank?
 | 
			
		||||
          bulletins.each do |bulletin|
 | 
			
		||||
            unless bulletin.bulletin_files.blank?
 | 
			
		||||
              file = bulletin.bulletin_files[0]
 | 
			
		||||
              bulletin.text_translations = file.description_translations
 | 
			
		||||
              bulletin.save
 | 
			
		||||
              file.update_attribute(:description, nil)
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    categories = ArchiveFileCategory.where(key: /import_/).entries
 | 
			
		||||
    unless categories.blank?
 | 
			
		||||
      categories.each do |category|
 | 
			
		||||
        files = category.archive_files
 | 
			
		||||
        unless files.blank?
 | 
			
		||||
          files.each{|file| file.update_attributes({is_top: false, is_hot: false, is_hidden: false})}
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end 
 | 
			
		||||
 | 
			
		||||
  task :delete_rss_announcement => :environment do
 | 
			
		||||
    categories = BulletinCategory.where(key: /rss_/).entries
 | 
			
		||||
    unless categories.blank?
 | 
			
		||||
      categories.each do |category|
 | 
			
		||||
        bulletins = category.bulletins
 | 
			
		||||
        unless bulletins.blank?
 | 
			
		||||
          bulletins.each(&:destroy)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end 
 | 
			
		||||
 | 
			
		||||
  task :fix_imported_rss => :environment do
 | 
			
		||||
    categories = BulletinCategory.where(key: /rss_/).entries
 | 
			
		||||
    unless categories.blank?
 | 
			
		||||
      categories.each do |category|
 | 
			
		||||
        bulletins = category.bulletins
 | 
			
		||||
        unless bulletins.blank?
 | 
			
		||||
          bulletins.each do |bulletin|
 | 
			
		||||
            bulletin.update_attribute(:is_top, false) unless bulletin.is_top?
 | 
			
		||||
            bulletin.update_attribute(:is_hot, false) unless bulletin.is_hot?
 | 
			
		||||
            bulletin.update_attribute(:is_hidden, false) unless bulletin.is_hidden?
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  task :fix_tagged_ids => :environment do
 | 
			
		||||
    Tag.all.each do |tag|
 | 
			
		||||
      tag.taggings.each do |tagging|
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,183 @@
 | 
			
		|||
# encoding: utf-8 
 | 
			
		||||
 | 
			
		||||
namespace :mongo_files do
 | 
			
		||||
 | 
			
		||||
  MODELS = {  'ad_image' => 'file',
 | 
			
		||||
              'archive_file_multiple' => 'file',
 | 
			
		||||
              'asset' => 'data',
 | 
			
		||||
              'bulletin' => 'image',
 | 
			
		||||
              'bulletin_file' => 'file',
 | 
			
		||||
              'design' => 'zip_file',
 | 
			
		||||
              'design_file' => 'file',
 | 
			
		||||
              'gallery_image' => 'file',
 | 
			
		||||
              'image' => 'file',
 | 
			
		||||
              'lab_file' => 'file',
 | 
			
		||||
              'location_info' => 'file',
 | 
			
		||||
              'preview_file' => 'file',
 | 
			
		||||
              'project_file' => 'file',
 | 
			
		||||
              'research_file' => 'file',
 | 
			
		||||
              'site' => 'default_image',
 | 
			
		||||
              'stylesheet' => 'file_orig',
 | 
			
		||||
              'user' => 'avatar',
 | 
			
		||||
              'writing_book_file' => 'file',
 | 
			
		||||
              'writing_conference_file' => 'file',
 | 
			
		||||
              'writing_journal_file' => 'file',
 | 
			
		||||
              'writing_patent_file' => 'file' }
 | 
			
		||||
 | 
			
		||||
  IMAGE_UPLOADER_MODELS = %w[ad_image bulletin image site]
 | 
			
		||||
 | 
			
		||||
  # ad_banner
 | 
			
		||||
  # bulletin
 | 
			
		||||
  # design
 | 
			
		||||
  # site
 | 
			
		||||
 | 
			
		||||
  task :clean => :environment do
 | 
			
		||||
    @files = Mongoid.database['fs.files']
 | 
			
		||||
    @chunks = Mongoid.database['fs.chunks']
 | 
			
		||||
    clean_duplicates
 | 
			
		||||
    clean_unused
 | 
			
		||||
    remove_objects
 | 
			
		||||
    # remove_unlinked
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Remove unused files from db
 | 
			
		||||
  def clean_unused
 | 
			
		||||
    db_array = @files.find().inject([]) do |db_files, file|
 | 
			
		||||
      db_files << file['filename']
 | 
			
		||||
      db_files
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    p "# of files in db: #{db_array.size}"
 | 
			
		||||
 | 
			
		||||
    name_array = MODELS.inject([]) do |model_files, (model, type)|
 | 
			
		||||
      model.classify.constantize.all.each do |item|
 | 
			
		||||
        url = item.send(type).url
 | 
			
		||||
        thumb_url = item.send(type).thumb.url rescue nil
 | 
			
		||||
        if url && !url.eql?('sign-in-logo.png')
 | 
			
		||||
          url = url.gsub('/gridfs/', '')
 | 
			
		||||
          model_files << url
 | 
			
		||||
        end
 | 
			
		||||
        if thumb_url && !thumb_url.eql?('sign-in-logo.png')
 | 
			
		||||
          thumb_url = thumb_url.gsub('/gridfs/', '')
 | 
			
		||||
          model_files << thumb_url
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      model_files
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    p "# of files from uploaders: #{name_array.size}"
 | 
			
		||||
    useless_files = db_array - name_array
 | 
			
		||||
    p "# of unmatched files: #{useless_files.size}"
 | 
			
		||||
 | 
			
		||||
    useless_files.each do |file|
 | 
			
		||||
      id = @files.find_one('filename' => file)['_id']
 | 
			
		||||
      @files.remove('_id' => id)
 | 
			
		||||
      @chunks.remove('files_id' => id)
 | 
			
		||||
    end
 | 
			
		||||
    # p files.remove('filename' => { "$in" => useless_files})
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  # Remove duplicate files from db
 | 
			
		||||
  def clean_duplicates
 | 
			
		||||
    p "# of files in db: #{@files.count}"
 | 
			
		||||
    file_hash = @files.find().inject({}) do |db_files, file|
 | 
			
		||||
      name = file['filename']
 | 
			
		||||
      if db_files[name]
 | 
			
		||||
        db_files[name] += [file['_id']]
 | 
			
		||||
      else
 | 
			
		||||
        db_files[name] = [file['_id']]
 | 
			
		||||
      end
 | 
			
		||||
      db_files
 | 
			
		||||
    end
 | 
			
		||||
    file_array = file_hash.inject([]) do |files, (key, value)|
 | 
			
		||||
      files += value.drop(1) if value.size > 1
 | 
			
		||||
      files
 | 
			
		||||
    end
 | 
			
		||||
    p "# of duplicate ids to delete: #{file_array.size}"
 | 
			
		||||
    file_array.each do |id|
 | 
			
		||||
      @files.remove('_id' => id)
 | 
			
		||||
      @chunks.remove('files_id' => id)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  task :file_size => :environment do
 | 
			
		||||
    files = Mongoid.database['fs.files']
 | 
			
		||||
    size_array = files.find().inject([]) do |size, file|
 | 
			
		||||
      # size << [file['length'], file['filename']]
 | 
			
		||||
      size << [file['filename'], file['length']]
 | 
			
		||||
      size
 | 
			
		||||
    end
 | 
			
		||||
    size_array.sort.each do |pair|
 | 
			
		||||
      p "#{pair[0]} - #{pair[1]}"
 | 
			
		||||
    end
 | 
			
		||||
    p size_array.size
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def remove_objects
 | 
			
		||||
    # Destroy writing_journals and writing_journal_files
 | 
			
		||||
    Mongoid.database['writing_journals'].remove()
 | 
			
		||||
    Mongoid.database['writing_journal_files'].remove()
 | 
			
		||||
 | 
			
		||||
    # Destroy bulletins, bulletin_files and bulletin_links
 | 
			
		||||
    Bulletin.excludes(create_user_id: nil).destroy
 | 
			
		||||
    BulletinFile.destroy_all
 | 
			
		||||
    BulletinLink.destroy_all
 | 
			
		||||
 | 
			
		||||
    # Destroy gallery_albums and gallery_images
 | 
			
		||||
    Mongoid.database['gallery_albums'].remove()
 | 
			
		||||
    Mongoid.database['gallery_images'].remove()
 | 
			
		||||
 | 
			
		||||
    db_array = @files.find().inject([]) do |db_files, file|
 | 
			
		||||
      db_files << file['filename'] if file['filename'] =~ /writing_journal_file|news_bulletin_file|bulletin_file|gallery_image|image\/image/
 | 
			
		||||
      db_files
 | 
			
		||||
    end
 | 
			
		||||
    p db_array.size
 | 
			
		||||
    db_array.each do |file|
 | 
			
		||||
      id = @files.find_one('filename' => file)['_id']
 | 
			
		||||
      @files.remove('_id' => id)
 | 
			
		||||
      @chunks.remove('files_id' => id)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def remove_unlinked
 | 
			
		||||
    # name_array = AdBanner.all.inject([]) do |files, banner|
 | 
			
		||||
    #   banner.ad_images.inject(files) do |image_files, image|
 | 
			
		||||
    #     url = image.file.url
 | 
			
		||||
    #     thumb_url = image.file.thumb.url rescue nil
 | 
			
		||||
    #     if url && !url.eql?('sign-in-logo.png')
 | 
			
		||||
    #       url = url.gsub('/gridfs/', '')
 | 
			
		||||
    #       image_files << url
 | 
			
		||||
    #     end
 | 
			
		||||
    #     if thumb_url && !thumb_url.eql?('sign-in-logo.png')
 | 
			
		||||
    #       thumb_url = thumb_url.gsub('/gridfs/', '')
 | 
			
		||||
    #       image_files << thumb_url
 | 
			
		||||
    #     end
 | 
			
		||||
    #     image_files
 | 
			
		||||
    #   end
 | 
			
		||||
    #   files
 | 
			
		||||
    # end
 | 
			
		||||
    name_array = Design.all.inject([]) do |files, design|
 | 
			
		||||
      files += design.images.inject(files) do |image_files, image|
 | 
			
		||||
        p image_files += get_url_and_thumb(image.file)
 | 
			
		||||
        image_files
 | 
			
		||||
      end
 | 
			
		||||
      files
 | 
			
		||||
    end
 | 
			
		||||
    p name_array.size
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def get_url_and_thumb(file)
 | 
			
		||||
    url = file.url
 | 
			
		||||
    thumb_url = file.thumb.url rescue nil
 | 
			
		||||
    files = [url, thumb_url].inject([]) do |urls, current|
 | 
			
		||||
      urls << current.gsub('/gridfs/', '') if current && !current.eql?('sign-in-logo.png')
 | 
			
		||||
      urls
 | 
			
		||||
    end
 | 
			
		||||
    files
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  task :delete_rss_ann => :environment do
 | 
			
		||||
    Bulletin.where(create_user_id: nil).destroy
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -9,17 +9,17 @@ namespace :web_link_url do
 | 
			
		|||
  	
 | 
			
		||||
  	@weblinks.each do |wl|
 | 
			
		||||
 | 
			
		||||
  	  if wl.url.nil? 
 | 
			
		||||
      if wl.url_translations.is_a?(String)
 | 
			
		||||
      
 | 
			
		||||
        @wlurl = wl.url_translations
 | 
			
		||||
        
 | 
			
		||||
        wl.url_translations = {}
 | 
			
		||||
    	
 | 
			
		||||
        wl.url_translations["zh_tw"] = @wlurl
 | 
			
		||||
    	
 | 
			
		||||
        wl.url_translations["en"] = @wlurl
 | 
			
		||||
 | 
			
		||||
  	  @wlurl = wl.url_translations
 | 
			
		||||
 | 
			
		||||
      wl.url_translations = {}
 | 
			
		||||
  	
 | 
			
		||||
      wl.url_translations["zh_tw"] = @wlurl
 | 
			
		||||
  	
 | 
			
		||||
      wl.url_translations["en"] = @wlurl
 | 
			
		||||
 | 
			
		||||
      wl.save
 | 
			
		||||
        wl.save
 | 
			
		||||
 | 
			
		||||
  	  else
 | 
			
		||||
  	  	puts 'no data'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
// This list may be created by a server logic page PHP/ASP/ASPX/JSP in some backend system.
 | 
			
		||||
// There templates will be displayed as a dropdown in all media dialog if the "template_external_list_url"
 | 
			
		||||
// option is defined in TinyMCE init.
 | 
			
		||||
 | 
			
		||||
var tinyMCETemplateList = [
 | 
			
		||||
  // Name, URL, Description
 | 
			
		||||
  ["Simple snippet", "/tinymce/templates/snippet1.htm", "Simple HTML snippet."],
 | 
			
		||||
  ["Layout", "/tinymce/templates/layout1.htm", "HTML Layout."]
 | 
			
		||||
];
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
<table border="1">
 | 
			
		||||
	<thead>
 | 
			
		||||
		<tr>
 | 
			
		||||
			<td>Column 1</td>
 | 
			
		||||
			<td>Column 2</td>
 | 
			
		||||
		</tr>
 | 
			
		||||
	</thead>
 | 
			
		||||
 | 
			
		||||
	<tbody>
 | 
			
		||||
		<tr>
 | 
			
		||||
			<td>Username: {$username}</td>
 | 
			
		||||
			<td>Staffid: {$staffid}</td>
 | 
			
		||||
		</tr>
 | 
			
		||||
	</tbody>
 | 
			
		||||
</table>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
This is just some <strong>code</strong>.
 | 
			
		||||
| 
						 | 
				
			
			@ -95,6 +95,7 @@ class Panel::Announcement::BackEnd::BulletinsController < OrbitBackendController
 | 
			
		|||
  # GET /bulletins/1/edit
 | 
			
		||||
  def edit
 | 
			
		||||
    @bulletin = Bulletin.find(params[:id])
 | 
			
		||||
    @users = @bulletin.get_users
 | 
			
		||||
    if !current_user.admin? && (@bulletin.is_rejected? || @bulletin.is_checked?)
 | 
			
		||||
      redirect_to :action => :index
 | 
			
		||||
    else
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,6 +28,7 @@ class Bulletin
 | 
			
		|||
 | 
			
		||||
  field :create_user_id
 | 
			
		||||
  field :update_user_id, :class_name => "User"
 | 
			
		||||
  field :user_ids
 | 
			
		||||
  
 | 
			
		||||
  field :is_top, :type => Boolean, :default => false
 | 
			
		||||
  field :is_hot, :type => Boolean, :default => false
 | 
			
		||||
| 
						 | 
				
			
			@ -40,6 +41,7 @@ class Bulletin
 | 
			
		|||
  field :not_checked_reason
 | 
			
		||||
  
 | 
			
		||||
  field :public, :type => Boolean, :default => true
 | 
			
		||||
  field :rss_link
 | 
			
		||||
  
 | 
			
		||||
  scope :can_display, where(is_checked: true, is_rejected: false, is_pending: false)
 | 
			
		||||
  scope :available_for_lang, ->(locale){ where("available_for_#{locale}".to_sym => true) }
 | 
			
		||||
| 
						 | 
				
			
			@ -215,6 +217,10 @@ class Bulletin
 | 
			
		|||
    preview_object
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def get_users
 | 
			
		||||
    User.find(self.user_ids) rescue []
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  protected
 | 
			
		||||
  
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -116,6 +116,17 @@
 | 
			
		|||
		<% elsif current_user.admin? %>
 | 
			
		||||
			<%= f.hidden_field :is_checked,:value => true%>
 | 
			
		||||
		<% end %>
 | 
			
		||||
 | 
			
		||||
		<div id="widget-member" class="widget-box widget-size-300">
 | 
			
		||||
			<div class="widget-action clear tip" title="Rejected Report">
 | 
			
		||||
				<a class="action"><i class="icon-cog icon-white"></i></a>
 | 
			
		||||
			</div>
 | 
			
		||||
			<h3 class="widget-title"><i class="icons-tag"></i><%= t(:promoter) %></h3>
 | 
			
		||||
				<div class="widget-content clear form-horizontal">
 | 
			
		||||
					<%= render partial: 'admin/member_selects/selection_box', locals: {field: 'bulletin[user_ids][]', users: @users} %>
 | 
			
		||||
				</div>
 | 
			
		||||
		</div>
 | 
			
		||||
 | 
			
		||||
	</div>
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -130,7 +141,7 @@
 | 
			
		|||
		
 | 
			
		||||
			<%= f.label :category,t(:category)%> 
 | 
			
		||||
			<%= f.select :bulletin_category_id, @bulletin_categorys.collect{|t| [ t.title, t.id ]}, {}, :class => "input-medium" %>
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			<ul class="nav nav-tabs">
 | 
			
		||||
				<%# @site_valid_locales.each_with_index do |locale, i| %>
 | 
			
		||||
				<% @site_valid_locales.each_with_index do |locale, i| %>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@
 | 
			
		|||
<div class="news_paragraph">
 | 
			
		||||
	<%= @bulletin.text.html_safe rescue '' %>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<div class="linkAndFile">
 | 
			
		||||
	<% if @bulletin.bulletin_links.size > 0 %>
 | 
			
		||||
		<div>
 | 
			
		||||
| 
						 | 
				
			
			@ -36,6 +37,22 @@
 | 
			
		|||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
	<% end %>
 | 
			
		||||
	<% unless @bulletin.rss_link.blank? %>
 | 
			
		||||
		<div>
 | 
			
		||||
			<%= link_to t('ntu.rss_origin'), @bulletin.rss_link %>
 | 
			
		||||
		</div>
 | 
			
		||||
	<% end %>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<% unless @bulletin.user_ids.blank? %>
 | 
			
		||||
	<div class="promoter">
 | 
			
		||||
		<div>
 | 
			
		||||
			<p><%= t(:promoter) %>:</p>
 | 
			
		||||
			<span><%= @bulletin.get_users.map{|u| "<span>#{u.name}</span>"}.join(', ').html_safe %></span>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
<% end %>
 | 
			
		||||
 | 
			
		||||
<%= share_links(@bulletin, 'announcement') %>
 | 
			
		||||
 | 
			
		||||
<%= render partial: 'admin/member_selects/promoter_front', locals: {users: @bulletin.get_users} %>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,8 +29,8 @@ module Announcement
 | 
			
		|||
 | 
			
		||||
    widgets do
 | 
			
		||||
      default_widget do
 | 
			
		||||
	  sorting 'desc(:postdate)'
 | 
			
		||||
        query 'Bulletin.available_for_lang(I18n.locale).any_of( {deadline: nil,:postdate.lte => Time.now} , {:deadline.gte => Time.now,:postdate.lte => Time.now} )'
 | 
			
		||||
        sorting 'desc(:is_top, :postdate)'
 | 
			
		||||
        query 'Bulletin.can_display.available_for_lang(I18n.locale).any_of( {deadline: nil,:postdate.lte => Time.now} , {:deadline.gte => Time.now,:postdate.lte => Time.now} )'
 | 
			
		||||
        enable ["typeA","typeB_style3","typeC"]
 | 
			
		||||
        image :image
 | 
			
		||||
        field :postdate
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -133,4 +133,28 @@ border-radius: 3px;
 | 
			
		|||
}
 | 
			
		||||
.o-archives.layout-table .o-archives-category {
 | 
			
		||||
	font-weight: normal;
 | 
			
		||||
}
 | 
			
		||||
.o-archives.layout-table table {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
}
 | 
			
		||||
.o-archives.layout-table tbody tr td {
 | 
			
		||||
    border-top: none;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
}
 | 
			
		||||
.o-archives.layout-table tbody tr:nth-child(odd) td {
 | 
			
		||||
    border-bottom: none;
 | 
			
		||||
    padding: 10px 0 0;
 | 
			
		||||
}
 | 
			
		||||
.o-archives.layout-table tbody tr:nth-child(even) td .o-archives-category {
 | 
			
		||||
    margin-bottom: 5px;
 | 
			
		||||
}
 | 
			
		||||
.o-archives.layout-table tbody .o-archives-list-item ol {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
}
 | 
			
		||||
.o-archives.layout-table tbody .promoter-block {
 | 
			
		||||
    margin: 0 0 10px;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
    background-color: transparent;
 | 
			
		||||
    border: none;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -70,6 +70,7 @@ class Panel::Archive::BackEnd::ArchiveFilesController < OrbitBackendController
 | 
			
		|||
  # GET /archive_files/1/edit
 | 
			
		||||
  def edit
 | 
			
		||||
    @archive_file = ArchiveFile.find(params[:id])
 | 
			
		||||
    @users = @archive_file.get_users
 | 
			
		||||
	
 | 
			
		||||
	@tags = get_tags
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,6 +60,12 @@ class Panel::Archive::FrontEnd::ArchiveFilesController < OrbitWidgetController
 | 
			
		|||
    get_categorys
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def download
 | 
			
		||||
    file = ArchiveFileMultiple.find(params[:id])
 | 
			
		||||
    file.update_attribute(:download_count, file.download_count + 1)
 | 
			
		||||
    render text: 'OK'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  protected
 | 
			
		||||
 | 
			
		||||
  def reload_archive_files
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,11 +20,12 @@ class ArchiveFile
 | 
			
		|||
 | 
			
		||||
  field :create_user_id
 | 
			
		||||
  field :update_user_id
 | 
			
		||||
 | 
			
		||||
  field :is_top, :type => Boolean, :default => false
 | 
			
		||||
  field :is_hot, :type => Boolean, :default => false
 | 
			
		||||
  field :is_hidden, :type => Boolean, :default => false
 | 
			
		||||
 | 
			
		||||
  field :user_ids
 | 
			
		||||
  
 | 
			
		||||
  field :is_top, :type => Boolean, :default => false 
 | 
			
		||||
  field :is_hot, :type => Boolean, :default => false 
 | 
			
		||||
  field :is_hidden, :type => Boolean, :default => false 
 | 
			
		||||
  
 | 
			
		||||
  scope :can_display,where(is_hidden: false)
 | 
			
		||||
 | 
			
		||||
  # belongs_to :archive_file_category
 | 
			
		||||
| 
						 | 
				
			
			@ -85,4 +86,8 @@ class ArchiveFile
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def get_users
 | 
			
		||||
    User.find(self.user_ids) rescue []
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,7 @@ class ArchiveFileMultiple
 | 
			
		|||
  field :file_title, localize: true
 | 
			
		||||
  # field :description
 | 
			
		||||
  field :choose_lang, :type => Array, :default => nil
 | 
			
		||||
 | 
			
		||||
  field :download_count, type: Integer, default: 0
 | 
			
		||||
  field :should_destroy, :type => Boolean
 | 
			
		||||
 | 
			
		||||
  default_scope asc(:sort_number)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,8 +31,18 @@
 | 
			
		|||
				<%= tag.name %>
 | 
			
		||||
				<% end %>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
		</div>  
 | 
			
		||||
 | 
			
		||||
		<div id="widget-member" class="widget-box widget-size-300">
 | 
			
		||||
			<div class="widget-action clear tip" title="Rejected Report">
 | 
			
		||||
				<a class="action"><i class="icon-cog icon-white"></i></a>
 | 
			
		||||
			</div>
 | 
			
		||||
			<h3 class="widget-title"><i class="icons-tag"></i><%= t(:promoter) %></h3>
 | 
			
		||||
				<div class="widget-content clear form-horizontal">
 | 
			
		||||
					<%= render partial: 'admin/member_selects/selection_box', locals: {field: 'archive_file[user_ids][]', users: @users} %>
 | 
			
		||||
				</div>
 | 
			
		||||
		</div>
 | 
			
		||||
  
 | 
			
		||||
	</div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -86,12 +96,13 @@
 | 
			
		|||
							<th>File</th>
 | 
			
		||||
							<th>File Name</th>
 | 
			
		||||
							<th class="span2"><%= t('呈現語系')%></th>
 | 
			
		||||
							<th class="span2"><%= t('archive.download_count')%></th>
 | 
			
		||||
							<th class="span1"></th>
 | 
			
		||||
						</tr>
 | 
			
		||||
					</thead>
 | 
			
		||||
					<tfoot>
 | 
			
		||||
						<tr>
 | 
			
		||||
							<td style="text-align:center" colspan="4">
 | 
			
		||||
							<td style="text-align:center" colspan="6">
 | 
			
		||||
								<div id='add_archive_file_multiple' class="info_input archive_file_multiples_block">
 | 
			
		||||
									<%= hidden_field_tag 'archive_file_multiple_field_count', @archive_file.archive_file_multiples.count %>
 | 
			
		||||
									<a class="add"><span class="btn btn-primary btn-small"><i class="icon-plus icon-white"></i> ADD/新增</span></a>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@
 | 
			
		|||
      <td>
 | 
			
		||||
        <div class="control-group">
 | 
			
		||||
          <div class="controls">
 | 
			
		||||
            <%= f.text_field :sort_number %>
 | 
			
		||||
            <%= f.text_field :sort_number, class: 'input-mini' %>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </td>
 | 
			
		||||
| 
						 | 
				
			
			@ -47,18 +47,19 @@
 | 
			
		|||
				<% end %>
 | 
			
		||||
				<%= hidden_field_tag 'archive_file[archive_file_multiples_attributes][0][choose_lang][]', '' %>
 | 
			
		||||
			</td>
 | 
			
		||||
 | 
			
		||||
			<td>
 | 
			
		||||
			<span class="action">
 | 
			
		||||
			<% if form_file.new_record? %>
 | 
			
		||||
			  <a class="delete"><i class="icon-remove"></i></a>
 | 
			
		||||
			<% else %>
 | 
			
		||||
			  <%= f.hidden_field :id %>
 | 
			
		||||
			  <a class="remove_existing_record"><i class="icon-remove"></i></a>
 | 
			
		||||
			  <%= f.hidden_field :should_destroy, :value => nil, :class => 'should_destroy' %>
 | 
			
		||||
			<% end %>
 | 
			
		||||
			</span>
 | 
			
		||||
 | 
			
		||||
				<%= form_file.download_count %>
 | 
			
		||||
			</td>
 | 
			
		||||
			<td>
 | 
			
		||||
				<span class="action">
 | 
			
		||||
					<% if form_file.new_record? %>
 | 
			
		||||
					  <a class="delete"><i class="icon-remove"></i></a>
 | 
			
		||||
					<% else %>
 | 
			
		||||
					  <%= f.hidden_field :id %>
 | 
			
		||||
					  <a class="remove_existing_record"><i class="icon-remove"></i></a>
 | 
			
		||||
					  <%= f.hidden_field :should_destroy, :value => nil, :class => 'should_destroy' %>
 | 
			
		||||
					<% end %>
 | 
			
		||||
				</span>
 | 
			
		||||
			</td>
 | 
			
		||||
		</tr>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@
 | 
			
		|||
				<tr>
 | 
			
		||||
					<th class="column-ctrl col-title"><%= sortable(:title, t("archive.Title"))%></th>
 | 
			
		||||
					<th class="column-ctrl col-file"><%= t("archive.Files")%></th>
 | 
			
		||||
					<th class="column-ctrl col-category"><%= sortable(:archive_file_category, t("archive.Category"))%></th>
 | 
			
		||||
					<th class="column-ctrl col-file"><%= t(:promoter)%></th>
 | 
			
		||||
				</tr>
 | 
			
		||||
			</thead>
 | 
			
		||||
			<tbody>
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +23,7 @@
 | 
			
		|||
								<% post.archive_file_multiples.asc(:_id).each do | afile |  %>
 | 
			
		||||
									<%  if afile.file.file and afile.choose_lang_display(I18n.locale.to_s) %>
 | 
			
		||||
										<li>
 | 
			
		||||
											<%= link_to afile.file_title, afile.file.url, {:target => '_blank', :title => afile.file_title, :class => "o-archives-file"} %>
 | 
			
		||||
											<%= link_to afile.file_title, afile.file.url, {:target => '_blank', :title => afile.file_title, :class => "o-archives-file download_count", rel: download_panel_archive_front_end_archive_file_path(afile, inner: true)} %>
 | 
			
		||||
											<%= post.get_file_icon(afile.file.url) %>
 | 
			
		||||
										</li>
 | 
			
		||||
									<% end %>
 | 
			
		||||
| 
						 | 
				
			
			@ -32,9 +32,21 @@
 | 
			
		|||
							<% end %>
 | 
			
		||||
						</div>
 | 
			
		||||
					</td>
 | 
			
		||||
					<td><div class="o-archives-category">
 | 
			
		||||
						<%= post.archive_file_category.title %>
 | 
			
		||||
					</div></td>
 | 
			
		||||
					<td>
 | 
			
		||||
						<% unless post.get_users.blank? %>
 | 
			
		||||
							<div class="promoter-block">
 | 
			
		||||
						    <ul>
 | 
			
		||||
						      <% post.get_users.each do |user| %>
 | 
			
		||||
						        <li class="promoter">
 | 
			
		||||
						          <p>
 | 
			
		||||
						              <%= link_to user.name, "mailto:#{user.email}", class: "promoter-name" %> / <span class="promoter-phone"><%= user.office_tel %></span>
 | 
			
		||||
						          </p>
 | 
			
		||||
						        </li>
 | 
			
		||||
						      <% end %>
 | 
			
		||||
						    </ul>
 | 
			
		||||
						  </div>
 | 
			
		||||
					  <% end %>
 | 
			
		||||
					</td>
 | 
			
		||||
				</tr>
 | 
			
		||||
				<% end %>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -44,13 +56,10 @@
 | 
			
		|||
 | 
			
		||||
<%= paginate @archive_files, :param_name => :page_main, :params => {:inner => 'false'} %>
 | 
			
		||||
 | 
			
		||||
<%= stylesheet_link_tag "archive/archives" %>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
	$(document).ready(function(){
 | 
			
		||||
		$('.download_count').on('click', function(){
 | 
			
		||||
		  $.getScript($(this).attr('rel'));
 | 
			
		||||
		});
 | 
			
		||||
	});
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,12 +7,3 @@
 | 
			
		|||
</div>
 | 
			
		||||
 | 
			
		||||
<%= stylesheet_link_tag "archive/archives" %>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,4 +27,6 @@
 | 
			
		|||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<%= render partial: 'admin/member_selects/promoter_front', locals: {users: @archive_file.get_users} %>
 | 
			
		||||
 | 
			
		||||
<%= stylesheet_link_tag "archive/archives" %>
 | 
			
		||||
| 
						 | 
				
			
			@ -2,6 +2,7 @@ en:
 | 
			
		|||
 | 
			
		||||
  archive:
 | 
			
		||||
    archive: Archive
 | 
			
		||||
    download_count: Download count
 | 
			
		||||
    Title: Title
 | 
			
		||||
    Files: Files
 | 
			
		||||
    Category: Category
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@ zh_tw:
 | 
			
		|||
 | 
			
		||||
  archive:
 | 
			
		||||
    archive: 檔案室
 | 
			
		||||
    download_count: 下載次數
 | 
			
		||||
    Title: 標題
 | 
			
		||||
    Files: 檔案
 | 
			
		||||
    Category: 類別
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,11 @@ Rails.application.routes.draw do
 | 
			
		|||
      end
 | 
			
		||||
      namespace :front_end do
 | 
			
		||||
        match "archive_files" => "archive_files#index"
 | 
			
		||||
        resources :archive_files
 | 
			
		||||
        resources :archive_files do
 | 
			
		||||
          member do
 | 
			
		||||
            get 'download'
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      namespace :widget do
 | 
			
		||||
        match "index" => "archive_files#index"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,8 @@ class Panel::Ask::BackEnd::AskAcknowledgementsController < OrbitBackendControlle
 | 
			
		|||
  include AdminHelper
 | 
			
		||||
  include OrbitControllerLib::DivisionForDisable
 | 
			
		||||
 | 
			
		||||
  before_filter :for_app_manager
 | 
			
		||||
 | 
			
		||||
  def initialize
 | 
			
		||||
    super
 | 
			
		||||
    @app_title = 'ask_acknowledgement'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,8 @@ class Panel::Ask::BackEnd::AskAdminsController < OrbitBackendController
 | 
			
		|||
  include AdminHelper
 | 
			
		||||
  include OrbitControllerLib::DivisionForDisable
 | 
			
		||||
 | 
			
		||||
  before_filter :for_app_manager
 | 
			
		||||
 | 
			
		||||
  def initialize
 | 
			
		||||
    super
 | 
			
		||||
    @app_title = 'ask_admins'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,8 @@ class Panel::Ask::BackEnd::AskCategoriesController < OrbitBackendController
 | 
			
		|||
  include AdminHelper
 | 
			
		||||
  include OrbitControllerLib::DivisionForDisable
 | 
			
		||||
 | 
			
		||||
  before_filter :for_app_manager
 | 
			
		||||
 | 
			
		||||
  def initialize
 | 
			
		||||
    super
 | 
			
		||||
    @app_title = 'ask_categories'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,9 +5,11 @@ class Panel::Ask::BackEnd::AskQuestionsController < OrbitBackendController
 | 
			
		|||
  include AdminHelper
 | 
			
		||||
  include OrbitControllerLib::DivisionForDisable
 | 
			
		||||
 | 
			
		||||
  before_filter :for_app_manager
 | 
			
		||||
 | 
			
		||||
  def initialize
 | 
			
		||||
    super
 | 
			
		||||
    @app_title = 'ask_questions'
 | 
			
		||||
    @app_title = 'ask'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def index
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,8 @@ class Panel::Ask::BackEnd::AskRepliesController < OrbitBackendController
 | 
			
		|||
  include AdminHelper
 | 
			
		||||
  include OrbitControllerLib::DivisionForDisable
 | 
			
		||||
 | 
			
		||||
  before_filter :for_app_manager
 | 
			
		||||
 | 
			
		||||
  def initialize
 | 
			
		||||
    super
 | 
			
		||||
    @app_title = 'ask_replies'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,8 @@ class AskCategory
 | 
			
		|||
  include Mongoid::Document
 | 
			
		||||
  include Mongoid::Timestamps
 | 
			
		||||
  include OrbitCoreLib::ObjectDisable
 | 
			
		||||
 | 
			
		||||
  include OrbitCoreLib::ObjectAuthable
 | 
			
		||||
  
 | 
			
		||||
  field :name, localize: true
 | 
			
		||||
  field :key
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,26 +23,26 @@ module Ask
 | 
			
		|||
 | 
			
		||||
    side_bar do
 | 
			
		||||
      head_label_i18n 'ask.ask', icon_class: 'icons-light-bulb'
 | 
			
		||||
      available_for [:admin,:manager,:sub_manager]
 | 
			
		||||
      available_for [:admin]
 | 
			
		||||
      active_for_controllers({ private: ['ask_questions'] })
 | 
			
		||||
      head_link_path "panel_ask_back_end_ask_questions_path"
 | 
			
		||||
 | 
			
		||||
      context_link 'categories', link_path: 'panel_ask_back_end_ask_categories_path',
 | 
			
		||||
                               priority: 1,
 | 
			
		||||
                               active_for_action: {:ask_categories=>:index},
 | 
			
		||||
                               available_for: [:all]
 | 
			
		||||
                               available_for: [:manager]
 | 
			
		||||
 | 
			
		||||
      context_link 'ask.acknowledgement', link_path: 'panel_ask_back_end_ask_acknowledgements_path',
 | 
			
		||||
                               priority: 1,
 | 
			
		||||
                               available_for: [:all]
 | 
			
		||||
                               available_for: [:manager]
 | 
			
		||||
 | 
			
		||||
      context_link 'ask.admin', link_path: 'panel_ask_back_end_ask_admins_path',
 | 
			
		||||
                               priority: 1,
 | 
			
		||||
                               available_for: [:all]
 | 
			
		||||
                               available_for: [:manager]
 | 
			
		||||
 | 
			
		||||
      context_link 'ask.export', link_path: 'export_panel_ask_back_end_ask_questions_path',
 | 
			
		||||
                               priority: 1,
 | 
			
		||||
                               available_for: [:all]
 | 
			
		||||
                               available_for: [:manager]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -71,6 +71,7 @@ class Panel::Faq::BackEnd::QasController < OrbitBackendController
 | 
			
		|||
  # GET /qas/1/edit
 | 
			
		||||
  def edit
 | 
			
		||||
    @qa = Qa.find(params[:id])
 | 
			
		||||
    @users = @qa.get_users
 | 
			
		||||
	@tags = get_tags
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,7 @@ class Qa
 | 
			
		|||
 | 
			
		||||
  field :create_user_id
 | 
			
		||||
  field :update_user_id
 | 
			
		||||
  field :user_ids
 | 
			
		||||
  
 | 
			
		||||
  field :is_top, :type => Boolean, :default => false 
 | 
			
		||||
  field :is_hot, :type => Boolean, :default => false 
 | 
			
		||||
| 
						 | 
				
			
			@ -72,6 +73,10 @@ class Qa
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def get_users
 | 
			
		||||
    User.find(self.user_ids) rescue []
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  protected
 | 
			
		||||
 | 
			
		||||
  def qa_category_with_title
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,6 +45,16 @@
 | 
			
		|||
				<% end %>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>  
 | 
			
		||||
 | 
			
		||||
		<div id="widget-member" class="widget-box widget-size-300">
 | 
			
		||||
			<div class="widget-action clear tip" title="Rejected Report">
 | 
			
		||||
				<a class="action"><i class="icon-cog icon-white"></i></a>
 | 
			
		||||
			</div>
 | 
			
		||||
			<h3 class="widget-title"><i class="icons-tag"></i><%= t(:promoter) %></h3>
 | 
			
		||||
				<div class="widget-content clear form-horizontal">
 | 
			
		||||
					<%= render partial: 'admin/member_selects/selection_box', locals: {field: 'qa[user_ids][]', users: @users} %>
 | 
			
		||||
				</div>
 | 
			
		||||
		</div>
 | 
			
		||||
  
 | 
			
		||||
	</div>
 | 
			
		||||
  
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,25 +8,30 @@
 | 
			
		|||
<div class="news_paragraph">
 | 
			
		||||
	<%= @qa.answer.html_safe rescue '' %>
 | 
			
		||||
</div>
 | 
			
		||||
<div class="linkAndFile">
 | 
			
		||||
	<% if @qa.qa_links.size > 0 %>
 | 
			
		||||
		<div>
 | 
			
		||||
			<i class="icons-link"></i>
 | 
			
		||||
			<div class="showLink">
 | 
			
		||||
				<% @qa.qa_links.each do | blink | %>
 | 
			
		||||
			    <%= link_to blink.title, blink.url, :target => '_blank' %>
 | 
			
		||||
				<% end %>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
	<% end %>
 | 
			
		||||
	<% if @qa.qa_files.size > 0 %>
 | 
			
		||||
		<div>
 | 
			
		||||
			<i class="icons-paperclip"></i>
 | 
			
		||||
			<div class="showFile">
 | 
			
		||||
					<% @qa.qa_files.each do | bfile | %>
 | 
			
		||||
					<%= link_to bfile.title, bfile.file.url, {:target => '_blank', :title => bfile.description} if bfile.file.file %>
 | 
			
		||||
 | 
			
		||||
<% if @qa.qa_links.size > 0 || @qa.qa_files.size > 0 %>
 | 
			
		||||
	<div class="linkAndFile">
 | 
			
		||||
		<% if @qa.qa_links.size > 0 %>
 | 
			
		||||
			<div>
 | 
			
		||||
				<i class="icons-link"></i>
 | 
			
		||||
				<div class="showLink">
 | 
			
		||||
					<% @qa.qa_links.each do | blink | %>
 | 
			
		||||
				    <%= link_to blink.title, blink.url, :target => '_blank' %>
 | 
			
		||||
					<% end %>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
	<% end %>
 | 
			
		||||
</div>
 | 
			
		||||
		<% end %>
 | 
			
		||||
		<% if @qa.qa_files.size > 0 %>
 | 
			
		||||
			<div>
 | 
			
		||||
				<i class="icons-paperclip"></i>
 | 
			
		||||
				<div class="showFile">
 | 
			
		||||
						<% @qa.qa_files.each do | bfile | %>
 | 
			
		||||
						<%= link_to bfile.title, bfile.file.url, {:target => '_blank', :title => bfile.description} if bfile.file.file %>
 | 
			
		||||
						<% end %>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		<% end %>
 | 
			
		||||
	</div>
 | 
			
		||||
<% end %>
 | 
			
		||||
 | 
			
		||||
<%= render partial: 'admin/member_selects/promoter_front', locals: {users: @qa.get_users} %>
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +53,7 @@ class Panel::PageContent::BackEnd::PageContextsController < OrbitBackendControll
 | 
			
		|||
  # GET /page_contexts/1/edit
 | 
			
		||||
  def edit
 | 
			
		||||
    @page_context = PageContext.find(params[:id])
 | 
			
		||||
    @users = @page_context.get_users
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # POST /page_contexts
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@ class PageContext
 | 
			
		|||
  
 | 
			
		||||
  field :archived, :type => Boolean, :default => false
 | 
			
		||||
  # field :current, :type => Boolean, :default => false
 | 
			
		||||
  field :user_ids
 | 
			
		||||
  
 | 
			
		||||
  belongs_to :page
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -32,5 +33,9 @@ class PageContext
 | 
			
		|||
  def is_top?
 | 
			
		||||
    self.is_top
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def get_users
 | 
			
		||||
    User.find(self.user_ids) rescue []
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -2,6 +2,22 @@
 | 
			
		|||
 | 
			
		||||
<%= f.error_messages %>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<div id="sub-wiget"> 
 | 
			
		||||
 | 
			
		||||
	<div id="widget-member" class="widget-box widget-size-300">
 | 
			
		||||
		<div class="widget-action clear tip" title="Rejected Report">
 | 
			
		||||
			<a class="action"><i class="icon-cog icon-white"></i></a>
 | 
			
		||||
		</div>
 | 
			
		||||
		<h3 class="widget-title"><i class="icons-tag"></i><%= t(:promoter) %></h3>
 | 
			
		||||
			<div class="widget-content clear form-horizontal">
 | 
			
		||||
				<%= render partial: 'admin/member_selects/selection_box', locals: {field: 'page_context[user_ids][]', users: @users} %>
 | 
			
		||||
			</div>
 | 
			
		||||
	</div>
 | 
			
		||||
  
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<div id="post-body">
 | 
			
		||||
	<div id="post-body-content">
 | 
			
		||||
		<div class="title">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,3 +9,4 @@
 | 
			
		|||
<div class="page_content"><%= @page_context.context.html_safe rescue '' %></div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<%= render partial: 'admin/member_selects/promoter_front', locals: {users: @page_context.get_users} %>
 | 
			
		||||
		Loading…
	
		Reference in New Issue