diff --git a/admin/component/post.js b/admin/component/post.js index 38a5e7d..aca63d2 100644 --- a/admin/component/post.js +++ b/admin/component/post.js @@ -1,17 +1,271 @@ (() => { - function create(tag) { - return document.createElement(tag); + let listData = { + page: -1, + limit: -1, + allPostCount: -1 + }; + + async function fetchPost(mode, data) { + let queryData = { + method: "GET", + url: "../ajax/posts.php" + } + + switch (mode) { + case "page": + queryData.url += `?page=${data}`; + if (listData["page"] != -1 && data > Math.ceil(listData['allPostCount'] / listData['limit'])) { + // we don't have that much post + pageManager.snackbar('頁數不存在'); + router.navigate('/post'); + return; + } + break; + case "user": + queryData.url += `?username=${data}`; + pageManager.setHeader(`${data} 的文章`); + break; + case "pid": + queryData.url += `?pid=${data}`; + break; + default: + break; + } + + try { + let res = await axios.request(queryData); + if (mode == "page") { + listData.allPostCount = parseInt(res.data["all_posts_count"]); + listData.page = parseInt(res.data["page"]); + listData.limit = parseInt(res.data["page_limit"]); + } + + if (mode == "pid") { + let likeData = await axios.request({ + url: `../ajax/like.php?pid=${data}&fetch`, + method: "GET" + }); + renderPostPage(data, res.data.post, likeData.data); + } else { + renderPage(mode, res.data); + } + + } catch (error) { + console.error(error); + if (error.response) { + if (error.response.status == 404) { + pageManager.snackbar("找不到文章"); + } + } else { + pageManager.snackbar("讀取資料時發生錯誤。"); + } + } finally { + bindListener(mode); + finish(); + } + } + + function renderPage(mode, data) { + let doc = pageManager.document; + doc.innerHTML = ""; + + var wrapper = create('div', "table wrapper"); + var table = create('table', "ts sortable celled striped table"); + + let thead = create('thead'); + (["標題", "讚", "留言", "日期", "管理"]).forEach((e, _i) => { + let th = create('th'); th.textContent = e; + thead.appendChild(th); + }) + table.appendChild(thead); + + var tbody = create('tbody'); + for (post of data["posts"]) { + let tr = create("tr"); + (["title", "likes_count", "comments_count", "time"]).forEach((e, _i) => { + let td = create('td'); + if (e != "title") td.classList.add("collapsing"); + if (e.indexOf("count") != -1) td.classList.add("center", "aligned"); + + if (e == "title") { + td.innerHTML = `${post[e]}`; + } else { + td.textContent = post[e]; + } + tr.appendChild(td); + }); + + let action = ``; + tr.insertAdjacentHTML("beforeend", action); + + tbody.appendChild(tr); + } + + table.appendChild(tbody); + wrapper.appendChild(table); + doc.appendChild(wrapper); + + if (mode === "page") doc.appendChild(pagination(listData["allPostCount"], listData["limit"], listData["page"])); + } + + function renderPostPage(pid, data, likeData) { + let doc = pageManager.document; + doc.innerHTML = ""; + + let segment = create('div', "ts clearfix primary segment"); + let title = create('div', "ts big header"); + let cardContainer = create('div', "ts stackable three cards"); + title.innerHTML = data["title"]; + title.insertAdjacentHTML("beforeend", `
${data["name"]}
`); + segment.appendChild(title); + + data["length"] = data["content"].length; + let iconName = { + "length": "font", + "likes_count": "like outline", + "comments_count": "comments" + }; + + let statLabel = { + "length": "文章字數", + "likes_count": "獲得讚數", + "comments_count": "留言數量" + }; + + let statTemplate = `
{{ value }}
{{ label }}
`; + Object.keys(iconName).forEach((e, _i) => { + let card = create('div', "ts card"); + let content = create('div', "content"); + let symbol = create('div', "symbol"); + let icon = create('i', `${iconName[e]} icon`); + + content.innerHTML = statTemplate.replace("{{ value }}", data[e]).replace("{{ label }}", statLabel[e]); + symbol.appendChild(icon); + card.appendChild(content); + card.appendChild(symbol); + + cardContainer.appendChild(card); + }); + segment.appendChild(cardContainer); + + let likersDetail = create('details', "ts accordion"); + let detailContent = create('div', "content"); + likersDetail.insertAdjacentHTML("beforeend", ` 按讚的人`); + let likersList = create('div', "ts link list"); + for (let username of likeData["likers"]) { + let item = create('a', "item"); + item.href = `/user/${username}`; + item.setAttribute("data-navigo", ""); + item.textContent = username; + likersList.appendChild(item); + } + if (!likeData["likers"].length) { + likersList.insertAdjacentHTML("beforeend", `
(無)
`); + } + detailContent.appendChild(likersList); + likersDetail.appendChild(detailContent); + segment.appendChild(likersDetail); + + let actionsContainer = create('div', "ts separated right floated buttons"); + let actionClass = { + "編輯": "basic", + "預覽": "primary", + "刪除": "negative" + }; + let actionParams = { + "編輯": `?edit=${pid}`, + "預覽": `?pid=${pid}`, + "刪除": `?del=${pid}` + }; + Object.keys(actionClass).forEach((e, _i) => { + let button = create('a', "ts button"); + button.classList.add(actionClass[e]); + button.target = "_blank"; + button.href = "../post.php" + actionParams[e]; + button.textContent = e; + actionsContainer.appendChild(button); + }); + segment.appendChild(actionsContainer); + doc.appendChild(segment); + doc.insertAdjacentHTML("beforeend", ` -1 ? listData["page"] : 1)}" data-navigo>返回列表`); + } + + function pagination(all, limit, currentPage) { + let totalPage = Math.ceil(all / limit); + let pagination = create('div'); pagination.className = "ts basic center aligned padded segment"; + let buttons = create('div'); buttons.className = "ts small separated buttons"; + + if (currentPage > 1) buttons.innerHTML += ``; + buttons.innerHTML += `
${currentPage} / ${totalPage}
`; + if (currentPage != totalPage) buttons.innerHTML += ``; + + pagination.appendChild(buttons); + return pagination; + } + + function bindListener(mode) { + if (mode == "page" || mode == "user") { + var selector = "tbody"; + } else if (mode == "pid") { + var selector = ".ts.primary.segment"; + } + + $(selector).on('click', 'a.negative', function(e) { + e.preventDefault(); + + let el = e.currentTarget; + let pid = el.dataset.pid; + showModal(pid); + }); + + function showModal(pid) { + swal({ + type: 'question', + title: '確定要刪除嗎?', + showCancelButton: true, + confirmButtonText: '確定', + cancelButtonText: '取消' + }).then((result) => { + if (result.value) { // confirm + axios.request({ + method: "GET", + url: "../post.php?del=" + pid + }).then(function (res) { + pageManager.snackbar('刪除成功'); + router.navigate('/post'); // reload + }).catch(function (err) { + switch (err.response.status) { + case 404: + pageManager.snackbar('找不到文章'); + case 403: + pageManager.snackbar('權限不足'); + } + }); + } + }); + } + } + + function finish() { + ts('table').tablesort(); + router.updatePageLinks(); + setTimeout(() => { + pageManager.setLoaderState(false) + }, 1000); + } + + function create(tag, className="") { + let el = document.createElement(tag); + el.className = className; + return el; } pageManager.register("post", function () { return { render: function (...args) { pageManager.setHeader("文章"); - setTimeout(() => { - pageManager.document.innerHTML = args[0] + args[1]; - pageManager.setLoaderState(false) - }, 500); + fetchPost(...args); } } }); -})(); +})(); \ No newline at end of file diff --git a/ajax/posts.php b/ajax/posts.php index 90590ce..0c7dc41 100644 --- a/ajax/posts.php +++ b/ajax/posts.php @@ -66,7 +66,7 @@ if (isset($_GET['pid'])) { "SELECT `post`.*, `user`.name FROM `post` INNER JOIN `user` ON `post`.username = `user`.username WHERE `post`.username = '%s' ORDER BY `time`", array($_GET['username']) )); - $all_posts_count = cavern_query_result("SELECT COUNT(*) AS `count` FROM `post` WHERE `username` = '%s'", array($_GET['username']))['row']['count']; + $all_posts_count = sizeOf($post_list); } else { $post_list = article_list(cavern_query_result( "SELECT `post`.*, `user`.name FROM `post` INNER JOIN `user` ON `post`.username = `user`.username ORDER BY `time` DESC LIMIT %d,%d", @@ -86,9 +86,8 @@ if (isset($_GET['pid'])) { $post = array( 'username' => $article->author, 'name' => $article->name, - 'pid' => $article->pid, + 'pid' => intval($article->pid), 'title' => $article->title, - 'content' => $article->content, 'time' => $article->time, 'likes_count' => $article->likes_count, 'comments_count' => $article->comments_count,