Compare commits
4 Commits
master
...
0913_ntu_g
Author | SHA1 | Date |
---|---|---|
Spen | f9485c1f86 | |
chris | cd26b880fb | |
chris | 7c398ce4fe | |
chris | d766eea9f4 |
|
@ -4,6 +4,8 @@
|
|||
.rvmrc
|
||||
|
||||
Gemfile.lock
|
||||
Procfile
|
||||
log/*
|
||||
|
||||
db/*.sqlite3
|
||||
log/*.log
|
||||
|
|
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.0 KiB |
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,23 +9,18 @@ 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",
|
||||
theme_advanced_resizing : true,
|
||||
|
||||
// Domain Absolute URLs
|
||||
relative_urls : false,
|
||||
remove_script_host : false,
|
||||
document_base_url: window.location.protocol + '//' + window.location.host,
|
||||
|
||||
// Skin options
|
||||
skin : "o2k7",
|
||||
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
|
||||
|
|
|
@ -43,7 +43,7 @@ class MobileController < ApplicationController
|
|||
|
||||
def page
|
||||
@page_title = t('mobile.page')
|
||||
@page_contexts = get_sorted_page_from_structure
|
||||
@page_contexts = PageContext.where(:archived => false).page(params[:page_main]).per(15)
|
||||
end
|
||||
|
||||
def page_content
|
||||
|
@ -57,12 +57,4 @@ class MobileController < ApplicationController
|
|||
@no_footer = true if request.path =~ /app/
|
||||
end
|
||||
|
||||
def get_sorted_page_from_structure
|
||||
page_contexts = Item.structure_ordered_items.inject([]){ |pages, page|
|
||||
pages << page.page_contexts.where(archived: false).limit(1)[0] if page.is_a?(Page) && !page.page_contexts.blank?
|
||||
pages
|
||||
}
|
||||
Kaminari.paginate_array(page_contexts).page(params[:page]).per(15)
|
||||
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');
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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,7 +9,7 @@ namespace :web_link_url do
|
|||
|
||||
@weblinks.each do |wl|
|
||||
|
||||
if wl.url.nil?
|
||||
if wl.url_translations.is_a?(String)
|
||||
|
||||
@wlurl = wl.url_translations
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
||||
|
|
|
@ -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} %>
|
||||
|
|
|
@ -134,3 +134,27 @@ 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,6 +20,7 @@ class ArchiveFile
|
|||
|
||||
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
|
||||
|
@ -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)
|
||||
|
|
|
@ -33,6 +33,16 @@
|
|||
</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,7 +47,9 @@
|
|||
<% end %>
|
||||
<%= hidden_field_tag 'archive_file[archive_file_multiples_attributes][0][choose_lang][]', '' %>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<%= form_file.download_count %>
|
||||
</td>
|
||||
<td>
|
||||
<span class="action">
|
||||
<% if form_file.new_record? %>
|
||||
|
@ -58,7 +60,6 @@
|
|||
<%= 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,6 +2,7 @@ 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
|
||||
|
|
|
@ -46,6 +46,16 @@
|
|||
</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,7 +8,9 @@
|
|||
<div class="news_paragraph">
|
||||
<%= @qa.answer.html_safe rescue '' %>
|
||||
</div>
|
||||
<div class="linkAndFile">
|
||||
|
||||
<% 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>
|
||||
|
@ -29,4 +31,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render partial: 'admin/member_selects/promoter_front', locals: {users: @qa.get_users} %>
|
Before Width: | Height: | Size: 12 KiB |
|
@ -9,40 +9,17 @@ class Panel::Gallery::Widget::AlbumsController < OrbitWidgetController
|
|||
@album = GalleryAlbum.find(@part.widget_options['album_id']) rescue nil
|
||||
@album_images = @album.gallery_images if @album
|
||||
|
||||
|
||||
@settings = {"vertical"=>vertical,"horizontal"=>horizontal} #[note] horizontal has it's limitation from 2 to 6
|
||||
@class = "c" + @settings["horizontal"].to_s
|
||||
@total = @settings["vertical"] * @settings["horizontal"]
|
||||
@rnd = Random.new
|
||||
@images = []
|
||||
|
||||
if @album_images.count > @total
|
||||
@randoms = []
|
||||
until @randoms.count == @total do
|
||||
r = @rnd.rand(0...@album_images.count)
|
||||
if !@randoms.include?r
|
||||
@randoms << r
|
||||
image = @album_images[r]
|
||||
for i in 0..@total-1
|
||||
image = @album_images[@rnd.rand(0...@album_images.count)]
|
||||
values = {"show_link"=>theater_panel_gallery_front_end_album_path(image),"thumb"=>image.file.thumb.url}
|
||||
@images << values
|
||||
end
|
||||
end
|
||||
elsif @album_images.count == @total
|
||||
@album_images.each do |image|
|
||||
values = {"show_link"=>theater_panel_gallery_front_end_album_path(image),"thumb"=>image.file.thumb.url}
|
||||
@images << values
|
||||
end
|
||||
else
|
||||
@album_images.each do |image|
|
||||
values = {"show_link"=>theater_panel_gallery_front_end_album_path(image),"thumb"=>image.file.thumb.url}
|
||||
@images << values
|
||||
end
|
||||
until @images.count == @total do
|
||||
values = {"show_link"=>"javascript:void(0);","thumb"=>"assets/gallery/nodata.jpg"}
|
||||
@images << values
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def widget2
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -33,4 +34,8 @@ class PageContext
|
|||
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} %>
|