changelog updates
This commit is contained in:
parent
80f9c7d0dc
commit
074a89e6b1
18 changed files with 869 additions and 16 deletions
47
assets/less/manage/classes/changelog-change.less
Normal file
47
assets/less/manage/classes/changelog-change.less
Normal file
|
@ -0,0 +1,47 @@
|
|||
.changelog-change {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
|
||||
&__datetime,
|
||||
&__text {
|
||||
margin: 2px 5px;
|
||||
}
|
||||
|
||||
&__text {
|
||||
font-size: 1.2em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
&__tags {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
&__tag {
|
||||
padding: 2px 5px;
|
||||
margin: 1px;
|
||||
background-color: #444;
|
||||
border-radius: 2px;
|
||||
|
||||
&--dark {
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
&__contributor {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__avatar {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
&__username {
|
||||
font-size: 1.2em;
|
||||
margin: 2px 5px;
|
||||
}
|
||||
}
|
27
assets/less/manage/classes/changelog-tags.less
Normal file
27
assets/less/manage/classes/changelog-tags.less
Normal file
|
@ -0,0 +1,27 @@
|
|||
.changelog-tags {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
|
||||
&__entry {
|
||||
margin: 2px;
|
||||
width: 296px;
|
||||
}
|
||||
|
||||
&__content {
|
||||
height: 100%;
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&__text {
|
||||
font-size: 1.2em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
&__description {
|
||||
font-size: .9em;
|
||||
}
|
||||
}
|
|
@ -30,3 +30,6 @@ body {
|
|||
@import "classes/pagination";
|
||||
|
||||
@import "classes/user-listing";
|
||||
|
||||
@import "classes/changelog-change";
|
||||
@import "classes/changelog-tags";
|
||||
|
|
|
@ -47,8 +47,10 @@ function migrate_up(PDO $conn): void
|
|||
`tag_name` VARCHAR(255) NOT NULL,
|
||||
`tag_description` TEXT NULL,
|
||||
`tag_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`tag_archived` TIMESTAMP NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`tag_id`),
|
||||
UNIQUE INDEX `tag_name` (`tag_name`)
|
||||
UNIQUE INDEX `tag_name` (`tag_name`),
|
||||
INDEX `tag_archived` (`tag_archived`)
|
||||
)
|
||||
");
|
||||
|
||||
|
@ -56,8 +58,8 @@ function migrate_up(PDO $conn): void
|
|||
CREATE TABLE `msz_changelog_change_tags` (
|
||||
`change_id` INT(10) UNSIGNED NOT NULL,
|
||||
`tag_id` INT(10) UNSIGNED NOT NULL,
|
||||
INDEX `tag_id_foreign_key` (`tag_id`),
|
||||
INDEX `change_tag_constraint` (`change_id`, `tag_id`),
|
||||
INDEX `tag_id_foreign_key` (`tag_id`),
|
||||
UNIQUE INDEX `change_tag_unique` (`change_id`, `tag_id`),
|
||||
CONSTRAINT `change_id_foreign_key`
|
||||
FOREIGN KEY (`change_id`)
|
||||
REFERENCES `msz_changelog_changes` (`change_id`)
|
||||
|
|
369
public/manage/changelog.php
Normal file
369
public/manage/changelog.php
Normal file
|
@ -0,0 +1,369 @@
|
|||
<?php
|
||||
use Misuzu\Database;
|
||||
|
||||
require_once __DIR__ . '/../../misuzu.php';
|
||||
|
||||
$db = Database::connection();
|
||||
$tpl = $app->getTemplating();
|
||||
|
||||
$queryOffset = (int)($_GET['o'] ?? 0);
|
||||
|
||||
switch ($_GET['v'] ?? null) {
|
||||
case 'changes':
|
||||
$changesTake = 20;
|
||||
|
||||
$changesCount = (int)$db->query('
|
||||
SELECT COUNT(`change_id`)
|
||||
FROM `msz_changelog_changes`
|
||||
')->fetchColumn();
|
||||
|
||||
$getChanges = $db->prepare('
|
||||
SELECT
|
||||
c.`change_id`, c.`change_log`, c.`change_created`,
|
||||
a.`action_name`, a.`action_colour`, a.`action_class`,
|
||||
u.`user_id`, u.`username`,
|
||||
COALESCE(r.`role_colour`, CAST(0x40000000 AS UNSIGNED)) as `user_colour`
|
||||
FROM `msz_changelog_changes` as c
|
||||
LEFT JOIN `msz_changelog_actions` as a
|
||||
ON a.`action_id` = c.`action_id`
|
||||
LEFT JOIN `msz_users` as u
|
||||
ON u.`user_id` = c.`user_id`
|
||||
LEFT JOIN `msz_roles` as r
|
||||
ON r.`role_id` = u.`display_role`
|
||||
ORDER BY c.`change_id` DESC
|
||||
LIMIT :offset, :take
|
||||
');
|
||||
$getChanges->bindValue('take', $changesTake);
|
||||
$getChanges->bindValue('offset', $queryOffset);
|
||||
$changes = $getChanges->execute() ? $getChanges->fetchAll(PDO::FETCH_ASSOC) : [];
|
||||
|
||||
$getTags = $db->prepare('
|
||||
SELECT
|
||||
t.`tag_id`, t.`tag_name`, t.`tag_description`
|
||||
FROM `msz_changelog_change_tags` as ct
|
||||
LEFT JOIN `msz_changelog_tags` as t
|
||||
ON t.`tag_id` = ct.`tag_id`
|
||||
WHERE ct.`change_id` = :change_id
|
||||
');
|
||||
|
||||
// grab tags
|
||||
for ($i = 0; $i < count($changes); $i++) {
|
||||
$getTags->bindValue('change_id', $changes[$i]['change_id']);
|
||||
$changes[$i]['tags'] = $getTags->execute() ? $getTags->fetchAll(PDO::FETCH_ASSOC) : [];
|
||||
}
|
||||
|
||||
echo $tpl->render('@manage.changelog.changes', [
|
||||
'changelog_changes' => $changes,
|
||||
'changelog_changes_count' => $changesCount,
|
||||
'changelog_offset' => $queryOffset,
|
||||
'changelog_take' => $changesTake,
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'change':
|
||||
$changeId = (int)($_GET['c'] ?? 0);
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && tmp_csrf_verify($_POST['csrf'] ?? '')) {
|
||||
if (!empty($_POST['change']) && is_array($_POST['change'])) {
|
||||
if ($changeId > 0) {
|
||||
$postChange = $db->prepare('
|
||||
UPDATE `msz_changelog_changes`
|
||||
SET `change_log` = :log,
|
||||
`change_text` = :text,
|
||||
`action_id` = :action,
|
||||
`user_id` = :user,
|
||||
`change_created` = :created
|
||||
WHERE `change_id` = :change_id
|
||||
');
|
||||
$postChange->bindValue('change_id', $changeId);
|
||||
} else {
|
||||
$postChange = $db->prepare('
|
||||
INSERT INTO `msz_changelog_changes`
|
||||
(`change_log`, `change_text`, `action_id`, `user_id`, `change_created`)
|
||||
VALUES
|
||||
(:log, :text, :action, :user, :created)
|
||||
');
|
||||
}
|
||||
|
||||
$postChange->bindValue('log', $_POST['change']['log']);
|
||||
$postChange->bindValue('action', $_POST['change']['action']);
|
||||
$postChange->bindValue('text', strlen($_POST['change']['text'])
|
||||
? $_POST['change']['text']
|
||||
: null);
|
||||
$postChange->bindValue('user', is_numeric($_POST['change']['user'])
|
||||
? $_POST['change']['user']
|
||||
: null);
|
||||
$postChange->bindValue('created', strlen($_POST['change']['created'])
|
||||
? $_POST['change']['created']
|
||||
: null);
|
||||
$postChange->execute();
|
||||
|
||||
if ($changeId < 1) {
|
||||
header('Location: ?v=change&c=' . $db->lastInsertId());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($_POST['add_tag']) && is_numeric($_POST['add_tag'])) {
|
||||
$addTag = $db->prepare('REPLACE INTO `msz_changelog_change_tags` VALUES (:change_id, :tag_id)');
|
||||
$addTag->bindValue('change_id', $changeId);
|
||||
$addTag->bindValue('tag_id', $_POST['add_tag']);
|
||||
$addTag->execute();
|
||||
}
|
||||
|
||||
if (!empty($_POST['remove_tag']) && is_numeric($_POST['remove_tag'])) {
|
||||
$removeTag = $db->prepare('
|
||||
DELETE FROM `msz_changelog_change_tags`
|
||||
WHERE `change_id` = :change_id
|
||||
AND `tag_id` = :tag_id
|
||||
');
|
||||
$removeTag->bindValue('change_id', $changeId);
|
||||
$removeTag->bindValue('tag_id', $_POST['remove_tag']);
|
||||
$removeTag->execute();
|
||||
}
|
||||
}
|
||||
|
||||
$actions = $db->query('
|
||||
SELECT `action_id`, `action_name`
|
||||
FROM `msz_changelog_actions`
|
||||
')->fetchAll(PDO::FETCH_ASSOC);
|
||||
$tpl->var('changelog_actions', $actions);
|
||||
|
||||
if ($changeId > 0) {
|
||||
$getChange = $db->prepare('
|
||||
SELECT `change_id`, `change_log`, `change_text`, `user_id`, `action_id`, `change_created`
|
||||
FROM `msz_changelog_changes`
|
||||
WHERE `change_id` = :change_id
|
||||
');
|
||||
$getChange->bindValue('change_id', $changeId);
|
||||
$change = $getChange->execute() ? $getChange->fetch(PDO::FETCH_ASSOC) : [];
|
||||
|
||||
if ($change) {
|
||||
$tpl->var('edit_change', $change);
|
||||
|
||||
$assignedTags = $db->prepare('
|
||||
SELECT `tag_id`, `tag_name`
|
||||
FROM `msz_changelog_tags`
|
||||
WHERE `tag_id` IN (
|
||||
SELECT `tag_id`
|
||||
FROM `msz_changelog_change_tags`
|
||||
WHERE `change_id` = :change_id
|
||||
)
|
||||
');
|
||||
$assignedTags->bindValue('change_id', $change['change_id']);
|
||||
$assignedTags = $assignedTags->execute() ? $assignedTags->fetchAll(PDO::FETCH_ASSOC) : [];
|
||||
|
||||
$availableTags = $db->prepare('
|
||||
SELECT `tag_id`, `tag_name`
|
||||
FROM `msz_changelog_tags`
|
||||
WHERE `tag_id` NOT IN (
|
||||
SELECT `tag_id`
|
||||
FROM `msz_changelog_change_tags`
|
||||
WHERE `change_id` = :change_id
|
||||
)
|
||||
AND `tag_archived` IS NULL
|
||||
');
|
||||
$availableTags->bindValue('change_id', $change['change_id']);
|
||||
$availableTags = $availableTags->execute() ? $availableTags->fetchAll(PDO::FETCH_ASSOC) : [];
|
||||
|
||||
$tpl->vars([
|
||||
'edit_change_assigned_tags' => $assignedTags,
|
||||
'edit_change_available_tags' => $availableTags,
|
||||
]);
|
||||
} else {
|
||||
header('Location: ?v=changes');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
echo $tpl->render('@manage.changelog.change_edit');
|
||||
break;
|
||||
|
||||
case 'tags':
|
||||
$tagsTake = 32;
|
||||
|
||||
$tagsCount = (int)$db->query('
|
||||
SELECT COUNT(`tag_id`)
|
||||
FROM `msz_changelog_tags`
|
||||
')->fetchColumn();
|
||||
|
||||
$getTags = $db->prepare('
|
||||
SELECT
|
||||
t.`tag_id`, t.`tag_name`, t.`tag_description`, t.`tag_created`,
|
||||
(
|
||||
SELECT COUNT(ct.`change_id`)
|
||||
FROM `msz_changelog_change_tags` as ct
|
||||
WHERE ct.`tag_id` = t.`tag_id`
|
||||
) as `tag_count`
|
||||
FROM `msz_changelog_tags` as t
|
||||
ORDER BY t.`tag_id` ASC
|
||||
LIMIT :offset, :take
|
||||
');
|
||||
$getTags->bindValue('take', $tagsTake);
|
||||
$getTags->bindValue('offset', $queryOffset);
|
||||
$tags = $getTags->execute() ? $getTags->fetchAll(PDO::FETCH_ASSOC) : [];
|
||||
|
||||
echo $tpl->render('@manage.changelog.tags', [
|
||||
'changelog_tags' => $tags,
|
||||
'changelog_tags_count' => $tagsCount,
|
||||
'changelog_take' => $tagsTake,
|
||||
'changelog_offset' => $queryOffset,
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'tag':
|
||||
$tagId = (int)($_GET['t'] ?? 0);
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && tmp_csrf_verify($_POST['csrf'] ?? '')) {
|
||||
if (!empty($_POST['tag']) && is_array($_POST['tag'])) {
|
||||
if ($tagId > 0) {
|
||||
$updateTag = $db->prepare('
|
||||
UPDATE `msz_changelog_tags`
|
||||
SET `tag_name` = :name,
|
||||
`tag_description` = :description,
|
||||
`tag_archived` = :archived
|
||||
WHERE `tag_id` = :id
|
||||
');
|
||||
$updateTag->bindValue('id', $tagId);
|
||||
} else {
|
||||
$updateTag = $db->prepare('
|
||||
INSERT INTO `msz_changelog_tags`
|
||||
(`tag_name`, `tag_description`, `tag_archived`)
|
||||
VALUES
|
||||
(:name, :description, :archived)
|
||||
');
|
||||
}
|
||||
|
||||
$updateTag->bindValue('name', $_POST['tag']['name']);
|
||||
$updateTag->bindValue('description', $_POST['tag']['description']);
|
||||
$updateTag->bindValue('archived', empty($_POST['tag']['description']) ? null : date('Y-m-d H:i:s'));
|
||||
$updateTag->execute();
|
||||
|
||||
if ($tagId < 1) {
|
||||
header('Location: ?v=tag&t=' . $db->lastInsertId());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($tagId > 0) {
|
||||
$getTag = $db->prepare('
|
||||
SELECT `tag_id`, `tag_name`, `tag_description`, `tag_archived`, `tag_created`
|
||||
FROM `msz_changelog_tags`
|
||||
WHERE `tag_id` = :tag_id
|
||||
');
|
||||
$getTag->bindValue('tag_id', $tagId);
|
||||
$tag = $getTag->execute() ? $getTag->fetch(PDO::FETCH_ASSOC) : [];
|
||||
|
||||
if ($tag) {
|
||||
$tpl->var('edit_tag', $tag);
|
||||
} else {
|
||||
header('Location: ?v=tags');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
echo $tpl->render('@manage.changelog.tag_edit');
|
||||
break;
|
||||
|
||||
case 'actions':
|
||||
$actionTake = 32;
|
||||
|
||||
$actionCount = (int)$db->query('
|
||||
SELECT COUNT(`action_id`)
|
||||
FROM `msz_changelog_actions`
|
||||
')->fetchColumn();
|
||||
|
||||
$getActions = $db->prepare('
|
||||
SELECT
|
||||
a.`action_id`, a.`action_name`, a.`action_colour`,
|
||||
(
|
||||
SELECT COUNT(c.`action_id`)
|
||||
FROM `msz_changelog_changes` as c
|
||||
WHERE c.`action_id` = a.`action_id`
|
||||
) as `action_count`
|
||||
FROM `msz_changelog_actions` as a
|
||||
ORDER BY a.`action_id` ASC
|
||||
LIMIT :offset, :take
|
||||
');
|
||||
$getActions->bindValue('take', $actionTake);
|
||||
$getActions->bindValue('offset', $queryOffset);
|
||||
$actions = $getActions->execute() ? $getActions->fetchAll(PDO::FETCH_ASSOC) : [];
|
||||
|
||||
echo $tpl->render('@manage.changelog.actions', [
|
||||
'changelog_actions' => $actions,
|
||||
'changelog_actions_count' => $actionTake,
|
||||
'changelog_take' => $actionTake,
|
||||
'changelog_offset' => $queryOffset,
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'action':
|
||||
$actionId = (int)($_GET['a'] ?? 0);
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && tmp_csrf_verify($_POST['csrf'] ?? '')) {
|
||||
if (!empty($_POST['action']) && is_array($_POST['action'])) {
|
||||
if ($actionId > 0) {
|
||||
$updateAction = $db->prepare('
|
||||
UPDATE `msz_changelog_actions`
|
||||
SET `action_name` = :name,
|
||||
`action_colour` = :colour,
|
||||
`action_class` = :class
|
||||
WHERE `action_id` = :id
|
||||
');
|
||||
$updateAction->bindValue('id', $actionId);
|
||||
} else {
|
||||
$updateAction = $db->prepare('
|
||||
INSERT INTO `msz_changelog_actions`
|
||||
(`action_name`, `action_colour`, `action_class`)
|
||||
VALUES
|
||||
(:name, :colour, :class)
|
||||
');
|
||||
}
|
||||
|
||||
$actionColour = colour_create();
|
||||
|
||||
if (!empty($_POST['action']['colour']['inherit'])) {
|
||||
colour_set_inherit($actionColour);
|
||||
} else {
|
||||
colour_set_red($actionColour, $_POST['action']['colour']['red']);
|
||||
colour_set_green($actionColour, $_POST['action']['colour']['green']);
|
||||
colour_set_blue($actionColour, $_POST['action']['colour']['blue']);
|
||||
}
|
||||
|
||||
$updateAction->bindValue('name', $_POST['action']['name']);
|
||||
$updateAction->bindValue('colour', $actionColour);
|
||||
$updateAction->bindValue('class', $_POST['action']['class']);
|
||||
$updateAction->execute();
|
||||
|
||||
if ($actionId < 1) {
|
||||
header('Location: ?v=action&a=' . $db->lastInsertId());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($actionId > 0) {
|
||||
$getAction = $db->prepare('
|
||||
SELECT `action_id`, `action_name`, `action_colour`, `action_class`
|
||||
FROM `msz_changelog_actions`
|
||||
WHERE `action_id` = :action_id
|
||||
');
|
||||
$getAction->bindValue('action_id', $actionId);
|
||||
$action = $getAction->execute() ? $getAction->fetch(PDO::FETCH_ASSOC) : [];
|
||||
|
||||
if ($action) {
|
||||
$tpl->var('edit_action', $action);
|
||||
} else {
|
||||
header('Location: ?v=actions');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
echo $tpl->render('@manage.changelog.action_edit');
|
||||
break;
|
||||
|
||||
default:
|
||||
header('Location: ?v=changes');
|
||||
break;
|
||||
}
|
|
@ -20,7 +20,7 @@ switch ($_GET['v'] ?? null) {
|
|||
echo 'somewhat soon i guess';
|
||||
break;
|
||||
|
||||
case null:
|
||||
default:
|
||||
header('Location: ?v=overview');
|
||||
break;
|
||||
}
|
||||
|
|
63
views/manage/changelog/action_edit.twig
Normal file
63
views/manage/changelog/action_edit.twig
Normal file
|
@ -0,0 +1,63 @@
|
|||
{% extends '@manage/changelog/master.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<form action="?v=action{{ edit_action is defined ? '&a=' ~ edit_action.action_id : '' }}" method="post">
|
||||
<h1 class="container__title">
|
||||
{% if edit_action is defined %}
|
||||
Editing <span style="{{ edit_action.action_colour|html_colour }}">{{ edit_action.action_name }}</span> ({{ edit_action.action_id }})
|
||||
{% else %}
|
||||
Adding a new action
|
||||
{% endif %}
|
||||
</h1>
|
||||
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Name</div>
|
||||
<div class="form__label__input">
|
||||
<input class="input input--text" type="text" value="{{ edit_action is defined ? edit_action.action_name : '' }}" name="action[name]" maxlength="50">
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Class</div>
|
||||
<div class="form__label__input">
|
||||
<input class="input input--text" type="text" value="{{ edit_action is defined ? edit_action.action_class : '' }}" name="action[class]" maxlength="20">
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<h2 class="container__subtitle">Colour</h2>
|
||||
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Inherit Colour</div>
|
||||
<div class="form__label__input">
|
||||
<input class="input" type="checkbox" name="action[colour][inherit]"{% if edit_action is defined and edit_action.action_colour|colour_get_inherit %} checked{% endif %}>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Red</div>
|
||||
<div class="form__label__input">
|
||||
<input class="input input--number" type="number" value="{{ edit_action is defined ? edit_action.action_colour|colour_get_red : '0' }}" min="0" max="255" name="action[colour][red]">
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Green</div>
|
||||
<div class="form__label__input">
|
||||
<input class="input input--number" type="number" value="{{ edit_action is defined ? edit_action.action_colour|colour_get_green : '0' }}" min="0" max="255" name="action[colour][green]">
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Blue</div>
|
||||
<div class="form__label__input">
|
||||
<input class="input input--number" type="number" value="{{ edit_action is defined ? edit_action.action_colour|colour_get_blue : '0' }}" min="0" max="255" name="action[colour][blue]">
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<div>
|
||||
<button class="button" name="csrf" value="{{ csrf_token() }}">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
25
views/manage/changelog/actions.twig
Normal file
25
views/manage/changelog/actions.twig
Normal file
|
@ -0,0 +1,25 @@
|
|||
{% extends '@manage/changelog/master.twig' %}
|
||||
{% from '@manage/macros.twig' import pagination %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<a href="?v=action" class="button">Create new action</a>
|
||||
</div>
|
||||
|
||||
<div class="container listing changelog-tags">
|
||||
{% for action in changelog_actions %}
|
||||
<a href="?v=action&a={{ action.action_id }}" class="listing__entry changelog-tags__entry"
|
||||
style="{{ action.action_colour|html_colour({'border-color':'%s'}) }}">
|
||||
<div class="listing__entry__content changelog-tags__content">
|
||||
<div class="changelog-tags__text">
|
||||
{{ action.action_name }} ({{ action.action_count }})
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="container container--center">
|
||||
{{ pagination(changelog_actions_count, changelog_take, changelog_offset, '?v=actions') }}
|
||||
</div>
|
||||
{% endblock %}
|
108
views/manage/changelog/change_edit.twig
Normal file
108
views/manage/changelog/change_edit.twig
Normal file
|
@ -0,0 +1,108 @@
|
|||
{% extends '@manage/changelog/master.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<form action="?v=change{{ edit_change is defined ? '&c=' ~ edit_change.change_id : '' }}" method="post">
|
||||
<h1 class="container__title">
|
||||
{% if edit_change is defined %}
|
||||
Editing #{{ edit_change.change_id }}
|
||||
{% else %}
|
||||
Adding a new change
|
||||
{% endif %}
|
||||
</h1>
|
||||
|
||||
<label class="form__label" style="width:100%">
|
||||
<div class="form__label__text">Log</div>
|
||||
<div class="form__label__input">
|
||||
<input class="input input--text" type="text" value="{{ edit_change is defined ? edit_change.change_log : '' }}" name="change[log]" maxlength="255">
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="form__label" style="width:100%">
|
||||
<div class="form__label__text">Text</div>
|
||||
<div class="form__label__input">
|
||||
<textarea class="input input--textarea" name="change[text]" maxlength="65535">{{ edit_change is defined ? edit_change.change_text : '' }}</textarea>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Action</div>
|
||||
<div class="form__label__input">
|
||||
<select name="change[action]" class="input input--select">
|
||||
{% for action in changelog_actions %}
|
||||
<option value="{{ action.action_id }}"{% if edit_change is defined and action.action_id == edit_change.action_id %} selected{% endif %}>
|
||||
{{ action.action_name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Contributor Id</div>
|
||||
<div class="form__label__input">
|
||||
<input class="input input--text" type="number" value="{{ edit_change is defined ? edit_change.user_id : current_user.user_id }}" name="change[user]" min="1">
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Created</div>
|
||||
<div class="form__label__input">
|
||||
<input class="input input--text" type="text" value="{{ edit_change is defined ? edit_change.change_created : ''|date('Y-m-d H:i:s') }}" name="change[created]">
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<div>
|
||||
<button class="button" name="csrf" value="{{ csrf_token() }}">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% if edit_change is defined %}
|
||||
<h1 class="container__title">
|
||||
Tags
|
||||
</h1>
|
||||
|
||||
{% if edit_change_assigned_tags|length > 0 %}
|
||||
<form class="container" method="post" action="" style="display:inline-block">
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Assigned Tags</div>
|
||||
<div class="form__label__input">
|
||||
<select name="remove_tag" class="input input--select">
|
||||
{% for tag in edit_change_assigned_tags %}
|
||||
<option value="{{ tag.tag_id }}">
|
||||
{{ tag.tag_name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<div>
|
||||
<button class="button" name="csrf" value="{{ csrf_token() }}">Remove</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% if edit_change_available_tags|length > 0 %}
|
||||
<form class="container" method="post" action="" style="display:inline-block">
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Available Tags</div>
|
||||
<div class="form__label__input">
|
||||
<select name="add_tag" class="input input--select">
|
||||
{% for tag in edit_change_available_tags %}
|
||||
<option value="{{ tag.tag_id }}">
|
||||
{{ tag.tag_name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<div>
|
||||
<button class="button" name="csrf" value="{{ csrf_token() }}">Add</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
54
views/manage/changelog/changes.twig
Normal file
54
views/manage/changelog/changes.twig
Normal file
|
@ -0,0 +1,54 @@
|
|||
{% extends '@manage/changelog/master.twig' %}
|
||||
{% from '@manage/macros.twig' import pagination %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<a href="?v=change" class="button">Create new change</a>
|
||||
</div>
|
||||
|
||||
<div class="container listing">
|
||||
{% for change in changelog_changes %}
|
||||
<a href="?v=change&c={{ change.change_id }}" class="listing__entry" style="{{ change.action_colour|html_colour({'border-color':'%s'}) }}">
|
||||
<div class="listing__entry__content changelog-change">
|
||||
<div class="changelog-change__change">
|
||||
<div class="changelog-change__text">
|
||||
{{ change.change_log }}
|
||||
</div>
|
||||
|
||||
<time class="changelog-change__datetime"
|
||||
datetime="{{ change.change_created|date('c') }}"
|
||||
title="{{ change.change_created|date('r') }}">
|
||||
{{ change.change_created|time_diff }}
|
||||
</time>
|
||||
|
||||
<ul class="changelog-change__tags">
|
||||
<li style="{{ change.action_colour|html_colour({'background-color':'%s'}) }}"
|
||||
class="changelog-change__tag changelog-change__tag--{{ change.action_colour|colour_get_css_contrast }}">
|
||||
{{ change.action_name }}
|
||||
</li>
|
||||
|
||||
{% for tag in change.tags %}
|
||||
<li class="changelog-change__tag">{{ tag.tag_name }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="changelog-change__contributor">
|
||||
<div class="changelog-change__username"
|
||||
style="{{ change.user_colour|html_colour }}">
|
||||
{{ change.username }}
|
||||
</div>
|
||||
|
||||
<div class="avatar changelog-change__avatar"
|
||||
style="background-image:url('/profile.php?u={{ change.user_id }}&m=avatar')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="container container--center">
|
||||
{{ pagination(changelog_changes_count, changelog_take, changelog_offset, '?v=changes') }}
|
||||
</div>
|
||||
{% endblock %}
|
1
views/manage/changelog/master.twig
Normal file
1
views/manage/changelog/master.twig
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends '@manage/master.twig' %}
|
97
views/manage/changelog/tag_edit.twig
Normal file
97
views/manage/changelog/tag_edit.twig
Normal file
|
@ -0,0 +1,97 @@
|
|||
{% extends '@manage/changelog/master.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<form action="?v=tag{{ edit_tag is defined ? '&t=' ~ edit_tag.tag_id : '' }}" method="post">
|
||||
<h1 class="container__title">
|
||||
{% if edit_tag is defined %}
|
||||
Editing {{ edit_tag.tag_name }} ({{ edit_tag.tag_id }})
|
||||
{% else %}
|
||||
Adding a new tag
|
||||
{% endif %}
|
||||
</h1>
|
||||
|
||||
<label class="form__label" style="width:100%">
|
||||
<div class="form__label__text">Name</div>
|
||||
<div class="form__label__input">
|
||||
<input class="input input--text" type="text" value="{{ edit_tag is defined ? edit_tag.tag_name : '' }}" name="tag[name]" maxlength="255">
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="form__label" style="width:100%">
|
||||
<div class="form__label__text">Description</div>
|
||||
<div class="form__label__input">
|
||||
<textarea class="input input--textarea" name="tag[description]" maxlength="65535">{{ edit_tag is defined ? edit_tag.tag_description : '' }}</textarea>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Archived</div>
|
||||
<div class="form__label__input">
|
||||
<input class="input" type="checkbox" name="tag[archived]"{% if edit_role is defined and edit_role.tag_archived is not null %} checked{% endif %}>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
{% if edit_tag is defined %}
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Created</div>
|
||||
<div class="form__label__input">
|
||||
<input class="input input--text" type="text" value="{{ edit_tag.tag_created }}" readonly>
|
||||
</div>
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
<button class="button" name="csrf" value="{{ csrf_token() }}">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% if edit_change is defined %}
|
||||
<h1 class="container__title">
|
||||
Tags
|
||||
</h1>
|
||||
|
||||
{% if edit_change_assigned_tags|length > 0 %}
|
||||
<form class="container" method="post" action="" style="display:inline-block">
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Assigned Tags</div>
|
||||
<div class="form__label__input">
|
||||
<select name="remove_tag" class="input input--select">
|
||||
{% for tag in edit_change_assigned_tags %}
|
||||
<option value="{{ tag.tag_id }}">
|
||||
{{ tag.tag_name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<div>
|
||||
<button class="button" name="csrf" value="{{ csrf_token() }}">Remove</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% if edit_change_available_tags|length > 0 %}
|
||||
<form class="container" method="post" action="" style="display:inline-block">
|
||||
<label class="form__label">
|
||||
<div class="form__label__text">Available Tags</div>
|
||||
<div class="form__label__input">
|
||||
<select name="add_tag" class="input input--select">
|
||||
{% for tag in edit_change_available_tags %}
|
||||
<option value="{{ tag.tag_id }}">
|
||||
{{ tag.tag_name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<div>
|
||||
<button class="button" name="csrf" value="{{ csrf_token() }}">Add</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
28
views/manage/changelog/tags.twig
Normal file
28
views/manage/changelog/tags.twig
Normal file
|
@ -0,0 +1,28 @@
|
|||
{% extends '@manage/changelog/master.twig' %}
|
||||
{% from '@manage/macros.twig' import pagination %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<a href="?v=tag" class="button">Create new tag</a>
|
||||
</div>
|
||||
|
||||
<div class="container listing changelog-tags">
|
||||
{% for tag in changelog_tags %}
|
||||
<a href="?v=tag&t={{ tag.tag_id }}" class="listing__entry changelog-tags__entry">
|
||||
<div class="listing__entry__content changelog-tags__content">
|
||||
<div class="changelog-tags__text">
|
||||
{{ tag.tag_name }} ({{ tag.tag_count }})
|
||||
</div>
|
||||
|
||||
<div class="changelog-tags__description">
|
||||
{{ tag.tag_description }}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="container container--center">
|
||||
{{ pagination(changelog_tags_count, changelog_take, changelog_offset, '?v=tags') }}
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,9 +1,3 @@
|
|||
{% macro link(url, content, class) %}
|
||||
{% spaceless %}
|
||||
<a href="{{ url }}" {% if '://' in url %} target="_blank" rel="noreferrer noopener"{% endif %} {% if class is defined %}class="{{ class }}"{% endif %}>{{ content|raw }}</a>
|
||||
{% endspaceless %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro pagination_segment(url_window, base_url, currentPage) %}
|
||||
{% for page, url in url_window %}
|
||||
<li class="pagination__option{{ currentPage == page ? ' pagination__option--active' : '' }}">
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
{% from '@manage/macros.twig' import link %}
|
||||
|
||||
{% set menus = [
|
||||
{
|
||||
'name': 'general',
|
||||
|
@ -96,6 +94,29 @@
|
|||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
'name': 'changelog',
|
||||
'title': 'Changelog',
|
||||
'sections': [
|
||||
[
|
||||
{
|
||||
'name': 'changes',
|
||||
'title': 'Changes',
|
||||
'url': '/manage/changelog.php?v=changes',
|
||||
},
|
||||
{
|
||||
'name': 'tags',
|
||||
'title': 'Tags',
|
||||
'url': '/manage/changelog.php?v=tags',
|
||||
},
|
||||
{
|
||||
'name': 'actions',
|
||||
'title': 'Actions',
|
||||
'url': '/manage/changelog.php?v=actions',
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
] %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
@ -160,11 +181,20 @@
|
|||
{% endblock %}
|
||||
|
||||
<footer class="footer">
|
||||
{{ link('https://flash.moe', 'flash.moe', 'footer__link') }} 2013-{{
|
||||
{{ 'https://flash.moe'|html_link('Flashwave', 'footer__link')|raw }} 2013-{{
|
||||
''|date('Y') }} /
|
||||
{{ link('https://github.com/flashwave/misuzu/tree/' ~ git_branch(), git_branch(), 'footer__link') }} # {{ link('https://github.com/flashwave/misuzu/commit/' ~ git_hash(true), git_hash(), 'footer__link') }}
|
||||
<span title="{{ git_hash(true) }}">
|
||||
{{ git_branch() }} # {{ git_hash() }}
|
||||
</span>
|
||||
{# link('https://github.com/flashwave/misuzu/tree/' ~ git_branch(), git_branch(), 'footer__link') }} # {{ link('https://github.com/flashwave/misuzu/commit/' ~ git_hash(true), git_hash(), 'footer__link') #}
|
||||
</footer>
|
||||
</div>
|
||||
<script src="/js/libraries.js" charset="utf-8"></script>
|
||||
<script>
|
||||
window.addEventListener('load', () => {
|
||||
timeago().render(document.querySelectorAll('time'));
|
||||
hljs.initHighlighting();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
{% if is_valid %}
|
||||
{% set canonical_url = '/changelog.php?c=' ~ change.change_id %}
|
||||
{% set manage_link = '/manage/changelog.php?v=change&c=' ~ change.change_id %}
|
||||
{% set description = change.change_log %}
|
||||
{% endif %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -36,7 +38,7 @@
|
|||
</div>
|
||||
|
||||
<div class="changelog__change__user__info">
|
||||
<div class="changelog__change__user__name">
|
||||
<div class="changelog__change__user__name" style="{{ change.user_colour|html_colour }}">
|
||||
{{ change.username }}
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
{% extends '@mio/master.twig' %}
|
||||
|
||||
{% if manage_link is not defined %}
|
||||
{% set manage_link = '/manage/changelog.php' %}
|
||||
{% endif %}
|
||||
|
|
|
@ -75,7 +75,6 @@
|
|||
|
||||
<div class="footer__links">
|
||||
{% autoescape false %}
|
||||
{{ '#'|html_link('Terms of Service', 'footer__links__link') }} |
|
||||
{{ '#'|html_link('Rules', 'footer__links__link') }} |
|
||||
{{ '#'|html_link('Contact', 'footer__links__link') }} |
|
||||
{{ '#'|html_link('Status', 'footer__links__link') }} |
|
||||
|
|
Loading…
Add table
Reference in a new issue