Upload All

This commit is contained in:
Alan
2018-02-26 14:09:18 +08:00
parent 42d3a3fc46
commit 46257f08b0
1024 changed files with 204324 additions and 0 deletions

View File

@ -0,0 +1,16 @@
const User = require("../mongooseSchemas/User");
/**
* 頁面「更變密碼」的插值函式。
* @param {BasicLayout} renderData 基本插值物件。
* @param {string} route 路由路徑。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function ChangePasswordRender(renderData, route, session, callback) {
// 頁面「更變密碼」不需要任何插值。
callback(null, true);
}
module.exports.Render = ChangePasswordRender;

View File

@ -0,0 +1,72 @@
const User = require("../mongooseSchemas/User");
const Painting = require("../mongooseSchemas/Painting");
const Participation = require("../mongooseSchemas/Participation");
/** 預設的新畫作基本資料。 */
const defaultPaintingData = {
id: null,
paintingName: "",
description: "",
tags: [],
viewAuthority: 0,
createdTime: "無",
lastModified: "無",
activity: null,
isFinished: false,
isLocked: false
};
/**
* 頁面「繪圖創作」的插值函式。
* @param {BasicLayout} renderData 基本插值資料物件。
* @param {string} route 路由路徑。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function DrawingRender(renderData, route, session, callback) {
let paintingId = route.substr(9);
let datas = renderData.datas;
// 若使用者有登入
if (renderData.hasLogin) {
// 先尋找使用者資料
User.findOne({"username": renderData.username})
.select("autoSaveEnable tags paintings")
.populate({ path: "paintings", select: { "id": 1 } })
.exec((err, userDocs) => {
if (err) return callback(err, null);
// 先將使用者的自動儲存設定、所有標填上
datas.isAutoSave = userDocs.autoSaveEnable;
datas.userTags = userDocs.tags;
// 若沒有指定圖畫ID將預設的畫作資料填上後回呼。
if (!paintingId) {
datas.painting = defaultPaintingData;
return callback(null, true);
}
// 若該圖畫不屬於使用者的話就回乎錯誤Error_PaintingNotExist。
if (!userDocs.IsPaintingsOwner(paintingId)) {
return callback(Painting.GetError_PaintingNotExist(), null);
}
// 若該圖畫屬於使用者則將目標畫作的基本資料填入然後回呼true。
Painting.GetDrawingPageInfoById(paintingId, (err, paintingInfo) => {
if (err) return callback(err, null);
datas.painting = paintingInfo;
callback(null, true);
});
}
);
}
// 若使用者沒有登入
else {
datas.isAutoSave = false;
datas.userTags = [];
datas.painting = defaultPaintingData;
callback(null, true);
}
}
module.exports.Render = DrawingRender;

View File

@ -0,0 +1,26 @@
const User = require("../mongooseSchemas/User");
/**
* 頁面「編輯個人資料」的插值函式。
* @param {BasicLayout} renderData 插值物件。
* @param {string} route 路由路徑。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function EditPersonalInfoRender(renderData, route, session, callback) {
User.findOne({"username": renderData.username})
.exec((err, userDocs) => {
if (err) return callback(err, null);
if (userDocs) {
renderData.datas = userDocs.personalInfo;
callback(null, true);
}
else {
callback(User.Error_UserNotExist(), null);
}
}
);
}
module.exports.Render = EditPersonalInfoRender;

View File

@ -0,0 +1,27 @@
var User = require("../mongooseSchemas/User");
/**
* 頁面「意見回饋」的插值函式。
* @param {BasicLayout} renderData 基本插值物件。
* @param {string} route 路由路徑。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function FeedBackRender(renderData, route, session, callback) {
renderData.datas.currentDate = (new Date()).toLocaleDateString();
// 如果使用者沒有登入則設定hasPostFeedback為false並呼叫回呼函式。
if (!renderData.hasLogin) {
renderData.datas.hasPostFeedback = false;
callback(null, true);
return;
}
// 如果使用者有登入則尋找資料庫中指定的使用者資料的「hasPostFeedback」欄位。
User.findOne({ "username": renderData.username }).select("hasPostFeedback").exec(function (err, userDoc) {
if (err) {
callback(err, null);
return;
}
renderData.datas.hasPostFeedback = userDoc.hasPostFeedback;
callback(null, true);
});
}
module.exports.Render = FeedBackRender;

View File

@ -0,0 +1,30 @@
let PaintingSpotlight = require("../mongooseSchemas/PaintingSpotlight");
let Season = require("../mongooseSchemas/Season");
/**
* 頁面「傑作藝廊」的插值函式。
* @param {BasicLayout} renderData 基本插值物件。
* @param {string} route 路由路徑。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。傳回錯誤訊息或資料插值設定是否成功。
*/
function GalleryRender(renderData, route, session, callback) {
// 先取得傑作藝廊中的精選輯
PaintingSpotlight.GetCarouselInfo("gallery", function (err, carouselInfo) {
if (err || !carouselInfo) {
callback(err, null);
return;
}
renderData.datas.paintings = carouselInfo.paintings;
// 再取得活動相關的訊息
Season.GetGalleryNeedInfo(function (err, seasonsInfo) {
if (err) {
callback(err, null);
}
else {
renderData.datas.seasons = seasonsInfo;
callback(err, true);
}
});
});
}
module.exports.Render = GalleryRender;

View File

@ -0,0 +1,20 @@
var PaintingSpotlight = require("../mongooseSchemas/PaintingSpotlight");
/**
* 取得首頁的插值資料。
* @param {BasicLayout} renderData 插值物件。
* @param {string} route 路由路徑。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function IndexRender(renderData, route, session, callback) {
PaintingSpotlight.GetCarouselInfo("index", function (err, infos) {
if (err) {
callback(err, null);
}
else {
renderData.datas = infos;
callback(null, true);
}
});
}
module.exports.Render = IndexRender;

View File

@ -0,0 +1,12 @@
/**
* 頁面「登入」的插值函式。
* @param {BasicLayout} renderData 基本插值物件。
* @param {string} route 路由路徑。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function LoginRender(renderData, route, session, callback) {
// 登入頁面目前不需要做任何插值
callback(null, true);
}
module.exports.Render = LoginRender;

View File

@ -0,0 +1,101 @@
/**
* 設定轉跳訊息頁面下的插值處理。
* @param {BasicLayout} renderData 插值物件。
* @param {string} route 路由路徑。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function MessageFormRender(renderData, route, session, callback) {
switch(true) {
case route == "/signupmsg": // 註冊成功的轉跳頁面
renderData.datas.title = "註冊成功!";
renderData.datas.content = "您現在可以用您所註冊的帳號登入了!";
renderData.datas.button1 = "登入";
renderData.datas.script = "$('#btnAction1').on('click', () => window.location.replace('/login'));";
break;
case route.includes("/homenotexist/"): // 在「個人頁面」下找不到目標使用者時的轉跳頁面
// 確認使用者名稱存在於路徑中
if (route.length > 14) {
let username = route.substr(14); // 取得找不到的「使用者名稱」
renderData.datas.title = "找不到 “" + username + "” 的個人頁面!"
}
else {
renderData.datas.title = "找不到指定使用者的個人頁面!";
}
renderData.datas.content = "很抱歉,您所尋找的使用者並不存在!";
renderData.datas.button1 = "首頁";
renderData.datas.script = "$('#btnAction1').on('click', () => window.location.replace('/'));";
break;
case route == "/personalinfo_updated": // 在「編輯個人資料」頁面下,成功編輯個人資料後的跳轉提示頁面
renderData.datas.title = "個人資料修改成功!";
renderData.datas.content = "您的個人資料已成功更新!";
renderData.datas.button1 = "返回";
renderData.datas.script = "$('#btnAction1').on('click', () => window.location.replace('/home/" + renderData.username + "'));";
break;
case route == "/send_sitemail_successfully": // 在「撰寫站內訊息」頁面下,成功編輯個人資料後的轉跳頁面。
renderData.datas.title = "站內信發送成功!";
renderData.datas.content = "您的站內信件已成功寄送!";
renderData.datas.button1 = "返回";
renderData.datas.script = "$('#btnAction1').on('click', () => window.location.replace('/home/" + renderData.username + "'));";
break;
case route == "/newpw_success": // 在「更變密碼」頁面下,成功更改密碼後的轉跳頁面。
renderData.datas.title = "密碼更改成功!";
renderData.datas.content = "您的密碼已經更改成功!";
renderData.datas.button1 = "返回";
renderData.datas.script = "$('#btnAction1').on('click', () => window.location.replace('/home/" + renderData.username + "'));";
break;
case route == "/painting_finished": // 在「繪圖創作」頁面下,成功完成畫作之後的跳轉頁面。
renderData.datas.title = "作品已完成!";
renderData.datas.content = "您的畫作已經完成,您可以返回去欣賞您的畫作!";
renderData.datas.button1 = "返回";
renderData.datas.script = "$('#btnAction1').on('click', () => window.location.replace('/home/" + renderData.username + "'));";
break;
case route == "/painting_not_exist": // 在找不到指定的圖畫作品之下的跳轉頁面
renderData.datas.title = "找不到您的圖畫作品!";
renderData.datas.content = "請確認您所指定的圖畫作品是否所屬於您,或是該作品是否存在。";
renderData.datas.button1 = "返回";
renderData.datas.script = "$('#btnAction1').on('click', () => window.location.replace('/home/" + renderData.username + "'));";
break;
case route == "/painting_deleted": // 成功刪除指定圖畫作品後的跳轉頁面
renderData.datas.title = "圖畫作品刪除成功!";
renderData.datas.content = "您指定的圖畫作品已刪除成功!" + (session.paintingDeleted_Activity ? "請注意,投稿至活動上的圖畫不會被刪除!" : "");
renderData.datas.button1 = "返回";
renderData.datas.script = "$('#btnAction1').on('click', () => window.location.replace('/home/" + renderData.username + "'));";
// 若有被標記則刪除paintingDeleted_Activity
if (session.paintingDeleted_Activity)
delete session.paintingDeleted_Activity;
break;
case route == "/newtheme/successful": // 當成功處理了「投稿新主題」後的轉跳頁面
renderData.datas.title = "新主題投稿成功!";
renderData.datas.content = "您所投稿的新主題已成功地上傳!請等待最新一季的結果。";
renderData.datas.button1 = "返回首頁";
renderData.datas.script = "$('#btnAction1').on('click', () => window.location.replace('/'));";
break;
case route == "/newtheme": // 當使用者在「投稿主題」路由上,但卻已經有投稿過主題的轉跳頁面
renderData.datas.title = "您已經投稿過新主題了!";
renderData.datas.content = "請等待下一次的「投稿主題」活動再進行發起主題的動作!。";
renderData.datas.button1 = "返回";
renderData.datas.script = "$('#btnAction1').on('click', () => window.history.back() );";
break;
case route == "/votetheme/success": // 當成功處理了「主題票選」後的轉跳頁面
renderData.datas.title = "候選主題投票成功!";
renderData.datas.content = "您的投票資料已經成功送出!請等待下一次的主題投票。";
renderData.datas.button1 = "返回首頁";
renderData.datas.script = "$('#btnAction1').on('click', () => window.location.replace('/'));";
break;
case route == "/votetheme": // 當使用者在「主題票選」路由上,但卻已經有票選過主題之後的跳轉頁面
renderData.datas.title = "您已經對候選主題票選過了!";
renderData.datas.content = "請等待下一次的「主題票選」活動再進行主題票選的動作!";
renderData.datas.button1 = "返回";
renderData.datas.script = "$('#btnAction1').on('click', () => window.history.back() );";
break;
default: // 其他未定義的伺服器訊息
return callback(new Error("未定義的對應伺服訊息插值資料。"), null);
}
return callback(false, true);
}
module.exports.Render = MessageFormRender;

View File

@ -0,0 +1,89 @@
const User = require("../mongooseSchemas/User");
const Painting = require("../mongooseSchemas/Painting");
const SiteMail = require("../mongooseSchemas/SiteMail");
/**
* 取得「個人頁面」的插值資料。
* @param {BasicLayout} renderData 插值物件。
* @param {string} route 路由路徑。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function PersonalPageRender(renderData, route, session, callback) {
let paramUsername = route.substr(6); // 取得路徑中所選的目標個人頁面的使用者名稱
// 初步地檢查是否為合法的使用者名稱長度。若是,則進一步地去查詢相關資料
if (4 <= paramUsername.length && paramUsername.length <= 16) {
// 定義Populate Query : 套用的有paintings, siteMsg, siteMail 與 friendList
let populateQuery = [
{ path: "paintings", select: { "id": 1, "name": 1, "links": 1, "description": 1, "viewAuthority": 1, "tags": 1 } },
{ path: "friendList", select: { "username": 1 } },
{ path: "siteMsg.refId" },
{ path: "siteMail" }
];
// 嘗試尋找指定的使用者並做populate來取得相關連的資料
User.findOne({"username": paramUsername})
.populate(populateQuery)
.exec((err, userDocs) => {
// 如果找到使用者的話,將需要的資料填入插值物件中
if (userDocs) {
// 定義 datas 物件,並將一些不需要過濾的資料先加入
let datas = {
isOwner: (renderData.username == userDocs.username), // 若目前正瀏覽的使用者與目標使用者的相同,則為這個個人頁面的擁有者(true),反之為否(false)
username: userDocs.username, // 使用者名稱
nickname: userDocs.personalInfo.nickname, // 暱稱
motto: userDocs.personalInfo.motto, // 短言
userPhotoURL: userDocs.personalInfo.photo, // 個人相片 (連結路徑)
autoSaveEnable: userDocs.autoSaveEnable, // 自動儲存
userTags: userDocs.tags, // 作品標籤
friendList: [], // 好友清單
siteMsg: [], // 網站訊息
paintings: [], // 作品集
siteMail: null // 站內信
};
// 循環將 friendList 加入 datas 中
for (let i = 0, list = userDocs.friendList; i < list.length; i++)
datas.friendList.push(list[i].username);
// 循環將 siteMail 加入 datas 中
for (let list = userDocs.siteMsg, i = list.length - 1; i >= 0; i--) {
// 若為伺服訊息,則引用連接的伺服訊息資料
if (list[i].isServerMessage) {
datas.siteMsg.push({ title: list[i].refId.title, content: list[i].refId.content });
}
else {
datas.siteMsg.push({ title: list[i].title, content: list[i].content });
}
}
datas.siteMail = userDocs.siteMail; // 將 siteMail 加入 datas 中
// 循環將 paintings 加入 datas 中
let isFriend = userDocs.IsUsersFriend(session.passport.user); // 取得目前使用者對目標使用者而言的權限
for (let i = 0, list = userDocs.paintings; i < list.length; i++) {
// 若 觀看權限為「公開」 或 使用者為目標使用者的朋友且觀看權限為「半公開」 或 該使用者即為擁有者,則將幅畫資訊加入
if (list[i].viewAuthority == 0 || isFriend && list[i].viewAuthority == 1 || datas.isOwner) {
datas.paintings.push(list[i]);
}
}
renderData.datas = datas; // 最後將 datas 複寫至 renderData.datas
callback(null, true);
}
// 若沒有找到,則將錯誤「找不到目標使用者」回呼至上層路由
else {
callback(User.Error_UserNotExist(), null);
}
}
);
}
// 如果不為合法的使用者名稱長度,則將錯誤「找不到目標使用者」回呼至上層路由。
else {
callback(User.Error_UserNotExist(), null);
}
}
module.exports.Render = PersonalPageRender;

View File

@ -0,0 +1,166 @@
const User = require("../mongooseSchemas/User");
const Painting = require("../mongooseSchemas/Painting");
const ParticipantInfo = require("../mongooseSchemas/ParticipantInfo");
/**
* 以主使用者與被檢查的使用者之間的關係,取得觀看權限數值。
* @param {User} mainUser 主要使用者的資料。
* @param {string} otherUser_id 目標要查詢的使用者_id。
* @return {number} 觀看權限數值。
*/
function GetAuthorityNumber(mainUser, otherUser_id) {
if (mainUser._id.equals(otherUser_id)) { // 若mainUser與otherUser為同一人則回傳2。
return 2;
}
else if (mainUser.IsUsersFriend(otherUser_id)) { // 若otherUser為mainUser的好友則回傳1。
return 1;
}
else { // 若不為好友則回傳0。
return 0;
}
}
/**
* @typedef PaintingRange
* @prop {number} n 表示第n個區間。
* @prop {string[]} range_id 表示在第n個區間中的圖畫Id。
*/
/**
* 取得目標要尋找的圖畫Id座落的區間與該區間中第一個圖畫Id。
* @param {Painting[]} list 全域的資料。為圖畫陣列。
* @param {string} id 要尋找座落在哪區間的資料。為圖畫Id。
* @param {number} viewAutho 觀看權限數值。
* @return {PaintingRange} 回傳第N個區間整數與該區間中的第一個圖畫Id。為 {n, range_id}。
*/
function GetRangeIndex(list, id, viewAutho) {
let viewList = list.filter((docs => docs.viewAuthority <= viewAutho)); // 用「訪問權限」與觀看權限數值,過濾原本的畫作清單,成新的畫作清單。
let length = viewList.length; // 取得清單內容長度
// 尋找目標畫作在清單中的索引位置
for (let i = 0; i < length; i++) {
if (list[i].id == id) {
// 以十個畫作為一組取得目前在第n組
let n = Math.floor(i / 10);
// 回傳n與第n組中 (n * 10) ~ (n * 10 + 9) 之間的畫作_id清單。
return { n: n, range_id: list.slice(n * 10, n * 10 + 10).filter(docs => docs._id) };
}
}
// 若沒找到則回傳null。
return null;
}
/**
* 為「個人藝廊」模式下的插值方法。
* @param {BasicLayout} renderData 基本差值物件。
* @param {string[]} params 路由路徑中的每項參數。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function PersonalShowcaseRender(renderData, params, session, callback) {
let username = params[2]; // 此個人藝廊的使用者
let paintingId = params[3]; // 指定要瀏覽的畫作Id
let tag = params[4]; // 指定畫作的標籤群組(可有可無)
let datas = renderData.datas;
datas.isActivity = false;
datas.themeTitle = null;
datas.themeOriginator = null;
datas.artist = username;
datas.tag = tag;
datas.paintings = []; // 建立畫作清單欄位
// 建立 Populate Query
let populateQuery = {
path: "paintings",
select: { "id": 1, "viewAuthority": 1 },
match: { "isLocked": false }
};
// 如果有指定tag則將其加入到populateQuery之中作為條件
// 比對每個畫作的標籤中是否有包含tag。
if (tag)
populateQuery.match.tags = tag;
// 以username尋找目標使用者的資料其中選取paintings欄位然後再以populateQuery做畫作連結
User.findOne({"username": username})
.select("personalInfo.photo paintings friendList")
.populate(populateQuery)
.exec((err, userDocs) => {
if (err) callback(err, null);
if (!userDocs) callback(User.Error_UserNotExist(), null); // 若找不到使用者,則帶著相對應的錯誤回呼
let ownersPhotoURL = userDocs.personalInfo.photo; // 擁有此展示藝廊的人的頭像照片
let paintingList = userDocs.paintings; // 取得畫作Id清單
let viewAuth = GetAuthorityNumber(userDocs, session.passport.user); // 取得觀看權限數值
let rangeInfo = GetRangeIndex(paintingList, paintingId, viewAuth); // 取得區間資料
// 如果目標畫作不在清單之中的話,則回呼錯誤 **仍要再改
if (!rangeInfo) return callback(new Error("找不到對應的畫作。"), null);
// 以區間尋找畫作資訊
Painting.find({ "_id": { $in: rangeInfo.range_id } })
.populate([{path: "ratings"}, {path: "comments"}])
.exec((err, paintingDocs) => {
if (err) callback(err, null);
// 循每一個畫作資料,取其中的欄位資料加入至 datas.paintings 中
paintingDocs.forEach((docs) => {
datas.paintings.push({
id: docs.id,
links: docs.links,
name: docs.name,
description: docs.description,
artistInfo: { name: username, photoURL: ownersPhotoURL},
totalScore: docs.totalScore,
userScore: docs.FindRatingScoreByUsername(renderData.username),
comments: docs.comments
});
});
// 最後,取得當前使用者的個人照片
User.findOne({"_id": session.passport.user}, "personalInfo.photo", (err, guestUserDocs) => {
if (err) return callback(err, null);
if (!guestUserDocs) return callback(User.Error_UserNotExist(), null);
datas.photoURL = guestUserDocs.personalInfo.photo; // 取得當前使用者的個人照片
callback(null, true);
});
}
);
}
);
}
/**
* 為「活動藝廊」模式下的差值方法。
* @param {BasicLayout} renderData 基本插值物件。
* @param {string[]} params 路由路徑中的每項參數。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function ActivityShowcaseRender(renderData, params, session, callback) {
}
/**
*
* @param {BasicLayout} renderData 基本插值物件。
* @param {string} route 路由路徑。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function ShowcaseRender(renderData, route, session, callback) {
let params = route.split("/").slice(1);
switch(params[1]) {
case "personal":
PersonalShowcaseRender(renderData, params, session, callback);
break;
case "activity":
ActivityShowcaseRender(renderData, params, session, callback);
break;
default:
callback(new Error("未定義的展示藝廊模式。"), null);
}
}
module.exports.Render = ShowcaseRender;

View File

@ -0,0 +1,12 @@
/**
* 頁面「註冊」的插值函式。
* @param {BasicLayout} renderData 基本插值物件。
* @param {string} route 路由路徑。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function SignUpRender(renderData, route, session, callback) {
// 登入頁面目前不需要做任何插值
callback(null, true);
}
module.exports.Render = SignUpRender;

View File

@ -0,0 +1,14 @@
/**
* 以基本插值資料、路由路徑做資料源設定在submit_theme頁面下該插入什麼資料值。
* @param {BasicLayout} renderData 插值物件。
* @param {string} route 路由路徑。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function SubmitThemeRender(renderData, route, session, callback) {
// 此頁面不需要任何插值資料
callback(null, true);
}
module.exports.Render = SubmitThemeRender;

View File

@ -0,0 +1,21 @@
var Season = require("../mongooseSchemas/Season");
/**
* 頁面「畫作主題」的插值函式。
* @param {BasicLayout} renderData 基本插值物件。
* @param {string} route 路由路徑。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function ThemeRender(renderData, route, session, callback) {
// 先取得「畫作主題」頁面所需要的季資訊
// 若出現錯誤則回呼錯誤訊息若取得成功則回呼true已表示成功。
Season.GetThemePageNeedInfo(function (err, seasonDatas) {
if (err) {
callback(err, null);
return;
}
renderData.datas = seasonDatas;
callback(null, true);
});
}
module.exports.Render = ThemeRender;

View File

@ -0,0 +1,42 @@
const User : any = require("../mongooseSchemas/User");
/**
* 由DataRender所定義的基本差值物件。這裡僅列出必要的datas屬性與會用到的屬性。
*/
interface BasicLayout {datas: any, hasLogin: boolean, username: string}
/**
* A Callback function.
* @callback CallbackFunction
* @param {Object} err 錯誤資訊物件。
* @param {Object} obj 成功時所回傳的物件。
*/
interface CallbackFunction { (err: Object, obj: Object) : void }
/**
* 頁面「意見回饋」的插值函式。
* @param {BasicLayout} renderData 基本插值物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function FeedBackRender(renderData: BasicLayout, callback: CallbackFunction) : void
{
renderData.datas.currentDate = (new Date()).toLocaleDateString();
// 如果使用者沒有登入則設定hasPostFeedback為false並呼叫回呼函式。
if (!renderData.hasLogin) {
renderData.datas.hasPostFeedback = false;
callback(null, true);
return;
}
// 如果使用者有登入則尋找資料庫中指定的使用者資料的「hasPostFeedback」欄位。
User.findOne({"username" : renderData.username}).select("hasPostFeedback").exec((err, property) => {
if (err) {
callback(err, null);
return;
}
renderData.datas.hasPostFeedback = property;
callback(null, true);
});
}
module.exports.Render = FeedBackRender;

View File

@ -0,0 +1,94 @@
const PaintingSpotlight = require("../mongooseSchemas/PaintingSpotlight");
const Season = require("../mongooseSchemas/Season");
/**
* 由DataRender所定義的基本差值物件。這裡僅列出必要的datas屬性
*/
interface BasicLayout {datas: any}
/**
* A Callback function.
* @callback CallbackFunction
* @param {Object} err 錯誤資訊物件。
* @param {Object} obj 成功時所回傳的物件。
*/
interface CallbackFunction { (err: Object, obj: Object) : void }
/**
* 繪圖展示上的簡短訊息。
* @prop {string} links 此畫作的圖片連結。
* @prop {string} name 此畫作的名稱。
* @prop {string} description 此畫作的敘述。
* @prop {string} artist 畫作的作者。
*/
interface PaintingInfo {
links : string
name : string,
description : string,
artist : string
}
/**
* 表示畫作的參賽相關訊息。
* @prop {number} rank 此畫作的名次。
* @prop {string} artist 畫作的作者。
* @prop {string} paintingName 畫作的名稱。
* @prop {Date} postTime 此畫作的參賽時間。
*/
interface ParticipantInfo {
rank : number,
artist : string,
paintingName : string,
postTime : Date
}
/**
* 有關主題的相關訊息。
* @prop {number} order 主題與主題之間的識別號碼(用於版面先後排序用)。
* @prop {string} title 主題的標題。
* @prop {ParticipantInfo[]} participants 此主題的所有參賽畫作資訊。
*/
interface ThemeInfo {
order : number,
title : string,
participants : ParticipantInfo[]
}
/**
* 有關一季活動之中的相關訊息。
* @prop {number} nth 表示目前是第nth季
* @prop {ThemeInfo[]} 儲存這一季之中所有的活動。
*/
interface SeasonInfo {
nth : number,
themes : ThemeInfo[]
}
/**
* 頁面「傑作藝廊」的插值函式。
* @param {BasicLayout} renderData 基本插值物件。
* @param {CallbackFunction} callback 回呼函式。傳回錯誤訊息或資料插值設定是否成功。
*/
function GalleryRender(renderData : BasicLayout, callback : CallbackFunction) : void {
// 先取得傑作藝廊中的精選輯
PaintingSpotlight.GetCarouselInfo("gallery", (err, carouselInfo) => {
if (err || !carouselInfo) {
callback(err, null);
return;
}
renderData.datas.paintings = carouselInfo.paintings;
// 再取得活動相關的訊息
Season.GetGalleryNeedInfo((err, seasonsInfo) => {
if (err){
callback(err, null);
}
else {
renderData.datas.seasons = seasonsInfo;
callback(err, true);
}
});
});
}
module.exports.Render = GalleryRender;

View File

@ -0,0 +1,50 @@
let PaintingSpotlight = require("../mongooseSchemas/PaintingSpotlight");
/**
* 由DataRender所定義的基本差值物件。這裡僅列出必要的datas屬性。
*/
interface BasicLayout {datas: any}
/**
* A Callback function.
* @callback CallbackFunction
* @param {Object} err 錯誤資訊物件。
* @param {Object} obj 成功時所回傳的物件。
*/
interface CallbackFunction { (err: Object, obj: Object) : void }
/**
* Painting Information Interface
*/
interface PaintingInfo {
links : string
name : string,
description : string,
artist : string
}
/**
* Data layout of index.
*/
interface IndexLayout {
paintings : PaintingInfo[]
}
/**
* 取得首頁的插值資料。
* @param {BasicLayout} renderData 插值物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function IndexRender(renderData : BasicLayout, callback : CallbackFunction) : void {
PaintingSpotlight.GetCarouselInfo("index", (err, infos) => {
if (err) {
callback(err, null);
}
else {
renderData.datas = infos;
callback(null, true);
}
});
}
module.exports.Render = IndexRender;

View File

@ -0,0 +1,26 @@
/**
* 由DataRender所定義的基本差值物件。這裡僅列出必要的datas屬性。
*/
interface BasicLayout {datas: any}
/**
* A Callback function.
* @callback CallbackFunction
* @param {Object} err 錯誤資訊物件。
* @param {Object} obj 成功時所回傳的物件。
*/
interface CallbackFunction { (err: Object, obj: Object) : void }
/**
* 頁面「登入」的插值函式。
* @param {BasicLayout} renderData 基本插值物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function LoginRender(renderData: BasicLayout, callback: CallbackFunction) : void
{
// 登入頁面目前不需要做任何插值
callback(null, true);
}
module.exports.Render = LoginRender;

View File

@ -0,0 +1,26 @@
/**
* 由DataRender所定義的基本差值物件。這裡僅列出必要的datas屬性。
*/
interface BasicLayout {datas: any}
/**
* A Callback function.
* @callback CallbackFunction
* @param {Object} err 錯誤資訊物件。
* @param {Object} obj 成功時所回傳的物件。
*/
interface CallbackFunction { (err: Object, obj: Object) : void }
/**
* 頁面「註冊」的插值函式。
* @param {BasicLayout} renderData 基本插值物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function SignUpRender(renderData: BasicLayout, callback: CallbackFunction) : void
{
// 登入頁面目前不需要做任何插值
callback(null, true);
}
module.exports.Render = SignUpRender;

View File

@ -0,0 +1,70 @@
const Season : any = require("../mongooseSchemas/Season");
/**
* 由DataRender所定義的基本差值物件。這裡僅列出必要的datas屬性
*/
interface BasicLayout {datas: any}
/**
* A Callback function.
* @callback CallbackFunction
* @param {Object} err 錯誤資訊物件。
* @param {Object} obj 成功時所回傳的物件。
*/
interface CallbackFunction { (err: Object, obj: Object) : void }
/**
* 有關主題的相關訊息。
* @prop {number} order 主題與主題之間的識別號碼(用於版面先後排序用)。
* @prop {string} title 主題的標題。
* @prop {string} narrative 主題的敘述。
* @prop {string} imageURL 主題縮圖連結。
* @prop {string} originator 主題發起人。
* @prop {number} participantCount 投稿人數。
* @prop {number} views 瀏覽此主題的人次數。
* @prop {number} commentCount 主題中相關留言人數。
*/
interface ThemeInfo {
order : number,
title : string,
narrative : string,
imageURL : string,
originator : string,
participantCount : number,
views : number,
commentCount : number
}
/**
* 有關一季活動之中的相關訊息。
* @prop {number} nth 表示目前是第nth季
* @prop {Date} endTime 表示該季的結束時間。在資料取得中只有上一季有這個欄位
* @prop {ThemeInfo[]} 儲存這一季之中所有的活動。
*/
interface SeasonInfo {
nth : number,
endTime : Date,
themes : ThemeInfo[]
}
/**
* 頁面「畫作主題」的插值函式。
* @param renderData 基本插值物件。
* @param callback 回呼函式。
*/
function ThemeRender(renderData: BasicLayout, callback: CallbackFunction) : void
{
// 先取得「畫作主題」頁面所需要的季資訊
// 若出現錯誤則回呼錯誤訊息若取得成功則回呼true已表示成功。
Season.GetThemePageNeedInfo((err, seasonDatas) => {
if (err) {
callback(err, null);
return;
}
renderData.datas = seasonDatas;
callback(null, true);
});
}
module.exports.Render = ThemeRender;

View File

@ -0,0 +1,44 @@
const NewTheme = require("../mongooseSchemas/NewTheme");
const ServerStatus = require("../../ServerStatus");
/**
* 以基本插值資料、路由路徑做資料源設定在write_message頁面下該插入什麼資料值。
* @param {BasicLayout} renderData 基本插值物件。
* @param {string} route 路由路徑。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function VoteThemeRenderer(renderData, route, session, callback) {
let status = ServerStatus.status; // 取得伺服器的狀態資料
let datas = renderData.datas;
datas.title = "第" + (status.currentSeason + 1) + "季主題票選";
datas.voteCount = status.voteCount; // 取得在主題候選之中,使用者的手中有多少票
// 將候選主題全部找出,並依建立時間來進行排列
NewTheme.find({})
.sort({ "createdTime": 1 })
.exec((err, newThemeDocs) => {
if (err) return callback(err, null);
// 將所有頁面所要的候選主題資料加入到 themes 中
let themes = [];
newThemeDocs.forEach((docs, index) => {
themes.push({
id: index,
title: docs.title,
narrative: docs.narrative,
imageURL: docs.image,
originator: docs.sponsor
});
});
// 隨後再將 themes 加入到 datas 之上
datas.themes = themes;
callback(null, true);
}
);
}
module.exports.Render = VoteThemeRenderer;

View File

@ -0,0 +1,35 @@
let User = require("../mongooseSchemas/User");
/**
* 以基本插值資料、路由路徑做資料源設定在write_message頁面下該插入什麼資料值。
* @param {BasicLayout} renderData 插值物件。
* @param {string} route 路由路徑。
* @param {Express.Session} session Express的Session物件。
* @param {CallbackFunction} callback 回呼函式。
*/
function WriteMessageRender(renderData, route, session, callback) {
let populateQuery = { path: "friendList", select: { "username": 1 } }; // 建立Populate Query連結好友清單中的「Username」欄位。
let recipient = route.substr(15); // 取得指定的使用者
// 尋找目前使用者的好友清單內的所有好友的使用者名稱
User.findOne({"username": renderData.username})
.populate(populateQuery)
.exec((err, docs) => {
// 若有錯誤,則將錯誤回呼並返回
if (err) return callback(err);
// 將收件者加入插值物件中
renderData.datas.recipient = recipient;
// 循環取得好友清單所有的使用者名稱
let friendsUsernames = [];
for (let friend of docs.friendList)
friendsUsernames.push(friend.username);
renderData.datas.friendList = friendsUsernames;
callback(null, true);
}
);
}
module.exports.Render = WriteMessageRender;