tangled
alpha
login
or
join now
leaflet.pub
/
leaflet
289
fork
atom
a tool for shared writing and social publishing
289
fork
atom
overview
issues
28
pulls
pipelines
fix tag selector when no draft and tweak search
awarm.space
3 months ago
5c25b2af
1b82fdfc
+68
-36
3 changed files
expand all
collapse all
unified
split
app
[leaflet_id]
publish
PublishPost.tsx
page.tsx
components
Tags.tsx
+21
-8
app/[leaflet_id]/publish/PublishPost.tsx
···
33
33
record?: PubLeafletPublication.Record;
34
34
posts_in_pub?: number;
35
35
entitiesToDelete?: string[];
36
36
+
hasDraft: boolean;
36
37
};
37
38
38
39
export function PublishPost(props: Props) {
···
67
68
let params = useParams();
68
69
let { rep } = useReplicache();
69
70
70
70
-
// Get tags from Replicache state (same as in the draft editor)
71
71
-
let tags = useSubscribe(rep, (tx) => tx.get<string[]>("publication_tags"));
71
71
+
// For publications with drafts, use Replicache; otherwise use local state
72
72
+
let replicacheTags = useSubscribe(rep, (tx) =>
73
73
+
tx.get<string[]>("publication_tags"),
74
74
+
);
75
75
+
let [localTags, setLocalTags] = useState<string[]>([]);
72
76
73
73
-
// Default to empty array if undefined
74
74
-
const currentTags = Array.isArray(tags) ? tags : [];
77
77
+
// Use Replicache tags only when we have a draft
78
78
+
const hasDraft = props.hasDraft;
79
79
+
const currentTags = hasDraft
80
80
+
? Array.isArray(replicacheTags)
81
81
+
? replicacheTags
82
82
+
: []
83
83
+
: localTags;
75
84
76
76
-
// Update tags via the same mutation used in the editor
85
85
+
// Update tags via Replicache mutation or local state depending on context
77
86
const handleTagsChange = async (newTags: string[]) => {
78
78
-
await rep?.mutate.updatePublicationDraft({
79
79
-
tags: newTags,
80
80
-
});
87
87
+
if (hasDraft) {
88
88
+
await rep?.mutate.updatePublicationDraft({
89
89
+
tags: newTags,
90
90
+
});
91
91
+
} else {
92
92
+
setLocalTags(newTags);
93
93
+
}
81
94
};
82
95
83
96
async function submit() {
+6
app/[leaflet_id]/publish/page.tsx
···
99
99
// If parsing fails, just use empty array
100
100
}
101
101
102
102
+
// Check if a draft record exists (either in a publication or standalone)
103
103
+
let hasDraft =
104
104
+
data.leaflets_in_publications.length > 0 ||
105
105
+
data.leaflets_to_documents.length > 0;
106
106
+
102
107
return (
103
108
<ReplicacheProvider
104
109
rootEntity={rootEntity}
···
116
121
record={publication?.record as PubLeafletPublication.Record | undefined}
117
122
posts_in_pub={publication?.documents_in_publications[0]?.count}
118
123
entitiesToDelete={entitiesToDelete}
124
124
+
hasDraft={hasDraft}
119
125
/>
120
126
</ReplicacheProvider>
121
127
);
+41
-28
components/Tags.tsx
···
95
95
[tagInputValue],
96
96
);
97
97
98
98
-
const filteredTags = searchResults.filter(
99
99
-
(tag) => !props.selectedTags.includes(tag.name),
100
100
-
);
98
98
+
const filteredTags = searchResults
99
99
+
.filter((tag) => !props.selectedTags.includes(tag.name))
100
100
+
.filter((tag) =>
101
101
+
tag.name.toLowerCase().includes(tagInputValue.toLowerCase()),
102
102
+
);
103
103
+
104
104
+
const showResults = tagInputValue.length >= 3;
101
105
102
106
function clearTagInput() {
103
107
setHighlightedIndex(0);
···
139
143
};
140
144
141
145
const userInputResult =
146
146
+
showResults &&
142
147
tagInputValue !== "" &&
143
148
!filteredTags.some((tag) => tag.name === tagInputValue);
144
149
···
219
224
)}
220
225
<hr className=" mb-[2px] border-border-light" />
221
226
222
222
-
{userInputResult && (
227
227
+
{showResults ? (
223
228
<>
224
224
-
<TagResult
225
225
-
key={"userInput"}
226
226
-
index={0}
227
227
-
name={tagInputValue}
228
228
-
tagged={0}
229
229
-
highlighted={0 === highlightedIndex}
230
230
-
setHighlightedIndex={setHighlightedIndex}
231
231
-
onSelect={() => {
232
232
-
selectTag(tagInputValue);
233
233
-
}}
234
234
-
/>
229
229
+
{userInputResult && (
230
230
+
<TagResult
231
231
+
key={"userInput"}
232
232
+
index={0}
233
233
+
name={tagInputValue}
234
234
+
tagged={0}
235
235
+
highlighted={0 === highlightedIndex}
236
236
+
setHighlightedIndex={setHighlightedIndex}
237
237
+
onSelect={() => {
238
238
+
selectTag(tagInputValue);
239
239
+
}}
240
240
+
/>
241
241
+
)}
242
242
+
{filteredTags.map((tag, i) => (
243
243
+
<TagResult
244
244
+
key={tag.name}
245
245
+
index={userInputResult ? i + 1 : i}
246
246
+
name={tag.name}
247
247
+
tagged={tag.document_count}
248
248
+
highlighted={
249
249
+
(userInputResult ? i + 1 : i) === highlightedIndex
250
250
+
}
251
251
+
setHighlightedIndex={setHighlightedIndex}
252
252
+
onSelect={() => {
253
253
+
selectTag(tag.name);
254
254
+
}}
255
255
+
/>
256
256
+
))}
235
257
</>
258
258
+
) : (
259
259
+
<div className="text-tertiary italic text-sm py-1">
260
260
+
type at least 3 characters to search
261
261
+
</div>
236
262
)}
237
237
-
{filteredTags.map((tag, i) => (
238
238
-
<TagResult
239
239
-
key={tag.name}
240
240
-
index={userInputResult ? i + 1 : i}
241
241
-
name={tag.name}
242
242
-
tagged={tag.document_count}
243
243
-
highlighted={(userInputResult ? i + 1 : i) === highlightedIndex}
244
244
-
setHighlightedIndex={setHighlightedIndex}
245
245
-
onSelect={() => {
246
246
-
selectTag(tag.name);
247
247
-
}}
248
248
-
/>
249
249
-
))}
250
263
</div>
251
264
</Popover>
252
265
</div>