Compare commits

...

78 Commits

Author SHA1 Message Date
Spen 4034fb20ee add archive frontend table class 2013-11-18 16:38:06 +08:00
Spen d1fd2b6984 fix app sub manager and ask verification code 2013-11-07 18:06:16 +08:00
Spen 8f25dc2871 fix ntu ga survey export 2013-11-04 10:00:54 +08:00
thomaschen 82988a2029 Fix front-end tag cloud search under category filters 2013-11-01 16:22:08 +08:00
thomaschen e5fccb33bf Fix tag cloud search under category filters 2013-11-01 15:38:49 +08:00
thomaschen d832f4c4b1 can read the spreadsheet each row.(need to think of a method to parse each row to figure)
Conflicts:

	Gemfile
	vendor/built_in_modules/survey/app/controllers/panel/survey/back_end/surveys_controller.rb
2013-10-25 18:36:32 +08:00
thomaschen 59af75e50a fix error 2013-10-25 18:21:17 +08:00
Bernie Chiu 67cd34ab27 Add oneline and multiline import 2013-10-25 18:21:17 +08:00
thomaschen 4a736cc92c error fix 2013-10-25 18:21:17 +08:00
Bernie Chiu 9b96f2eeb0 Merge
Conflicts:

	vendor/built_in_modules/survey/app/controllers/panel/survey/back_end/surveys_controller.rb
2013-10-25 18:21:07 +08:00
Bernie Chiu 74b89f1fac Allow update answers on radio groups
Conflicts:

	vendor/built_in_modules/survey/app/controllers/panel/survey/back_end/surveys_controller.rb
2013-10-25 18:09:55 +08:00
thomaschen 62e9acdbb8 fix error 2013-10-25 18:05:37 +08:00
thomaschen 4a897b68cf merge 2013-10-25 18:05:37 +08:00
Bernie Chiu d3fc6e5956 Add import on radiogroups on file change 2013-10-25 18:05:37 +08:00
Bernie Chiu 71acee200c Fix encoding issue and add import on title change 2013-10-25 18:05:37 +08:00
thomaschen 63156c7a95 remove unuse variable and comment 2013-10-25 18:05:37 +08:00
thomaschen 5156701094 import 'check' and 'select' question success 2013-10-25 18:05:37 +08:00
thomaschen 1266cd1384 fix import-csv column error 2013-10-25 18:05:37 +08:00
thomaschen f3f4dc842c import radio question success
Conflicts:

	Gemfile
	vendor/built_in_modules/survey/app/controllers/panel/survey/back_end/surveys_controller.rb
2013-10-25 17:56:49 +08:00
Spen 13144f62fb add ntu_ga survey init sorting 2013-10-18 18:17:05 +08:00
Bernie Chiu 6d951f8d9c Add correct department links 2013-10-18 16:20:13 +08:00
Bernie Chiu d0364c788b Fix locale error 2013-10-17 18:23:33 +08:00
Bernie Chiu e2ec8f134e Add routing and links for import 2013-10-17 18:23:17 +08:00
Bernie Chiu 83a8433e52 Fix survey title link redirection after deadline 2013-10-17 18:22:54 +08:00
thomaschen 8f65da0a04 fix js hide localsite error 2013-10-17 18:22:41 +08:00
thomaschen ad8bb72b07 fix uri parse problem 2013-10-17 18:22:11 +08:00
Manson Wang 06a8b9073e Merge branch '0913_ntu_ga_co' of github.com:Rulingcom/orbit into 0913_ntu_ga 2013-10-17 18:21:41 +08:00
Spen f9485c1f86 announcement init sorting fix
Conflicts:

	vendor/built_in_modules/announcement/init.rb
2013-10-11 18:00:39 +08:00
Bernie Chiu 627425b72e Add port to test 2013-10-08 17:51:40 +08:00
Bernie Chiu 9cb2a5b211 Update values to test servers 2013-10-08 17:41:22 +08:00
Bernie Chiu 75f5404b7a Modify value to test servers 2013-10-08 17:36:03 +08:00
Bernie Chiu bd3a922073 Add local test server 2013-10-08 16:06:36 +08:00
Bernie Chiu 9fbb2917b1 Widget title without link 2013-10-08 12:24:34 +08:00
Bernie Chiu bd6d94a143 Comment out JavaScript redirect workaround 2013-10-04 17:48:58 +08:00
Bernie Chiu 8684388ab9 Reverse 2013-10-04 17:47:26 +08:00
thomaschen 5e05f5d02b Merge branch '0913_ntu_ga_co' of https://github.com/Rulingcom/orbit into 0913_ntu_ga_co 2013-10-04 17:22:33 +08:00
thomaschen 6607f6b66e roll back 2013-10-04 17:22:02 +08:00
Bernie Chiu 63fab74a25 Post form without ajax 2013-10-04 15:57:14 +08:00
Bernie Chiu 48969b70b5 Modify thank_you route 2013-10-04 14:08:18 +08:00
Bernie Chiu 88c8ca68d0 Add ask fail message and success redirect fix 2013-10-01 16:09:43 +08:00
Bernie Chiu 3eeda5410c Fix bugs 2013-09-27 17:15:49 +08:00
thomaschen 660960f316 fix first reply error 2013-09-27 17:03:09 +08:00
Bernie Chiu 696134aa18 Fix ip direct 2013-09-27 16:40:34 +08:00
Bernie Chiu 2777b92589 Test ip direct 2013-09-27 16:30:36 +08:00
thomaschen 5432238816 merge 2013-09-27 15:07:19 +08:00
thomaschen 4e12c0bb5b (test)remote ip 2013-09-27 15:04:35 +08:00
Bernie Chiu d68f324ca3 Merge 2013-09-27 14:46:18 +08:00
thomaschen 50f5d12da3 fix status error 2013-09-27 14:35:25 +08:00
thomaschen d635c892cf fix dns error 2013-09-27 11:22:37 +08:00
Bernie Chiu 26bc837c76 Modify fail definition 2013-09-25 17:53:35 +08:00
Bernie Chiu 8247f077df Change status based on your requests sent 2013-09-25 17:46:32 +08:00
Bernie Chiu 70de1cea9d Modify syntax 2013-09-25 14:55:02 +08:00
Bernie Chiu 0f18cdfe8e Skip invalid options 2013-09-25 14:46:55 +08:00
thomaschen 0d1426cab8 add post request error checking and resend one more time 2013-09-23 12:46:59 +08:00
thomaschen b57b899dba fix naming error 2013-09-23 11:28:30 +08:00
Bernie Chiu 1305b9f1ef Rescue URI Error 2013-09-17 16:37:38 +08:00
Bernie Chiu 21009961ef Fix status bugs 2013-09-17 16:16:37 +08:00
Bernie Chiu 1edc134691 Add back mongoid yml 2013-09-17 12:07:41 +08:00
Bernie Chiu e89615a6f3 Fix naming error 2013-09-17 12:02:35 +08:00
thomaschen 0c29701f9b test 2013-09-16 15:07:50 +08:00
thomaschen 580be0b34b fix frontend ask_category error 2013-09-16 15:05:08 +08:00
Bernie Chiu c361a7a201 Fix check box selections appearance
Conflicts:
	vendor/built_in_modules/ask_new/app/controllers/panel/ask/back_end/ask_replies_controller.rb
2013-09-13 15:43:14 +08:00
thomaschen b7bf180df2 fix frontend ask_category error 2013-09-13 15:43:14 +08:00
Bernie Chiu 71dad22b04 Add dynamic checkboxes
Conflicts:
	vendor/built_in_modules/ask_new/app/views/panel/ask/back_end/ask_questions/edit.html.erb
2013-09-13 15:43:14 +08:00
thomaschen 883496ede1 add multi deliver request 2013-09-13 15:43:14 +08:00
Bernie Chiu 0a1ebf18e3 Add check box array 2013-09-13 15:43:13 +08:00
thomaschen 3f9cdec426 add option for dep_dns 2013-09-13 15:43:13 +08:00
thomaschen 24b9f4015b add checkboxes for 11 dep in edit view 2013-09-13 15:43:13 +08:00
thomaschen 1237a111ca add transfered_category if not exist. change transfered reply's status to 待處理(轉). showing request code if error. 2013-09-13 15:43:13 +08:00
Bernie Chiu 64e14d42e2 Allow ask_question transter 2013-09-13 15:43:13 +08:00
thomaschen cc7a4ffb6d add response(temp) 2013-09-13 15:43:13 +08:00
Bernie Chiu da40c2b669 Allow sending request and getting response 2013-09-13 15:43:13 +08:00
thomaschen bf5416095e add auth_request route and controller 2013-09-13 15:43:13 +08:00
Bernie Chiu 8cd27e26e2 Fixed untracked files
Conflicts:
	config/mongoid.yml
2013-09-13 15:43:13 +08:00
thomaschen d98d008806 add sending post request function 2013-09-13 15:43:13 +08:00
chris cd26b880fb Change the logo and favicon 2013-09-13 15:42:52 +08:00
chris 7c398ce4fe Changes for NTU General Affairs 2013-09-13 15:10:27 +08:00
chris d766eea9f4 Changes for NTU common
Conflicts:
	lib/tasks/migrate.rake

Conflicts:
	lib/tasks/migrate.rake

Conflicts:
	config/resque_schedule.yml
	lib/tasks/migrate.rake
2013-09-13 15:10:10 +08:00
138 changed files with 46205 additions and 162 deletions

2
.gitignore vendored
View File

@ -4,6 +4,8 @@
.rvmrc
Gemfile.lock
Procfile
log/*
db/*.sqlite3
log/*.log

View File

@ -29,6 +29,9 @@ gem 'mongoid-tree', :require => 'mongoid/tree'
gem "mongo_session_store-rails3", '3.0.6'
gem 'nokogiri'
# import csv
gem 'roo'
gem 'fb_graph'
gem 'rack-gridfs'
gem 'radius'

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -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"]'),
});
});

View File

@ -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);

View File

@ -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();
});
});

View File

@ -9,7 +9,7 @@ function load_tinymce() {
// Theme options
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,formatselect,fontselect,fontsizeselect",
theme_advanced_buttons2 : "cut,copy,paste,pastetext,pasteword,|,bullist,numlist,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,forecolor,backcolor",
theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,fullscreen",
theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,fullscreen,|,template",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
theme_advanced_statusbar_location : "bottom",
@ -20,7 +20,7 @@ function load_tinymce() {
skin_variant : "silver",
font_size_style_values : "xx-small,x-small,small,medium,large,x-large,xx-large",
// Drop lists for link/image/media/template dialogs
template_external_list_url : "js/template_list.js",
template_external_list_url : "/tinymce/lists/template_list.js",
// external_link_list_url : "js/link_list.js",
// external_image_list_url : "js/image_list.js",
// media_external_list_url : "js/media_list.js"

View File

@ -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;
}*/

View File

@ -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;

View File

@ -1,5 +1,7 @@
/*style*/
* {
outline: none;
}
@font-face{
font-family: 'WebSymbolsRegular';
src: url(<%= asset_path 'websymbols-regular-webfont.eot' %>);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 = {})

View File

@ -0,0 +1,7 @@
class GetAnnouncementFromRss
@queue = :high
def self.perform()
%x(ruby "#{Rails.root}/lib/rss_ntu_job.rb")
end
end

View File

@ -15,8 +15,13 @@ class ObjectAuth < PrototypeAuth
end
def check_user_has_can_access_app
sub_managing_users = auth_obj.module_app.sub_managing_users rescue []
module_app = auth_obj.module_app
if auth_obj["_type"] == "PageContext"
module_app = ModuleApp.where(:key=>'page_content').first
sub_managing_users = module_app.sub_managing_users rescue []
else
sub_managing_users = auth_obj.module_app.sub_managing_users rescue []
module_app = auth_obj.module_app
end
self.auth_users.each do |auth_user|
if !sub_managing_users.include? auth_user && !auth_user.admin?
module_app.assign_sub_manager(auth_user,User.current)

View File

@ -55,6 +55,16 @@ class PrototypeAuth
if (self.send item).include? obj.id
(self.send item).delete obj.id
self.save!
if auth_obj["_type"] == "PageContext"
module_app = ModuleApp.where(:key=>'page_content').first
else
module_app = auth_obj.module_app
end
module_app.remove_sub_manager(obj)
module_app.save
else
false #should put error message for user not existed in list
end

View File

@ -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

View File

@ -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">&times;</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>

View File

@ -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 %>

View File

@ -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>

View File

@ -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>

View File

@ -0,0 +1,2 @@
$("#select_user").html("<%= j render partial: 'admin/member_selects/modal_select', locals: {field: 'bulletin[user_ids][]'} %>");
$("#select_user_modal").modal();

View File

@ -0,0 +1,2 @@
$("#selected_users").append("<%= j render partial: 'user', collection: @users, locals: {field: @field} %>");
$("#select_user_modal").modal('hide');

View File

@ -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>

View File

@ -10,19 +10,10 @@
</div>
<ul class="nav">
<li><a href="<%= root_path %>" data-icons="&#xe022;"></a></li>
<li><a href="<%= desktop_path %>" data-icons="&#xe060;"></a></li>
<!-- <li><a href="<%#= desktop_path %>" data-icons="&#xe060;"></a></li> -->
</ul>
<ul class="nav pull-right">
<!--
<li class="dropdown">
<a class="dropdown-toggle" data-icons="&#xe02d;" 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="&#xe024;"></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="&#xe02d;" 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="&#xe054;"></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="&#xe076;"></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>

View File

@ -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" %>

View File

@ -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]-->

View File

@ -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" %>

View File

@ -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" %>

View File

@ -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>

View File

@ -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>

View File

@ -335,6 +335,7 @@ en:
posted_by: Posted by
preview: Preview
profile: Profile
promoter: Promoter
publications: Publications
purchase: Purchase
quantity: Quantity

View File

@ -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

View File

@ -9,5 +9,5 @@ zh_tw:
home: 首頁
language: 語言
location: 地理位置
location_description: '<h3>本大學</h3>302新竹縣竹北市嘉豐南路二段101號'
location_description: '<h3>臺灣大學總務處 版權所有</h3>10617 臺北市大安區羅斯福路四段一號'
page: 頁面

17
config/locales/ntu.en.yml Normal file
View File

@ -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"

View File

@ -0,0 +1,17 @@
zh_tw:
ntu:
rss_origin: 回臺大校園公佈欄
site_names:
"www": "總務處"
"sec": "總務長室暨總務處秘書室"
"doc": "文書組"
"general": "事務組"
"property": "保管組"
"construction": "營繕組"
"cashier": "出納組"
"procurement": "採購組"
"fss": "經營管理組"
"police": "駐警隊"
"social": "社科院總務分處"
"medicine": "醫學院總務分處"

View File

@ -336,6 +336,7 @@ zh_tw:
posted_by: 張貼人
preview: 預覽
profile: 基本資料
promoter: 承辦人
publications: 著作
purchase: 購買
quantity: 數量

View File

@ -12,7 +12,6 @@ development:
test:
<<: *defaults
database: test_site
# set these environment variables on your prod server
production:
# host: <%= ENV['MONGOID_HOST'] %>
@ -21,4 +20,4 @@ production:
# password: <%= ENV['MONGOID_PASSWORD'] %>
# database: <%= ENV['MONGOID_DATABASE'] %>
<<: *defaults
database: test_site
database: production_8

View File

@ -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

View File

@ -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'

View File

@ -0,0 +1,144 @@
# encoding : utf-8
# Usage ===============
#
# ARGV[0] = folder path of xml files
# ARGV[1] = folder path of files
#
#======================
require 'mongo'
require 'nokogiri'
include Mongo
CSV_PATH = ARGV[0]
FILE_PATH = ARGV[1]
FIELDS = %w[title file createdate modifydate createuser modifyuser]
DB_BASE_NAME = "production"
TABLE = {
"0" => ["gaTaco", "ntuga"],
"1" => ["fdLai", "fdhome"],
"5" => ["prLin", "property01"],
"3" => ["gsTien", "ckh", "general01", "lynn"],
"10" => ["cmChen", "construction01", "allen", "enAmeliaxu", "energy"],
# "2" => ["caLin", "cashier01"],
"6" => ["pcAmyok", "purchasing01", "purchasing02"],
"7" => ["fmHsyu", "ntufss"],
"4" => ["soChang", "social01"],
"8" => ["meJune", "medicine01"],
"9" => ["plKoa", "police"]
}
which_site = {}
data = []
Dir.foreach(ARGV[0]) do |file|
if file =~ /\w\.\w/
doc = Nokogiri::XML(File.open(File.join(ARGV[0], file)))
doc.xpath("//row").each { |row|
xml_fields = row.children.map{ |row| [row.name, row.content] }
fields = FIELDS.inject([]) do |fields, field|
xml_fields.each do |xf|
if xf[0].include?(field)
fields << xf[1]
break
end
end
fields
end
data << fields + [File.basename(file, '.xml')]
}
data.each do |d|
title, file, c_time, m_time, creator, modifier, category = d
if file =~ /\w\.\w/
file = File.join(File.join(ARGV[1], file))
site = ""
TABLE.each do |key, value|
if value.include? modifier
site = key
break
elsif value.include? creator
site = key
break
end
end
site = "0" if site.empty?
if which_site[site]
if which_site[site][category]
which_site[site][category] += [[title, file, c_time, m_time]]
else
which_site[site][category] = [[title, file, c_time, m_time]]
end
else
which_site[site] = {category => [[title, file, c_time, m_time]]}
end
end
end
end
end
def save_category archive_file_category, in_category
category = {
title: {"zh_tw" => in_category, "en" => in_category},
key: "import_#{category}"
}
archive_file_category.save(category)
end
def save_file_multiples archive_file_multiples, grid ,archive_id,title, file, c_time, m_time
a_file = File.open(file) rescue nil
if a_file
filename = File.basename(file)
archive_file = {
file_title: {"zh_tw" => title, "en" => title },
choose_lang: ["zh_tw", "en"],
file: filename,
archive_file_id: archive_id,
created_at: c_time,
updated_at: m_time
}
a_file_id = archive_file_multiples.save(archive_file)
grid.put(a_file, filename: "assets/archive_file_multiple/file/#{a_file_id}/#{filename}")
end
end
def save_archive archive_files, category_id
archive = {
title: {"zh_tw" => " ", "en" => " "},
archive_file_category_id: category_id,
is_top: false,
is_hot: false,
is_hidden: false,
created_at: c_time,
updated_at: m_time
}
archive_files.save(archive)
end
which_site.each do |site, categories|
db = MongoClient.new("localhost", 27017).db("#{DB_BASE_NAME}_#{site}")
categories.each do |category, data|
archive_file_category = db.collection('archive_file_categories')
category_id = save_category archive_file_category, category
archive_files = db.collection('archive_files')
archive_id = save_archive archive_files, category_id
grid = Grid.new(db)
archive_file_multiples = db.collection('archive_file_multiples')
file_ids = []
data.each do |file|
save_file_multiples(archive_file_multiples, grid ,archive_id , *file)
end
end
end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

35
lib/rss_ntu_0_to_11.rb Normal file
View File

@ -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

129
lib/rss_ntu_job.rb Normal file
View File

@ -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

113
lib/rss_ntu_migration.rb Normal file
View File

@ -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

View File

@ -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|

View File

@ -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

View File

@ -9,17 +9,17 @@ namespace :web_link_url do
@weblinks.each do |wl|
if wl.url.nil?
if wl.url_translations.is_a?(String)
@wlurl = wl.url_translations
@wlurl = wl.url_translations
wl.url_translations = {}
wl.url_translations = {}
wl.url_translations["zh_tw"] = @wlurl
wl.url_translations["zh_tw"] = @wlurl
wl.url_translations["en"] = @wlurl
wl.url_translations["en"] = @wlurl
wl.save
wl.save
else
puts 'no data'

View File

@ -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."]
];

View File

@ -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>

View File

@ -0,0 +1 @@
This is just some <strong>code</strong>.

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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} %>

View File

@ -29,8 +29,8 @@ module Announcement
widgets do
default_widget do
sorting 'desc(:postdate)'
query 'Bulletin.available_for_lang(I18n.locale).any_of( {deadline: nil,:postdate.lte => Time.now} , {:deadline.gte => Time.now,:postdate.lte => Time.now} )'
sorting 'desc(:is_top, :postdate)'
query 'Bulletin.can_display.available_for_lang(I18n.locale).any_of( {deadline: nil,:postdate.lte => Time.now} , {:deadline.gte => Time.now,:postdate.lte => Time.now} )'
enable ["typeA","typeB_style3","typeC"]
image :image
field :postdate

View File

@ -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;
}

View File

@ -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

View File

@ -31,18 +31,29 @@ class Panel::Archive::FrontEnd::ArchiveFilesController < OrbitWidgetController
@archive_file_categorys = ArchiveFileCategory.all
# @archive_files = ArchiveFile.where( :is_hidden => false ).desc(:is_top).page(params[:page]).per(@page_num)
# if !params[:category_id].blank? && !params[:tag_id].blank?
# @archive_files = @archive_files.default_sort(params[:sort]).can_display.where(:archive_file_category_id.in => params[:category_id], :tagged_ids.in => params[:tag_id]).desc( :is_top ).page( params[:page_main] ).per(@page_num)
# @current_category = ArchiveFileCategory.from_id(params[:category_id]) rescue nil
# elsif !params[:category_id].blank?
# @archive_files = ArchiveFile.default_sort(params[:sort]).can_display.where(:archive_file_category_id.in => params[:category_id]).desc( :is_top ).page( params[:page_main] ).per(@page_num)
# @current_category = ArchiveFileCategory.from_id(params[:category_id]) rescue nil
# elsif !params[:tag_id].blank?
# @archive_files = ArchiveFile.default_sort(params[:sort]).can_display.where(:tagged_ids.in => params[:tag_id]).desc( :is_top ).page( params[:page_main] ).per(@page_num)
# else
# @archive_files = ArchiveFile.default_sort(params[:sort]).can_display.desc( :is_top ).page( params[:page_main] ).per(@page_num)
# end
if !params[:category_id].blank? && !params[:tag_id].blank?
@archive_files = @archive_files.default_sort(params[:sort]).can_display.where(:archive_file_category_id.in => params[:category_id], :tagged_ids.in => params[:tag_id]).desc( :is_top ).page( params[:page_main] ).per(@page_num)
@current_category = ArchiveFileCategory.from_id(params[:category_id]) rescue nil
@archive_files = ArchiveFile.default_sort(params[:sort]).all.can_display.where(:tagged_ids.in => params[:tag_id]).any_in(:archive_file_category_id => params[:category_id]).merge(ArchiveFileCategory.excludes('disable' => true)).desc( :is_top ).page( params[:page_main] ).per(@page_num)
@current_category = ArchiveFileCategory.any_in(:_id => params[:category_id]).excludes('disable' => true)
elsif !params[:category_id].blank?
@archive_files = ArchiveFile.default_sort(params[:sort]).can_display.where(:archive_file_category_id.in => params[:category_id]).desc( :is_top ).page( params[:page_main] ).per(@page_num)
@current_category = ArchiveFileCategory.from_id(params[:category_id]) rescue nil
@archive_files = ArchiveFile.default_sort(params[:sort]).all.can_display.any_in(:archive_file_category_id => params[:category_id]).merge(ArchiveFileCategory.excludes('disable' => true)).desc( :is_top ).page( params[:page_main] ).per(@page_num)
@current_category = ArchiveFileCategory.any_in(:_id => params[:category_id]).excludes('disable' => true)
elsif !params[:tag_id].blank?
@archive_files = ArchiveFile.default_sort(params[:sort]).can_display.where(:tagged_ids.in => params[:tag_id]).desc( :is_top ).page( params[:page_main] ).per(@page_num)
@archive_files = ArchiveFile.default_sort(params[:sort]).all.can_display.any_in(:tagged_ids => params[:tag_id]).merge(ArchiveFileCategory.excludes('disable' => true)).desc( :is_top ).page( params[:page_main] ).per(@page_num)
else
@archive_files = ArchiveFile.default_sort(params[:sort]).can_display.desc( :is_top ).page( params[:page_main] ).per(@page_num)
@archive_files = ArchiveFile.default_sort(params[:sort]).all.can_display.merge(ArchiveFileCategory.excludes('disable' => true)).desc( :is_top).page( params[:page_main] ).per(@page_num)
end
@ -60,6 +71,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

View File

@ -27,8 +27,10 @@ class Panel::Archive::Widget::ArchiveFilesController < OrbitWidgetController
@category_id = @part.category
date_now = Time.now
if !params[:category_id].blank?
if !params[:category_id].blank? && !params[:tag_id].blank?
@archive_files = ArchiveFile.default_sort(params[:sort]).all.can_display.where(:tagged_ids.in => params[:tag_id]).any_in(:archive_file_category_id => params[:category_id]).merge(ArchiveFileCategory.excludes('disable' => true)).desc( :is_top ).page( params[:page_main] ).per(@page_num)
@archive_file_categorys = ArchiveFileCategory.any_in(:_id => params[:category_id]).excludes('disable' => true)
elsif !params[:category_id].blank?
@archive_files = ArchiveFile.default_sort(params[:sort]).all.can_display.any_in(:archive_file_category_id => params[:category_id]).merge(ArchiveFileCategory.excludes('disable' => true)).desc( :is_top ).page( params[:page_main] ).per(@page_num)
@archive_file_categorys = ArchiveFileCategory.any_in(:_id => params[:category_id]).excludes('disable' => true)
elsif !params[:tag_id].blank?

View File

@ -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

View File

@ -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)

View File

@ -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>

View File

@ -4,7 +4,7 @@
<td>
<div class="control-group">
<div class="controls">
<%= f.text_field :sort_number %>
<%= f.text_field :sort_number, class: 'input-mini' %>
</div>
</div>
</td>
@ -47,18 +47,19 @@
<% end %>
<%= hidden_field_tag 'archive_file[archive_file_multiples_attributes][0][choose_lang][]', '' %>
</td>
<td>
<span class="action">
<% if form_file.new_record? %>
<a class="delete"><i class="icon-remove"></i></a>
<% else %>
<%= f.hidden_field :id %>
<a class="remove_existing_record"><i class="icon-remove"></i></a>
<%= f.hidden_field :should_destroy, :value => nil, :class => 'should_destroy' %>
<% end %>
</span>
<%= form_file.download_count %>
</td>
<td>
<span class="action">
<% if form_file.new_record? %>
<a class="delete"><i class="icon-remove"></i></a>
<% else %>
<%= f.hidden_field :id %>
<a class="remove_existing_record"><i class="icon-remove"></i></a>
<%= f.hidden_field :should_destroy, :value => nil, :class => 'should_destroy' %>
<% end %>
</span>
</td>
</tr>

View File

@ -8,22 +8,22 @@
<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-promoter"><%= t(:promoter)%></th>
</tr>
</thead>
<tbody>
<% @archive_files.each_with_index do |post,i| %>
<tr <% if ( (i + 1) % 2 ) == 0 %> class="even" <% end %>>
<td><div class="o-archives-title"><%= post.title %></div></td>
<td>
<td class="col-title"><div class="o-archives-title"><%= post.title %></div></td>
<td class="col-file">
<div class="o-archives-list-item">
<% if !post.archive_file_multiples.blank? %>
<ol>
<% 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 class="col-promoter">
<% 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>

View File

@ -7,12 +7,3 @@
</div>
<%= stylesheet_link_tag "archive/archives" %>

View File

@ -27,4 +27,6 @@
</div>
</div>
<%= render partial: 'admin/member_selects/promoter_front', locals: {users: @archive_file.get_users} %>
<%= stylesheet_link_tag "archive/archives" %>

View File

@ -2,6 +2,7 @@ en:
archive:
archive: Archive
download_count: Download count
Title: Title
Files: Files
Category: Category

View File

@ -2,6 +2,7 @@ zh_tw:
archive:
archive: 檔案室
download_count: 下載次數
Title: 標題
Files: 檔案
Category: 類別

View File

@ -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"

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -0,0 +1,15 @@
class Panel::Ask::BackEnd::AskCoordinationsController < OrbitWidgetController
include AdminHelper
include OrbitControllerLib::DivisionForDisable
before_filter :for_app_manager
def initialize
super
@app_title = 'ask_coordinations'
end
def index
end
end

View File

@ -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

View File

@ -1,8 +1,10 @@
# encoding: utf-8
class Panel::Ask::BackEnd::AskRepliesController < OrbitBackendController
include AdminHelper
include OrbitControllerLib::DivisionForDisable
before_filter :for_app_manager
def initialize
super
@app_title = 'ask_replies'
@ -11,19 +13,121 @@ class Panel::Ask::BackEnd::AskRepliesController < OrbitBackendController
def create
@ask_question = AskQuestion.find(params[:ask_question_id])
@ask_question.ask_reply = AskReply.new(params[:ask_reply])
@ask_reply = @ask_question.ask_reply
@ask_question.save
if @ask_question.ask_reply.send_email?
Resque.enqueue(SendAskReplyMail, @ask_reply.ask_question.id)
end
status_stack = []
new_status = ""
params[:school][:depts].each do |dns|
begin
status_stack << send_request(dns, @ask_question, @ask_reply)
rescue
status_stack << "fail"
end
end unless params[:school].nil?
success_count = status_stack.count("success")
failed_count = status_stack.count("fail")
if failed_count == 0 && success_count > 0
new_status = "轉介其他單位"
elsif failed_count > 0 && success_count > 0
new_status = "部份轉介失敗"
elsif failed_count > 0 && success_count == 0
new_status = "轉介失敗"
elsif failed_count == 0 && success_count == 0 && @ask_reply.status == "待處理"
new_status = "待處理"
elsif failed_count == 0 && success_count == 0 && @ask_reply.status == "已處理"
new_status = "已處理"
elsif failed_count == 0 && success_count == 0 && @ask_reply.status == "轉介其他單位"
new_status = "轉介失敗"
end
@ask_reply.update_attributes(status: new_status)
redirect_to panel_ask_back_end_ask_questions_path, notice: t('ask.reply_success')
end
def update
@ask_question = AskQuestion.find(params[:ask_question_id])
@ask_reply = AskReply.find(params[:id])
@ask_reply.update_attributes(params[:ask_reply])
if @ask_reply.send_email?
Resque.enqueue(SendAskReplyMail, @ask_reply.ask_question.id)
end
status_stack = []
new_status = ""
params[:school][:depts].each do |dns|
begin
status_stack << send_request(dns, @ask_question, @ask_reply)
rescue
status_stack << "fail"
end
end unless params[:school].nil?
success_count = status_stack.count("success")
failed_count = status_stack.count("fail")
if failed_count == 0 && success_count > 0
new_status = "轉介其他單位"
elsif failed_count > 0 && success_count > 0
new_status = "部份轉介失敗"
elsif failed_count > 0 && success_count == 0
new_status = "轉介失敗"
elsif failed_count == 0 && success_count == 0 && @ask_reply.status == "待處理"
new_status = "待處理"
elsif failed_count == 0 && success_count == 0 && @ask_reply.status == "已處理"
new_status = "已處理"
elsif failed_count == 0 && success_count == 0 && @ask_reply.status == "轉介其他單位"
new_status = "轉介失敗"
end
@ask_reply.update_attributes(status: new_status)
redirect_to panel_ask_back_end_ask_questions_path, notice: t('ask.reply_success')
end
def send_request(dep_dns, current_question, current_reply)
require 'net/http'
require 'uri'
require 'json'
uri_path = "/panel/ask/back_end/ask_requests/transfer_request"
http = Net::HTTP.new(dep_dns,80)
request = Net::HTTP::Post.new(uri_path)
body = {
# 'auth_token' => '3kjlfksjDFJ',
'name' => current_question.name,
'title' => current_question.title,
'identity' => current_question.identity,
'email' => current_question.email,
'phone' => current_question.phone,
'tax' => current_question.tax,
'content' => current_question.content,
}
#binding.pry
status = ""
3.times do
request.set_form_data(body)
request.add_field 'X-Auth-Token', '3kjlfksjDFJ'
response = http.request(request)
if response.code == "200"
status = "success"
break
else
status = "fail"
end
end
return status
# puts "Response #{response.code} #{response.message}: #{response.body}"
# flash[:notice] = response.body
# flash[:notice] = "Response #{response.code} #{response.message}: #{response.body}"
end
end

View File

@ -0,0 +1,38 @@
# encoding: utf-8
class Panel::Ask::BackEnd::AskRequestsController < OrbitBackendController
include AdminHelper
include OrbitControllerLib::DivisionForDisable
skip_before_filter :verify_authenticity_token
def transfer_request
if request.headers["HTTP_X_AUTH_TOKEN"] == '3kjlfksjDFJ'
if !AskCategory.where(key: "transferred_question").any?
@ask_category = AskCategory.new(key: "transferred_question")
@ask_category.name_translations = { "zh_tw" => "轉介的問題", "en" => "Transferred Question" }
@ask_category.save!
end
category = AskCategory.where(key: "transferred_question")
@transfered_question = AskQuestion.new(
name: params['name'],
identity: params['identity'],
email: params['email'],
phone: params['phone'],
tax: params['tax'],
title: params['title'],
content: params['content'],
ask_category_id: category.first.id)
@transfered_question.ask_reply = AskReply.new
@transfered_question.ask_reply.update_attributes(status: "待處理 (轉)")
@transfered_question.save
render :nothing => true
else
render :status => 500
end
end
end

View File

@ -14,18 +14,22 @@ class Panel::Ask::FrontEnd::AskQuestionsController < OrbitWidgetController
def create
@ask_question = AskQuestion.new(params[:ask_question])
if gotcha_valid? && @ask_question.save
@acknowledgement = AskAcknowledgement.last
@acknowledgement = AskAcknowledgement.last
@ask_acknowledgement = AskAcknowledgement.first || AskAcknowlegement.new
#@ask_question.save
redirect_to root_path
AskAdmin.all.each do |ask_admin|
AskMailer.notice(ask_admin, @ask_question).deliver
Resque.enqueue(SendAskNoticeMail, ask_admin.id, @ask_question.id)
end
# redirect_to panel_ask_front_end_thank_you_path
# Render to create.js.erb
respond_to do |format|
format.js
# format.js { render :thank_you, notice: 'Your question has been successfully sent.' }
end
else
# Render to index.js.erb
respond_to do |format|
format.js { render :index }
end
end
end
@ -43,4 +47,7 @@ class Panel::Ask::FrontEnd::AskQuestionsController < OrbitWidgetController
end
@item = Page.find(params[:page_id]) rescue nil
end
def sorry
end
end

View File

@ -2,6 +2,7 @@ class AskCategory
include Mongoid::Document
include Mongoid::Timestamps
include OrbitCoreLib::ObjectDisable
include OrbitCoreLib::ObjectAuthable
field :name, localize: true
field :key

View File

@ -1,3 +1,50 @@
<script type="text/javascript">
var local_host = "<%= request.host %>";
if (local_host[0] == "g" && local_host[1] == "a") {
local_host = "www." + local_host;
}
function hide_current_host_name(localhost) {
$('input[type=checkbox]').each(function() {
if ($(this).val() == local_host) {
$(this).addClass("hide");
$(this).next().addClass("hide");
}
});
}
$(document).ready(function() {
if ($("#ask_reply_status").val() == '轉介其他單位') {
hide_current_host_name(local_host);
$('.dept_options').show();
}
$("#ask_reply_status").change(function() {
hide_current_host_name(local_host);
$('.dept_options').slideUp();
if ($(this).find('option:selected').attr('value') == '轉介其他單位') {
$('.dept_options').slideDown();
}
});
});
</script>
<style type="text/css">
.dept_options {
display: none;
}
.hide {
display: none;
}
</style>
<div id="ask_question_reply">
<%= form_for @ask_reply, url: @url, method: @method do |f| %>
<table class="table">
@ -31,6 +78,29 @@
['已處理', '已處理'],
['轉介其他單位', '轉介其他單位']
] %></td>
<td id="XXX"></td>
</tr>
<tr>
<td colspan="5" class="dept_options">
<div class="dept_options">
<!-- Example <%= check_box("school", "depts", {:multiple => true}, 'ntu_ga_test_p.tp.rulingcom.com', nil) %><%= label_tag("ntu_ga_test_p.tp.rulingcom.com", "測試站總務處 (ntu_ga_test_p)") %>
<%= check_box("school", "depts", {:multiple => true}, 'ntu_ga_test.tp.rulingcom.com', nil) %><%= label_tag("ntu_ga_test.tp.rulingcom.com", "測試站總務處經管組 (ntu_ga_test)") %> -->
<!-- <%= check_box("school", "depts", {:multiple => true}, (request.host + ":3000"), nil) %><%= label_tag((request.host + ":3000"), "測試站3000") %>
<%= check_box("school", "depts", {:multiple => true}, (request.host + ":4000"), nil) %><%= label_tag((request.host + ":4000"), "測試站4000") %> -->
<%= check_box("school", "depts", {:multiple => true}, "www.ga.ntu.edu.tw", nil) %><%= label_tag("www.ga.ntu.edu.tw", "總務處") %>
<%= check_box("school", "depts", {:multiple => true}, "sec.ga.ntu.edu.tw", nil) %><%= label_tag("sec.ga.ntu.edu.tw", "總務長室暨總務處秘書室") %>
<%= check_box("school", "depts", {:multiple => true}, "doc.ga.ntu.edu.tw", nil) %><%= label_tag("doc.ga.ntu.edu.tw", "文書組") %>
<%= check_box("school", "depts", {:multiple => true}, "general.ga.ntu.edu.tw", nil) %><%= label_tag("general.ga.ntu.edu.tw", "事務組") %>
<%= check_box("school", "depts", {:multiple => true}, "property.ga.ntu.edu.tw", nil) %><%= label_tag("property.ga.ntu.edu.tw", "保管組") %>
<%= check_box("school", "depts", {:multiple => true}, "construction.ga.ntu.edu.tw", nil) %><%= label_tag("construction.ga.ntu.edu.tw", "營繕組") %>
<%= check_box("school", "depts", {:multiple => true}, "cashier.ga.ntu.edu.tw", nil) %><%= label_tag("cashier.ga.ntu.edu.tw", "出納組") %>
<%= check_box("school", "depts", {:multiple => true}, "procurement.ga.ntu.edu.tw", nil) %><%= label_tag("procurement.ga.ntu.edu.tw", "採購組") %>
<%= check_box("school", "depts", {:multiple => true}, "fss.ga.ntu.edu.tw", nil) %><%= label_tag("fss.ga.ntu.edu.tw", "經營管理組") %>
<%= check_box("school", "depts", {:multiple => true}, "police.ga.ntu.edu.tw", nil) %><%= label_tag("police.ga.ntu.edu.tw", "駐警隊") %>
<%= check_box("school", "depts", {:multiple => true}, "social.ga.ntu.edu.tw", nil) %><%= label_tag("social.ga.ntu.edu.tw", "社科院總務分處") %>
<%= check_box("school", "depts", {:multiple => true}, "medicine.ga.ntu.edu.tw", nil) %><%= label_tag("medicine.ga.ntu.edu.tw", "醫學院總務分處") %>
</div>
</td>
</tr>
<tr>
<td colspan="5">

View File

@ -1 +1 @@
window.location.href= "<%= panel_ask_front_end_thank_you_path %>"
window.location.href = "<%= panel_ask_front_end_thank_you_path %>";

View File

@ -21,9 +21,9 @@ $(document).ready(function(){
$(this).hide();
}).bind("ajaxError", function() {
$(this).hide();
// window.location.href = "<%= panel_ask_front_end_thank_you_path %>";
});
});
});
</script>
<div id="spinner" class="spinner" style="display:none;">
@ -31,11 +31,11 @@ $(document).ready(function(){
</div>
<div id="new-ask-question" class="ask-question">
<div id="acknowledgement"></div>
<%= form_for @ask_question, url: panel_ask_front_end_ask_questions_path(standalone: true), html: {class: 'form-horizontal'} do |f| %>
<%= form_for @ask_question, url: panel_ask_front_end_ask_questions_path(standalone: true), html: {class: 'form-horizontal'}, method: :post do |f| %>
<div class="control-group">
<%= f.label :ask_category_id, class: 'control-label required' %>
<div class="controls">
<%= f.collection_select :ask_category_id, AskCategory.all, :id, :name %>
<%= f.collection_select :ask_category_id, AskCategory.all.select { |c| c.key != 'transferred_question' }, :id, :name %>
</div>
</div>
<div class="control-group">
@ -85,7 +85,9 @@ $(document).ready(function(){
</div>
</div>
<div class="control-group">
<%= f.label t('ask.validate_code'), class: 'control-label required' %>
<div class="controls">
<label><%= t('ask.validate_code_note') %></label>
<%= gotcha_error %>
<%= gotcha%>
</div>

View File

@ -0,0 +1 @@
window.location.href = "<%= panel_ask_front_end_sorry_path %>";

View File

@ -0,0 +1 @@
<h3><%= t(:ask_fail, :scope => :ask) %> !</h3>

View File

@ -1,5 +1,6 @@
en:
ask:
ask_fail: Something went wrong
ask: Ask
export: Export
reply: Reply
@ -17,6 +18,8 @@ en:
admin: Administrator
new_question: New question
pending: Pending
validate_code: Verification code
validate_code_note: Please answer the following verification questions.
mongoid:
attributes:
ask_question:

View File

@ -3,6 +3,7 @@ zh_tw:
errors:
verification_failed: 驗證碼錯誤
ask:
ask_fail: 寄送失敗
ask: 發問
export: 匯出
reply: 回覆
@ -22,6 +23,8 @@ zh_tw:
admin: 管理者
new_question: 新的發問
pending: 待處理
validate_code: 驗證碼
validate_code_note: 請回答下列驗證問句。
mongoid:
attributes:
ask_question:

View File

@ -15,10 +15,14 @@ Rails.application.routes.draw do
resources :ask_categories
resources :ask_acknowledgements
resources :ask_admins
match "ask_requests/auth_request" => "ask_requests#auth_request", :as => 'auth_request'
match "ask_requests/transfer_request" => "ask_requests#transfer_request", :as => 'transfer_request'
end
namespace :front_end do
match "ask_questions/thank_you" => "ask_questions#thank_you", :as => 'thank_you'
match "ask_questions/sorry" => "ask_questions#sorry", :as => 'sorry'
resources :ask_questions
end
end

View File

@ -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

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