Pages #5
63
assets/js/controllers/pagelist.js
Normal file
63
assets/js/controllers/pagelist.js
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
import { Controller } from "@hotwired/stimulus"
|
||||||
|
import { showToast } from "../services/toast";
|
||||||
|
|
||||||
|
export default class PagelistController extends Controller {
|
||||||
|
static values = {
|
||||||
|
siteId: Number,
|
||||||
|
};
|
||||||
|
|
||||||
|
static targets = ["list"];
|
||||||
|
|
||||||
|
dragStart(ev) {
|
||||||
|
this.draggedRow = ev.currentTarget;
|
||||||
|
ev.currentTarget.classList.add("opacity-50");
|
||||||
|
ev.dataTransfer.effectAllowed = "move";
|
||||||
|
}
|
||||||
|
|
||||||
|
dragOver(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.dataTransfer.dropEffect = "move";
|
||||||
|
}
|
||||||
|
|
||||||
|
drop(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
const targetRow = ev.currentTarget;
|
||||||
|
if (this.draggedRow && this.draggedRow !== targetRow) {
|
||||||
|
const rows = [...this.listTarget.children];
|
||||||
|
const draggedIdx = rows.indexOf(this.draggedRow);
|
||||||
|
const targetIdx = rows.indexOf(targetRow);
|
||||||
|
if (draggedIdx < targetIdx) {
|
||||||
|
targetRow.after(this.draggedRow);
|
||||||
|
} else {
|
||||||
|
targetRow.before(this.draggedRow);
|
||||||
|
}
|
||||||
|
this.saveOrder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dragEnd(ev) {
|
||||||
|
ev.currentTarget.classList.remove("opacity-50");
|
||||||
|
this.draggedRow = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveOrder() {
|
||||||
|
const rows = [...this.listTarget.children];
|
||||||
|
const pageIds = rows.map(row => parseInt(row.dataset.pageId, 10));
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fetch(`/sites/${this.siteIdValue}/pages/reorder`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Accept": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ page_ids: pageIds }),
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
showToast({
|
||||||
|
title: "Error",
|
||||||
|
body: "Failed to reorder pages.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ import LogoutController from "./controllers/logout";
|
||||||
import FirstRunController from "./controllers/firstrun";
|
import FirstRunController from "./controllers/firstrun";
|
||||||
import UploadController from "./controllers/upload";
|
import UploadController from "./controllers/upload";
|
||||||
import ShowUploadController from "./controllers/show_upload";
|
import ShowUploadController from "./controllers/show_upload";
|
||||||
|
import PagelistController from "./controllers/pagelist";
|
||||||
|
|
||||||
window.Stimulus = Application.start()
|
window.Stimulus = Application.start()
|
||||||
Stimulus.register("toast", ToastController);
|
Stimulus.register("toast", ToastController);
|
||||||
|
|
@ -16,3 +17,4 @@ Stimulus.register("logout", LogoutController);
|
||||||
Stimulus.register("first-run", FirstRunController);
|
Stimulus.register("first-run", FirstRunController);
|
||||||
Stimulus.register("upload", UploadController);
|
Stimulus.register("upload", UploadController);
|
||||||
Stimulus.register("show-upload", ShowUploadController);
|
Stimulus.register("show-upload", ShowUploadController);
|
||||||
|
Stimulus.register("pagelist", PagelistController);
|
||||||
|
|
@ -13,6 +13,9 @@
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link active" aria-current="page" href="/sites/{{.site.ID}}/categories">Categories</a>
|
<a class="nav-link active" aria-current="page" href="/sites/{{.site.ID}}/categories">Categories</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" aria-current="page" href="/sites/{{.site.ID}}/pages">Pages</a>
|
||||||
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link active" aria-current="page" href="/sites/{{.site.ID}}/uploads">Uploads</a>
|
<a class="nav-link active" aria-current="page" href="/sites/{{.site.ID}}/uploads">Uploads</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
35
views/pages/index.html
Normal file
35
views/pages/index.html
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
<main class="container">
|
||||||
|
<div class="my-4 d-flex justify-content-between align-items-baseline">
|
||||||
|
<div>
|
||||||
|
<a href="/sites/{{ .site.ID }}/pages/new" class="btn btn-success">New Page</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ if .pages }}
|
||||||
|
<table class="table" data-controller="pagelist" data-pagelist-site-id-value="{{ .site.ID }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 2rem;"></th>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Slug</th>
|
||||||
|
<th>Nav</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody data-pagelist-target="list">
|
||||||
|
{{ range .pages }}
|
||||||
|
<tr draggable="true" data-page-id="{{ .ID }}"
|
||||||
|
data-action="dragstart->pagelist#dragStart dragover->pagelist#dragOver drop->pagelist#drop dragend->pagelist#dragEnd">
|
||||||
|
<td class="text-muted" style="cursor: grab;">☰</td>
|
||||||
|
<td><a href="/sites/{{ $.site.ID }}/pages/{{ .ID }}">{{ .Title }}</a></td>
|
||||||
|
<td><code>{{ .Slug }}</code></td>
|
||||||
|
<td>{{ if .ShowInNav }}Yes{{ end }}</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{{ else }}
|
||||||
|
<div class="h4 m-3 text-center">
|
||||||
|
<div class="position-absolute top-50 start-50 translate-middle">No pages yet.</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</main>
|
||||||
Loading…
Reference in a new issue