summaryrefslogtreecommitdiff
path: root/pages/docs.inc
diff options
context:
space:
mode:
authorRaindropsSys <raindrops@equestria.dev>2023-12-17 12:23:19 +0100
committerRaindropsSys <raindrops@equestria.dev>2023-12-17 12:23:19 +0100
commit31fed783e82dd065c71b234ba08ece596a081f05 (patch)
tree9cda68ddf5b5beb9d81b0d708dfe9ed15b42945a /pages/docs.inc
parent1e5d2072fb4e257e82e2a97b4fb62e5b553b8e6d (diff)
downloadpluralconnect-31fed783e82dd065c71b234ba08ece596a081f05.tar.gz
pluralconnect-31fed783e82dd065c71b234ba08ece596a081f05.tar.bz2
pluralconnect-31fed783e82dd065c71b234ba08ece596a081f05.zip
Updated 15 files and deleted 3 files (automated)
Diffstat (limited to 'pages/docs.inc')
-rw-r--r--pages/docs.inc423
1 files changed, 0 insertions, 423 deletions
diff --git a/pages/docs.inc b/pages/docs.inc
deleted file mode 100644
index 403a4f9..0000000
--- a/pages/docs.inc
+++ /dev/null
@@ -1,423 +0,0 @@
-<?php
-
-require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages; global $_PROFILE;
-require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/random.inc";
-
-$parts = explode("/", $_GET['_']);
-$select = $parts[2] ?? null;
-
-if ($select === "add") {
- $id = random();
- file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/docs/" . $id . ".json", json_encode([
- "name" => "Untitled document ($id)",
- "category" => null,
- "contents" => "This is a new document you just created.",
- "last" => [
- "author" => $_PROFILE["login"],
- "date" => time()
- ]
- ]));
-
- header("Location: /-/docs/$id");
- die();
-} elseif (isset($select)) {
- if (ctype_alnum($select) && file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/docs/" . $select . ".json")) {
- $id = $_documentId = $select;
- $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/docs/" . $select . ".json"), true);
- $titleBase = " · " . $title . " · Ponycule";
- $title = $data["name"] . " · " . $title;
- } else {
- header("Location: /-/docs");
- die();
- }
-}
-
-require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/components/header.inc';
-
-function showDocument($item) { ?>
- <div style="display: grid; grid-template-columns: 2fr repeat(3, 1fr);">
- <span>
- <?= $item["name"] ?>
- <?php if (isset($item["nsfw"]) && $item["nsfw"]): ?>
- <span class="badge bg-danger rounded-pill">NSFW</span>
- <?php endif; ?>
- </span>
- <?php if (str_starts_with(strip_tags($item["contents"]), "/delete")): ?>
- <span class="badge bg-warning rounded-pill text-black" style="width: max-content;">Deleting in <?= round((($item["last"]["date"] + 86400) - time()) / 3600) ?> hours</span>
- <?php else: ?>
- <span class="text-muted"><?= prettySize(filesize($_SERVER['DOCUMENT_ROOT'] . "/includes/data/docs/" . $item["id"] . ".json")) ?></span>
- <span class="relative-time text-muted" data-relative-timestamp="<?= $item["last"]["date"] ?>"><?= timeAgo($item["last"]["date"]) ?></span>
- <span class="text-muted"><?= $item["last"]["author"] === "raindrops" ? "Raindrops System" : "Cloudburst System" ?></span>
- <?php endif; ?>
- </div>
-<?php }
-
-?>
-
-<br>
-<div class="container">
- <div>
- <?php if (isset($data)): ?><div id="page-content">
- <h2>
- <span contenteditable="true" id="document-name" style="outline: none;"><?= $data["name"] ?></span>
- <a href="/-/docs" class="small btn btn-outline-light" style="float:right;margin-top:5px;vertical-align:middle;opacity:1 !important; color:white;">Back</a>
- </h2>
- <p><b>Category:</b> <span id="category" contenteditable="true" style="outline: none;"><?= $data["category"] ?? "Unsorted" ?></span> · <label style="margin-bottom:5px;">
- <input <?= (isset($data["nsfw"]) && $data["nsfw"]) ? "checked" : "" ?> class="form-check-input" type="checkbox" id="explicit">
- Explicit
- </label></p>
- <p>
- <?php if ($data["last"]["date"] === 0): ?>
- Last modified <span id="last-edit-time" class="relative-time" data-relative-timestamp="">never</span>
- <?php else: ?>
- Last modified <span id="last-edit-time" class="relative-time" data-relative-timestamp="<?= $data["last"]["date"] ?>"><?= timeAgo($data["last"]["date"]) ?></span>
- <?php if ($data["last"]["author"] !== $_PROFILE["login"]): ?>
- <span id="last-edit-author">by <?= $data["last"]["author"] === "raindrops" ? "the Raindrops System" : "the Cloudburst System" ?></span>
- <?php endif; ?>
- <?php endif; ?>
- · <span id="editor-save-status" class="text-muted">Saved</span>
- </p>
-
- <?php $timeDiff = round((1800 - (time() - $data["last"]["date"])) / 60); if ($timeDiff >= 0 && $data["last"]["author"] !== $_PROFILE["login"]): ?>
- <div class="alert alert-warning">
- <b>This document is currently in use by <?= $data["last"]["author"] === "raindrops" ? "the Raindrops System" : "the Cloudburst System" ?>.</b> It has been open in read-only to prevent conflicts with the changes they make. If they stopped editing the document, it will become editable for you after you refresh the page in <?= $timeDiff ?> minute<?= $timeDiff > 1 ? "s" : "" ?>.
- </div>
- <?= $data["contents"] ?>
- <?php else: ?>
- <textarea id="editor"><?= $data["contents"] ?></textarea>
-
- <script src="/assets/editor/editor.js"></script>
- <script>
- let editor;
- ClassicEditor
- .create( document.querySelector( '#editor' ), {
- toolbar: [
- 'undo', 'redo', '|', 'removeFormat', '|', 'heading', '|', 'fontSize', 'fontColor', 'fontBackgroundColor', 'alignment', '|', 'bold', 'italic', 'underline', 'strikethrough', '|', 'subscript', 'superscript', '|', 'code', '|', 'outdent', 'indent', '|', 'bulletedList', 'numberedList', '|', 'link', 'imageUpload', 'mediaEmbed', 'blockQuote', 'insertTable', 'codeBlock', '|', 'horizontalLine'
- ]
- } )
-
- .then( newEditor => {
- editor = newEditor;
- } )
- .catch( error => {
- console.error( error );
- } );
- </script>
- <!--suppress CssUnresolvedCustomProperty -->
- <style>
- :root {
- --ck-color-base-background: transparent;
- }
-
- .ck-toolbar {
- filter: invert(1);
- border-bottom-left-radius: var(--ck-border-radius) !important;
- border-bottom-right-radius: var(--ck-border-radius) !important;
- border-bottom-width: 1px !important;
- }
-
- .ck-tooltip__text {
- color: white !important;
- }
-
- .ck-dropdown__panel {
- background: #ddd !important;
- }
-
- .ck-color-grid__tile {
- filter: invert(1);
- }
-
- .ck-balloon-rotator {
- background-color: #ccc !important;
- }
-
- .ck-balloon-panel {
- filter: invert(1);
- }
-
- .ck-editor__editable {
- border-color: transparent !important;
- }
-
- .ck.ck-sticky-panel__content_sticky {
- top: 59px !important;
- }
- </style>
- <script>
-
- let titleBase = "<?= $titleBase ?>";
- let lastSavedData = getData();
- let lastFetchedData = getData();
- let timeSinceLastModified = 0;
- let saving = false;
-
- async function save() {
- let data = editor.getData();
- document.getElementById("editor-save-status").innerHTML = "Saving...";
- document.getElementById("editor-save-status").classList.remove("text-danger");
- document.getElementById("editor-save-status").classList.remove("text-muted");
- document.getElementById("editor-save-status").classList.remove("text-warning");
- document.getElementById("editor-save-status").classList.add("text-primary");
- saving = true;
-
- try {
- await window.fetch("/api/docs?id=<?= $_documentId ?>", {
- method: "POST",
- body: JSON.stringify({ content: data, name: document.getElementById("document-name").innerText, category: document.getElementById("category").innerText, explicit: document.getElementById("explicit").checked })
- });
- document.getElementById("last-edit-time").setAttribute("data-relative-timestamp", (new Date().getTime() / 1000).toFixed(0));
- if (document.getElementById("last-edit-author")) document.getElementById("last-edit-author").outerHTML = "";
- document.title = document.getElementById("document-name").innerText + titleBase;
- document.getElementById("editor-save-status").innerHTML = "Saved";
- document.getElementById("editor-save-status").classList.remove("text-danger");
- document.getElementById("editor-save-status").classList.add("text-muted");
- document.getElementById("editor-save-status").classList.remove("text-warning");
- document.getElementById("editor-save-status").classList.remove("text-primary");
- lastSavedData = getData();
- saving = false;
- } catch (e) {
- console.error(e);
- document.getElementById("editor-save-status").innerHTML = "Failed to save";
- document.getElementById("editor-save-status").classList.add("text-danger");
- document.getElementById("editor-save-status").classList.remove("text-muted");
- document.getElementById("editor-save-status").classList.remove("text-warning");
- document.getElementById("editor-save-status").classList.remove("text-primary");
- }
- }
-
- document.onclick = async () => {
- if (saving) return;
-
- if (getData() !== lastSavedData) {
- await save();
- }
- }
-
- function getData() {
- return JSON.stringify({
- document: editor.getData(),
- name: document.getElementById("document-name").innerText,
- category: document.getElementById("category").innerText,
- explicit: document.getElementById("explicit").checked
- });
- }
-
- setInterval(async () => {
- if (saving) return;
-
- if (getData() !== lastSavedData) {
- document.getElementById("editor-save-status").innerHTML = "Modified";
- document.getElementById("editor-save-status").classList.remove("text-danger");
- document.getElementById("editor-save-status").classList.remove("text-muted");
- document.getElementById("editor-save-status").classList.add("text-warning");
- document.getElementById("editor-save-status").classList.remove("text-primary");
-
- if (getData() !== lastFetchedData) {
- lastFetchedData = getData();
- timeSinceLastModified = 0;
- } else {
- timeSinceLastModified++;
- }
-
- if (timeSinceLastModified > 20 || !document.hasFocus()) {
- await save();
- }
- } else {
- timeSinceLastModified = 0;
- }
- }, 100)
-
- </script>
- <?php endif; ?>
- </div><?php else: ?>
- <h2>Documents</h2>
- <div id="list">
- <?php
-
- $documents = array_map(function ($i) {
- return [
- "id" => substr($i, 0, -5),
- ...(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/docs/" . $i), true) ?? [])
- ];
- }, array_filter(scandir($_SERVER['DOCUMENT_ROOT'] . "/includes/data/docs"), function ($i) {
- return !str_starts_with($i, ".") && str_ends_with($i, ".json");
- }));
-
- $deletable = array_values(array_filter($documents, function ($i) {
- return str_starts_with(strip_tags($i["contents"]), "/delete");
- }));
- $unsorted_pre = array_values(array_filter($documents, function ($i) {
- return !str_starts_with(strip_tags($i["contents"]), "/delete");
- }));
-
- $categoryFirst = [];
- $unsorted = [];
- $categories = [];
- foreach ($unsorted_pre as $item) {
- if (isset($item["category"])) {
- $existing_categories = [...array_keys($categories), ...array_keys($categoryFirst)];
- $matched_category = null;
-
- foreach ($existing_categories as $existing_category) {
- if (levenshtein($item["category"], $existing_category) < 3) {
- $matched_category = $existing_category;
- }
- }
-
- $selected_category = $matched_category ?? $item["category"];
-
- if (str_starts_with($item["category"], ".")) {
- if (!isset($categoryFirst[$selected_category])) $categoryFirst[$selected_category] = [];
- $categoryFirst[$selected_category][] = $item;
- } else {
- if (!isset($categories[$selected_category])) $categories[$selected_category] = [];
- $categories[$selected_category][] = $item;
- }
- } else {
- $unsorted[] = $item;
- }
- }
-
- foreach ($categories as $category => $_) {
- uasort($categories[$category], function ($a, $b) {
- return preg_replace("/[^a-z\d]/m", "", strtolower($b["name"])) < preg_replace("/[^a-z\d]/m", "", strtolower($a["name"]));
- });
- }
-
- foreach ($categoryFirst as $category => $_) {
- uasort($categoryFirst[$category], function ($a, $b) {
- return preg_replace("/[^a-z\d]/m", "", strtolower($b["name"])) < preg_replace("/[^a-z\d]/m", "", strtolower($a["name"]));
- });
- }
-
- uasort($unsorted, function ($a, $b) {
- return preg_replace("/[^a-z\d]/m", "", strtolower($b["name"])) < preg_replace("/[^a-z\d]/m", "", strtolower($a["name"]));
- });
-
- uasort($deletable, function ($a, $b) {
- return preg_replace("/[^a-z\d]/m", "", strtolower($b["name"])) < preg_replace("/[^a-z\d]/m", "", strtolower($a["name"]));
- });
-
- $fullList = [...$categoryFirst, ...$categories];
-
- ?>
-
- <?php foreach ($fullList as $category => $items): if ($category != "Archives"): ?>
- <h4><?= str_starts_with($category, ".") ? substr($category, 1) : $category ?></h4><div class="list-group">
- <?php foreach ($items as $item): ?>
- <a href="/-/docs/<?= $item["id"] ?>" id="document-<?= $item["id"] ?>" class="list-group-item list-group-item-action document-listing <?php if (str_starts_with(strip_tags($item["contents"]), "/delete")): ?>opacity-75<?php endif; ?>">
- <?php showDocument($item) ?>
- </a>
- <?php endforeach; ?></div>
- <hr>
- <?php endif; endforeach; ?>
-
- <h4>Unsorted</h4><div class="list-group">
- <?php foreach ($unsorted as $item): ?>
- <a href="/-/docs/<?= $item["id"] ?>" id="document-<?= $item["id"] ?>" class="list-group-item list-group-item-action document-listing <?php if (str_starts_with(strip_tags($item["contents"]), "/delete")): ?>opacity-75<?php endif; ?>">
- <?php showDocument($item) ?>
- </a>
- <?php endforeach; ?></div>
-
- <hr>
- <details>
- <summary>Show archives and marked for deletion</summary>
-
- <h4 style="margin-top: 10px;">Archives</h4>
- <div class="list-group">
- <?php foreach ($categories["Archives"] as $item): ?>
- <a href="/-/docs/<?= $item["id"] ?>" id="document-<?= $item["id"] ?>" class="list-group-item list-group-item-action document-listing <?php if (str_starts_with(strip_tags($item["contents"]), "/delete")): ?>opacity-75<?php endif; ?>">
- <?php showDocument($item) ?>
- </a>
- <?php endforeach; ?></div>
-
- <hr>
- <h4 id="deletable">Marked for deletion</h4><div class="list-group">
- <?php foreach ($deletable as $item): ?>
- <a href="/-/docs/<?= $item["id"] ?>" id="document-<?= $item["id"] ?>" class="list-group-item list-group-item-action document-listing <?php if (str_starts_with(strip_tags($item["contents"]), "/delete")): ?>opacity-75<?php endif; ?>">
- <?php showDocument($item) ?>
- </a>
- <?php endforeach; ?></div>
- </details>
- </div>
-
- <hr>
- <div id="page-content">
- <a href="/-/docs/add">Create a new document</a>
- </div>
- <?php endif; ?>
- </div>
-</div>
-
-<script>
- setInterval(async () => {
- Array.from(document.getElementsByClassName("relative-time")).forEach((el) => {
- el.innerText = timeAgo(parseInt(el.getAttribute("data-relative-timestamp")) * 1000);
- })
- }, 1000)
-
- function timeAgo(time) {
- if (!isNaN(parseInt(time))) {
- time = new Date(time).getTime();
- }
-
- let periods = ["sec", "min", "hr", "d", "wk", "mo", "y", "ages"];
-
- let lengths = ["60", "60", "24", "7", "4.35", "12", "100"];
-
- let now = new Date().getTime();
-
- let difference = Math.round((now - time) / 1000);
- let tense;
- let period;
-
- if (difference <= 10 && difference >= 0) {
- return "now";
- } else if (difference > 0) {
- tense = "ago";
- } else {
- tense = "later";
- }
-
- let j;
-
- for (j = 0; difference >= lengths[j] && j < lengths.length - 1; j++) {
- difference /= lengths[j];
- }
-
- difference = Math.round(difference);
-
- period = periods[j];
-
- return `${difference} ${period} ${tense}`;
- }
-</script>
-<style>
- <?php global $use2023UI; if (!$use2023UI): ?>
- .list-group-item {
- color: #fff;
- background-color: #222;
- border: 1px solid rgba(255, 255, 255, .125);
- }
-
- .list-group-item.disabled {
- color: #fff;
- background-color: #222;
- border-color: rgba(255, 255, 255, .125);
- opacity: .75;
- }
-
- .list-group-item:hover {
- background-color: #252525;
- color: #ddd;
- }
-
- .list-group-item:active, .list-group-item:focus {
- background-color: #272727;
- color: #bbb;
- }
- <?php endif; ?>
-</style>
-
-<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/components/footer.inc'; ?>