Monorepo for Tangled
tangled.org
1{{ define "title" }}{{ .String.Filename }} · by {{ resolve .Owner.DID.String }} · Tangled{{ end }}
2
3{{ define "extrameta" }}
4 {{ $ownerId := resolve .Owner.DID.String }}
5 <meta property="og:title" content="{{ .String.Filename }} · by {{ $ownerId }}" />
6 <meta property="og:type" content="object" />
7 <meta property="og:url" content="https://tangled.org/strings/{{ $ownerId }}/{{ .String.Rkey }}" />
8 <meta property="og:description" content="{{ .String.Description }}" />
9{{ end }}
10
11{{ define "content" }}
12{{ $ownerId := resolve .Owner.DID.String }}
13 <section id="string-header" class="mb-2 py-2 px-4 dark:text-white">
14 <div class="text-lg flex flex-col sm:flex-row items-start gap-4 justify-between">
15 <!-- left items -->
16 <div class="flex flex-col gap-2">
17 <!-- string owner / string name -->
18 <div class="flex items-center gap-2 flex-wrap">
19 {{ template "user/fragments/picHandleLink" .Owner.DID.String }}
20 <span class="select-none">/</span>
21 <a href="/strings/{{ $ownerId }}/{{ .String.Rkey }}" class="font-bold">{{ .String.Filename }}</a>
22 </div>
23
24 <span class="flex flex-wrap items-center gap-x-4 gap-y-2 text-sm text-gray-600 dark:text-gray-300">
25 {{ if .String.Description }}
26 {{ .String.Description }}
27 {{ else }}
28 <span class="italic">This string has no description</span>
29 {{ end }}
30 </span>
31 </div>
32
33 {{ $isOwner := and .LoggedInUser (eq .LoggedInUser.Did .String.Did) }}
34 <div class="w-fit grid grid-flow-col grid-cols-3 gap-2">
35 {{ if $isOwner }}
36 <a class="btn no-underline hover:no-underline group"
37 hx-boost="true"
38 href="/strings/{{ .String.Did }}/{{ .String.Rkey }}/edit">
39 {{ i "pencil" "w-4 h-4" }}
40 <span class="hidden md:inline">Edit</span>
41 {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
42 </a>
43 <button
44 class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 group"
45 title="Delete string"
46 hx-delete="/strings/{{ .String.Did }}/{{ .String.Rkey }}/"
47 hx-swap="none"
48 hx-confirm="Are you sure you want to delete the string `{{ .String.Filename }}`?"
49 >
50 {{ i "trash-2" "w-4 h-4" }}
51 <span class="hidden md:inline">Delete</span>
52 {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
53 </button>
54 {{ end }}
55 <div class="{{ if not $isOwner }}col-span-3 justify-self-end{{ end }}">
56 {{ template "fragments/starBtn"
57 (dict "SubjectAt" .String.AtUri
58 "IsStarred" .IsStarred
59 "StarCount" .StarCount) }}
60 </div>
61 </div>
62 </div>
63 </section>
64 <section class="bg-white dark:bg-gray-800 px-6 py-4 rounded relative w-full dark:text-white">
65 <div class="flex flex-col md:flex-row md:justify-between md:items-center text-gray-500 dark:text-gray-400 text-sm md:text-base pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700">
66 <span>
67 {{ .String.Filename }}
68 <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
69 <span>
70 {{ with .String.Edited }}
71 edited {{ template "repo/fragments/shortTimeAgo" . }}
72 {{ else }}
73 {{ template "repo/fragments/shortTimeAgo" .String.Created }}
74 {{ end }}
75 </span>
76 </span>
77 <div>
78 <span>{{ .Stats.LineCount }} lines</span>
79 <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
80 <span>{{ byteFmt .Stats.ByteCount }}</span>
81 <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
82 <a href="/strings/{{ $ownerId }}/{{ .String.Rkey }}/raw">View raw</a>
83 {{ if .RenderToggle }}
84 <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
85 <a href="?code={{ .ShowRendered }}" hx-boost="true">
86 View {{ if .ShowRendered }}code{{ else }}rendered{{ end }}
87 </a>
88 {{ end }}
89 </div>
90 </div>
91 <div class="overflow-x-auto overflow-y-hidden relative">
92 {{ if .ShowRendered }}
93 <div id="blob-contents" class="prose dark:prose-invert">{{ .String.Contents | readme }}</div>
94 {{ else }}
95 <div id="blob-contents" class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ code .String.Contents .String.Filename | escapeHtml }}</div>
96 {{ end }}
97 </div>
98 {{ template "fragments/multiline-select" }}
99 </section>
100 <div class="flex flex-col gap-4 mt-4">
101 {{
102 template "fragments/comment/commentList"
103 (dict
104 "LoggedInUser" .LoggedInUser
105 "Reactions" .Reactions
106 "UserReacted" .UserReacted
107 "VouchRelationships" .VouchRelationships
108 "CommentList" .CommentList)
109 }}
110 {{ template "newComment" . }}
111 </div>
112{{ end }}
113
114{{ define "newComment" }}
115 {{ if .LoggedInUser }}
116 <form
117 hx-post="/comment"
118 hx-trigger="submit, keydown[(ctrlKey || metaKey) && key=='Enter'] from:find textarea"
119 hx-swap="none"
120 hx-disabled-elt="find button[type='submit']"
121 hx-on::after-request="if(event.detail.successful) this.reset()"
122 class="group/form"
123 >
124 <input name="subject-uri" type="hidden" value="{{ .String.AtUri }}">
125 <div class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-4 px-4 relative w-full">
126 <div class="text-sm pb-2 text-gray-500 dark:text-gray-400">
127 {{ template "user/fragments/picHandleLink" .LoggedInUser.Did }}
128 </div>
129 <textarea
130 name="body"
131 class="w-full p-2 rounded"
132 placeholder="Add to the discussion. Markdown is supported."
133 rows="5"
134 required
135 ></textarea>
136 <div id="comment-error" class="error"></div>
137 </div>
138 <div class="flex gap-2 mt-2">
139 <button
140 id="comment-button"
141 type="submit"
142 class="btn-create p-2 flex items-center gap-2 no-underline hover:no-underline"
143 >
144 {{ i "message-square-plus" "w-4 h-4 inline group-[.htmx-request]/form:hidden" }}
145 {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]/form:inline" }}
146 Comment
147 </button>
148 </div>
149 </form>
150 {{ else }}
151 <div class="bg-amber-50 dark:bg-amber-900 border border-amber-500 rounded drop-shadow-sm p-6 relative flex gap-2 items-center">
152 <a href="/signup" class="btn-create py-0 hover:no-underline hover:text-white flex items-center gap-2">
153 Sign up
154 </a>
155 <span class="text-gray-500 dark:text-gray-400">or</span>
156 <a href="/login" class="underline">login</a>
157 to add to the discussion
158 </div>
159 {{ end }}
160{{ end }}