166 lines
7.1 KiB
JavaScript
166 lines
7.1 KiB
JavaScript
|
||
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; |