tangled
alpha
login
or
join now
hotsocket.fyi
/
domlink
0
fork
atom
https://domlink.deployments.hotsocket.fyi/
0
fork
atom
overview
issues
pulls
pipelines
tangled issue list (search next?)
hotsocket.fyi
6 months ago
3ea20a4a
6c6aa4d2
+196
4 changed files
expand all
collapse all
unified
split
src
domlink.ts
issuesearch.ts
static
issuesearch.css
issuesearch.html
+21
src/domlink.ts
···
65
65
this.wraps.classList.add("LRow");
66
66
}
67
67
}
68
68
+
export class Table extends Node {
69
69
+
constructor() {
70
70
+
let table = document.createElement("table");
71
71
+
table.classList.add("LTable");
72
72
+
super(table);
73
73
+
}
74
74
+
}
75
75
+
export class TableRow extends Node {
76
76
+
constructor() {
77
77
+
let tr = document.createElement("tr");
78
78
+
tr.classList.add("LTableRow");
79
79
+
super(tr);
80
80
+
}
81
81
+
}
82
82
+
export class TableCell extends Node {
83
83
+
constructor() {
84
84
+
let td = document.createElement("td");
85
85
+
td.classList.add("LTableCell");
86
86
+
super(td);
87
87
+
}
88
88
+
}
68
89
export class Text extends Node {
69
90
private _text: string = "";
70
91
get text() {
+148
src/issuesearch.ts
···
1
1
+
import { Body, Button, Column, Input, Label, Row, Table, TableCell, TableRow } from "./domlink.js";
2
2
+
3
3
+
type issueRecord = {
4
4
+
body: string;
5
5
+
createdAt: string;
6
6
+
issueId: number;
7
7
+
owner: string;
8
8
+
repo: string;
9
9
+
title: string;
10
10
+
};
11
11
+
type constellationRecordItem = {
12
12
+
did: string;
13
13
+
collection: string;
14
14
+
rkey: string;
15
15
+
};
16
16
+
type constellationResponse = {
17
17
+
total: number;
18
18
+
linking_records: [constellationRecordItem];
19
19
+
cursor: string;
20
20
+
};
21
21
+
type slingshotResponse<T> = {
22
22
+
cid: string;
23
23
+
uri: string;
24
24
+
value: T;
25
25
+
};
26
26
+
type miniDoc = {
27
27
+
did: string;
28
28
+
handle: string;
29
29
+
pds: string;
30
30
+
signing_key: string;
31
31
+
};
32
32
+
type repoRecord = {
33
33
+
knot: string;
34
34
+
name: string;
35
35
+
owner: string;
36
36
+
createdAt: string;
37
37
+
};
38
38
+
type recordListingItem<T> = {
39
39
+
uri: string;
40
40
+
cid: string;
41
41
+
value: T;
42
42
+
};
43
43
+
type recordListing<T> = {
44
44
+
cursor: string;
45
45
+
records: [recordListingItem<T>];
46
46
+
};
47
47
+
48
48
+
async function xcall(host: string, method: string, params: Record<string, string | number> | null = null): Promise<unknown> {
49
49
+
let url = `${host}/xrpc/${method}`;
50
50
+
if (params) {
51
51
+
let usp = new URLSearchParams();
52
52
+
for (let key in params) {
53
53
+
usp.append(key, params[key].toString());
54
54
+
}
55
55
+
url += "?" + usp.toString();
56
56
+
}
57
57
+
return await (await fetch(url)).json();
58
58
+
}
59
59
+
60
60
+
const SLINGSHOT = "https://slingshot.microcosm.blue";
61
61
+
async function listIssues(repo: string) {
62
62
+
let repoUrl = new URL(repo);
63
63
+
let repoUrlSplat = repoUrl.pathname.split("/");
64
64
+
let repoOwnerHandle = repoUrlSplat[1].substring(1);
65
65
+
let repoName = repoUrlSplat[2];
66
66
+
let repoOwnerDoc = await xcall(SLINGSHOT, "com.bad-example.identity.resolveMiniDoc", {identifier: repoOwnerHandle}) as miniDoc;
67
67
+
let ownedRepos = await xcall(repoOwnerDoc.pds, "com.atproto.repo.listRecords", { repo: repoOwnerDoc.did, collection: "sh.tangled.repo" }) as recordListing<repoRecord>;
68
68
+
let repoRecord = ownedRepos.records.find(x=>x.value.name == repoName)!;
69
69
+
let encodedRepoUri = encodeURIComponent(repoRecord.uri);
70
70
+
let view_issues_list = new Table().add(
71
71
+
new TableRow().with(
72
72
+
new TableCell().add("Handle"),
73
73
+
new TableCell().add("Issue#"),
74
74
+
new TableCell().add("Title")
75
75
+
)
76
76
+
);
77
77
+
Body.add(view_issues_list);
78
78
+
let irsp = await (await fetch(`https://constellation.microcosm.blue/links?target=${encodedRepoUri}&collection=sh.tangled.repo.issue&path=.repo`)).json() as constellationResponse;
79
79
+
let allIssueRefs: constellationRecordItem[] = irsp.linking_records;
80
80
+
let nextCursor = irsp.cursor;
81
81
+
while (allIssueRefs.length < irsp.total && nextCursor != null) {
82
82
+
let rsp = await (await fetch(`https://constellation.microcosm.blue/links?target=${encodedRepoUri}&collection=sh.tangled.repo.issue&path=.repo&cursor=${nextCursor}`)).json() as constellationResponse;
83
83
+
nextCursor = rsp.cursor;
84
84
+
allIssueRefs = allIssueRefs.concat(rsp.linking_records);
85
85
+
if (nextCursor == null) break;
86
86
+
}
87
87
+
let sortedIssues = (await Promise.all(allIssueRefs.map(async (issueRef) => {
88
88
+
let rsp = await xcall(SLINGSHOT, "com.atproto.repo.getRecord", {
89
89
+
repo: issueRef.did,
90
90
+
collection: issueRef.collection,
91
91
+
rkey: issueRef.rkey
92
92
+
}) as slingshotResponse<issueRecord>;
93
93
+
let issue = rsp.value;
94
94
+
let doc;
95
95
+
try {
96
96
+
doc = await xcall(SLINGSHOT, "com.bad-example.identity.resolveMiniDoc", { identifier: issue.owner }) as miniDoc;
97
97
+
} catch (error) {
98
98
+
return null;
99
99
+
}
100
100
+
let handle = doc.handle;
101
101
+
return {
102
102
+
handle: handle,
103
103
+
issue: issue
104
104
+
};
105
105
+
}))).sort((a,b)=>{
106
106
+
let x = 0;
107
107
+
if (a && b) {
108
108
+
x = b.issue.issueId-a.issue.issueId
109
109
+
}
110
110
+
return x;
111
111
+
});
112
112
+
sortedIssues.forEach(that =>{
113
113
+
if (that) {
114
114
+
let view_issue_row = new TableRow();
115
115
+
view_issue_row.with(
116
116
+
new TableCell().add(that.handle),
117
117
+
new TableCell().add(that.issue.issueId.toString()),
118
118
+
new TableCell().add(that.issue.title)
119
119
+
);
120
120
+
view_issues_list.add(view_issue_row);
121
121
+
}
122
122
+
});
123
123
+
return view_issues_list;
124
124
+
}
125
125
+
126
126
+
127
127
+
let repoUrl = new Input();
128
128
+
let last: any;
129
129
+
let statusText = new Label("waiting");
130
130
+
let runButton = new Button("GO!",async ()=>{
131
131
+
(runButton.wraps as HTMLButtonElement).disabled = true;
132
132
+
if (last) {
133
133
+
Body.remove(last);
134
134
+
}
135
135
+
try {
136
136
+
last = await listIssues(repoUrl.value);
137
137
+
} catch (e) {
138
138
+
last = new Label("Failed");
139
139
+
Body.add(last);
140
140
+
}
141
141
+
console.log(last);
142
142
+
(runButton.wraps as HTMLButtonElement).disabled = false;
143
143
+
});
144
144
+
Body.add(new Row().with(
145
145
+
"List issues for repo: ",
146
146
+
repoUrl,
147
147
+
runButton
148
148
+
));
+12
static/issuesearch.css
···
1
1
+
tr:nth-child(1) {
2
2
+
font-weight: bold;
3
3
+
}
4
4
+
tr:nth-child(1)>* {
5
5
+
text-align: center !important;
6
6
+
}
7
7
+
td {
8
8
+
padding-right: 2ch;
9
9
+
}
10
10
+
td:nth-child(1) {
11
11
+
text-align: right;
12
12
+
}
+15
static/issuesearch.html
···
1
1
+
<!DOCTYPE html>
2
2
+
<html lang="en">
3
3
+
<head>
4
4
+
<meta charset="UTF-8">
5
5
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
+
<title>issuesearch</title>
7
7
+
<link rel="stylesheet" href="styles/domlink.css">
8
8
+
<link rel="stylesheet" href="pds.css">
9
9
+
<link rel="stylesheet" href="issuesearch.css">
10
10
+
</head>
11
11
+
<body>
12
12
+
<noscript>enable js or fukc off</noscript>
13
13
+
<script src="issuesearch.js" type="module"></script>
14
14
+
</body>
15
15
+
</html>