frontend: add ShowIssue, add useLocationHash

This commit is contained in:
0x1eef 2023-12-21 02:09:22 -03:00
parent 5d19e85068
commit c682a01977
10 changed files with 76 additions and 14 deletions

View file

@ -29,3 +29,18 @@ compile("/js/entry-point/issues.tsx") do
filter(:webpack, depend_on: %w[/js/components /js/hooks/ /js/types]) filter(:webpack, depend_on: %w[/js/components /js/hooks/ /js/types])
write("/js/entry-point/issues.js") write("/js/entry-point/issues.js")
end end
##
# GET /issues/show#<issue-id>
compile("/html/issues/show/index.html.erb") do
layout "/default.*"
filter(:erb)
write("/issues/show/index.html")
end
##
# GET /js/entry-point/show-issue.js
compile("/js/entry-point/show-issue.tsx") do
filter(:webpack, depend_on: %w[/js/components /js/hooks/ /js/types])
write("/js/entry-point/show-issue.js")
end

View file

@ -0,0 +1,4 @@
<div class="pure-g">
<div id="reactapp"></div>
<script src="/js/entry-point/show-issue.js"></script>
</div>

View file

@ -3,13 +3,12 @@ import { useIssues } from "/hooks/useIssues";
export function Issues() { export function Issues() {
const [issues] = useIssues(); const [issues] = useIssues();
console.log({issues})
return ( return (
<> <>
<span>Issues</span> <span>Issues</span>
<ul className="connections"> <ul className="connections">
{issues.map((issue, key) => { {issues.map((issue, key) => {
return (<li key={key}>{issue.title}</li>); return <li key={key}>{issue.title}</li>;
})} })}
</ul> </ul>
</> </>

View file

@ -0,0 +1,21 @@
import React, { useState, useEffect } from "react";
import { Issue } from "/types/schema";
import { useLocationHash } from "/hooks/useLocationHash";
export function ShowIssue() {
const [id] = useLocationHash();
const [issue, setIssue] = useState<Issue | null>(null);
useEffect(() => {
if (!id) return;
fetch(`/servlet/issues/${id}/`)
.then(res => res.json())
.then(res => setIssue(res.issue));
}, [id]);
if (id.length && issue) {
return <>{issue.title}</>;
} else {
return <>No issue</>;
}
}

View file

@ -27,10 +27,7 @@ export function NewIssue() {
<form className="new-issue pure-form" onSubmit={handleSubmit(onSave)}> <form className="new-issue pure-form" onSubmit={handleSubmit(onSave)}>
<div className="pure-u-1-1"> <div className="pure-u-1-1">
<div className="left"> <div className="left">
<Select <Select {...register("connectionId")} ref={selectRef}>
{...register("connectionId")}
ref={selectRef}
>
{connections.map((conn, key) => { {connections.map((conn, key) => {
return ( return (
<option key={key} value={conn.id}> <option key={key} value={conn.id}>

View file

@ -0,0 +1,8 @@
import React from "react";
import ReactDOM from "react-dom/client";
import { ShowIssue } from "/components/ShowIssue";
(function () {
const root = document.getElementById("reactapp")!;
ReactDOM.createRoot(root).render(<ShowIssue />);
})();

View file

@ -12,7 +12,7 @@ export function useConnections() {
useEffect(() => { useEffect(() => {
fetch("/servlet/connections") fetch("/servlet/connections")
.then(res => res.json()) .then(res => res.json())
.then((res) => setConns(res.connections)); .then(res => setConns(res.connections));
}, []); }, []);
return [conns]; return [conns];

View file

@ -7,7 +7,7 @@ export function useIssues() {
useEffect(() => { useEffect(() => {
fetch("/servlet/issues") fetch("/servlet/issues")
.then(res => res.json()) .then(res => res.json())
.then((res) => setIssues(res.issues)); .then(res => setIssues(res.issues));
}, []); }, []);
return [issues]; return [issues];

View file

@ -0,0 +1,18 @@
import { useEffect, useState } from "react";
export function useLocationHash() {
const [hash, setHash] = useState<string>("");
function set() {
const normalized = location.hash.substring(1, location.hash.length);
setHash(normalized);
}
useEffect(set, [location.hash]);
useEffect(() => {
window.addEventListener("hashchange", set);
return () => window.removeEventListener("hashchange", set);
}, []);
return [hash];
}

View file

@ -5,9 +5,9 @@ export type Connection = {
}; };
export type Issue = { export type Issue = {
id: number, id: number;
title: string, title: string;
content: string, content: string;
state: "open" | "closed", state: "open" | "closed";
connection_id: number connection_id: number;
} };