Skip to content

Commit 969f581

Browse files
Copilotsamliew
andauthored
Revert Tags to link-grid, move Manual field to Type fieldset, add type_manual sanitization
Agent-Logs-Url: https://github.com/samliew/se-timeline/sessions/de739d11-2698-4a43-8c2e-93e9ff9f364f Co-authored-by: samliew <845988+samliew@users.noreply.github.com>
1 parent b0219c3 commit 969f581

3 files changed

Lines changed: 51 additions & 150 deletions

File tree

assets/css/editor.css

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -100,24 +100,21 @@ fieldset > legend.w-label + .info {
100100
}
101101

102102
.event-editor .class-grid,
103-
.event-editor .type-grid,
104-
.event-editor .tags-grid {
103+
.event-editor .type-grid {
105104
display: grid;
106105
grid-template-columns: repeat(3, auto);
107106
grid-gap: 10px;
108107
align-items: start;
109108
}
110109
.event-editor .class-grid > .form-row-inline,
111-
.event-editor .type-grid > .form-row-inline,
112-
.event-editor .tags-grid > .form-row-inline {
110+
.event-editor .type-grid > .form-row-inline {
113111
display: inline-flex;
114112
align-items: center;
115113
justify-content: flex-start;
116114
flex-wrap: wrap;
117115
}
118116
.event-editor .class-grid .w-checkbox,
119-
.event-editor .type-grid .w-checkbox,
120-
.event-editor .tags-grid .w-checkbox {
117+
.event-editor .type-grid .w-checkbox {
121118
margin-right: 5px;
122119
}
123120
.event-editor .class-grid .info,
@@ -127,18 +124,21 @@ fieldset > legend.w-label + .info {
127124
padding-left: calc(1rem + 5px);
128125
}
129126

130-
.event-editor .link-grid {
127+
.event-editor .link-grid,
128+
.event-editor .tags-grid {
131129
display: grid;
132130
margin-top: 0.5rem;
133131
grid-template-columns: 10px 200px auto;
134132
grid-gap: 1rem 0.5rem;
135133
align-items: center;
136134
}
137-
.event-editor .linkUrl:placeholder-shown ~ * {
135+
.event-editor .linkUrl:placeholder-shown ~ *,
136+
.event-editor .tagUrl:placeholder-shown ~ * {
138137
display: none;
139138
}
140139

141-
.event-editor .link-grid .w-input {
140+
.event-editor .link-grid .w-input,
141+
.event-editor .tags-grid .w-input {
142142
margin: 0;
143143
}
144144

@@ -250,11 +250,11 @@ fieldset > legend.w-label + .info {
250250
/* Mobile Only */
251251
@media (max-width: 767px) {
252252
.event-editor .class-grid,
253-
.event-editor .type-grid,
254-
.event-editor .tags-grid {
253+
.event-editor .type-grid {
255254
grid-template-columns: repeat(2, auto);
256255
}
257-
.event-editor .link-grid {
256+
.event-editor .link-grid,
257+
.event-editor .tags-grid {
258258
grid-template-columns: 10px 90px auto;
259259
}
260260
}

assets/js/editor.js

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,11 @@ const toSlug = str => str?.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-
166166
.map((url, i) => ({ text: linkText[i], url }))
167167
.filter(v => v.text && v.url); // remove empty links
168168

169-
// Join tags (comma-separated manual field, allow spaces and hyphens in tag names)
170-
const tagValues = [...formData.getAll('tags')]
171-
.flatMap(v => v.split(/\s*,\s*/))
172-
.filter(Boolean);
173-
data.tags = [...new Set(tagValues)];
169+
// Join tags
170+
const tagText = [...form.querySelectorAll('.tagText')].map(v => v.value)
171+
data.tags = [...form.querySelectorAll('.tagUrl')].map(v => v.value)
172+
.map((url, i) => ({ text: tagText[i], url }))
173+
.filter(v => v.text && v.url); // remove empty links
174174

175175
// Remove empty fields
176176
Object.entries(data).forEach(([key, value]) => {
@@ -226,21 +226,21 @@ const toSlug = str => str?.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-
226226
});
227227
}
228228

229-
// If type field, update checkboxes
229+
// If type field, update checkboxes and manual field
230230
if (key === 'type') {
231-
const otherField = document.querySelector('#type_other');
232-
otherField.value = '';
231+
const manualField = document.querySelector('#type_manual');
232+
manualField.value = '';
233233
const values = (typeof value === 'string' ? value.split(/\s+/) : Array.isArray(value) ? value : []).filter(Boolean);
234234
values.forEach(v => {
235235
const checkbox = document.querySelector(`[name="type"][value="${CSS.escape(v)}"]`);
236236
if (checkbox) {
237237
checkbox.checked = true;
238238
}
239-
else if (otherField.value.length) {
240-
otherField.value += ` ${v}`;
239+
else if (manualField.value.length) {
240+
manualField.value += `, ${v}`;
241241
}
242242
else {
243-
otherField.value = v;
243+
manualField.value = v;
244244
}
245245
});
246246
}
@@ -255,25 +255,13 @@ const toSlug = str => str?.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-
255255
});
256256
}
257257

258-
// If tags field, update tag checkboxes and manual field
258+
// If tags field, update tags
259259
if (key === 'tags') {
260-
const manualField = document.querySelector('#tags_manual');
261-
manualField.value = '';
262-
const tagNames = Array.isArray(value)
263-
? value.map(v => typeof v === 'string' ? v : v.text).filter(Boolean)
264-
: [];
265-
const uniqueTags = [...new Set(tagNames)];
266-
uniqueTags.forEach(v => {
267-
const checkbox = document.querySelector(`[name="tags"][value="${CSS.escape(v)}"]`);
268-
if (checkbox) {
269-
checkbox.checked = true;
270-
}
271-
else if (manualField.value.length) {
272-
manualField.value += `, ${v}`;
273-
}
274-
else {
275-
manualField.value = v;
276-
}
260+
document.querySelectorAll('.tagText').forEach((el, i) => {
261+
el.value = value[i]?.text || '';
262+
});
263+
document.querySelectorAll('.tagUrl').forEach((el, i) => {
264+
el.value = value[i]?.url || '';
277265
});
278266
}
279267
});
@@ -328,6 +316,11 @@ const toSlug = str => str?.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-
328316
}
329317
}
330318

319+
// If manual type field, remove disallowed characters
320+
if (field.id === 'type_manual') {
321+
field.value = field.value.replace(/[^a-z0-9, -]/gi, '').trim();
322+
}
323+
331324
// If url field, and does not start with http, prepend with https://
332325
if (field.type === 'url' && notEmpty && !field.value.match(/^https?:\/\//)) {
333326
field.value = `https://${field.value}`;

event-editor/index.html

Lines changed: 17 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ <h1 class="main-title">Event Editor</h1>
7777
<fieldset>
7878
<legend class="w-label">Type</legend>
7979
<div class="info">for grouping similar events, for easier browser page search</div>
80+
<div class="form-row">
81+
<label class="w-label" for="type_manual">Manual</label>
82+
<input class="w-input" type="text" name="type" id="type_manual" placeholder="custom-type-1, custom-type-2">
83+
</div>
8084
<div class="type-grid">
8185
<div class="form-row-inline">
8286
<input class="w-checkbox" type="checkbox" name="type" id="type_advertising" value="advertising">
@@ -218,7 +222,6 @@ <h1 class="main-title">Event Editor</h1>
218222
<label class="w-label" for="type_strike">strike</label>
219223
<div class="info">strike or protest</div>
220224
</div>
221-
<input type="hidden" name="type" id="type_other" value="">
222225
</div>
223226
</fieldset>
224227
<fieldset>
@@ -273,116 +276,21 @@ <h1 class="main-title">Event Editor</h1>
273276
<input class="w-input linkUrl" type="url" id="linkUrl2" data-pair="linkText2" placeholder="https://">
274277
</div>
275278
</div>
276-
<fieldset>
277-
<legend class="w-label">Tags</legend>
278-
<div class="info">for easier browser searching of similar events</div>
279-
<div class="form-row">
280-
<label class="w-label" for="tags_manual">Manual</label>
281-
<input class="w-input" type="text" name="tags" id="tags_manual" placeholder="custom-tag-1, custom-tag-2">
282-
</div>
279+
<div class="form-row">
280+
<label class="w-label" for="tags">Tags</label>
281+
<div class="info">an array of link tags (up to three)</div>
283282
<div class="tags-grid">
284-
<div class="form-row-inline">
285-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_account-suspension" value="account-suspension">
286-
<label class="w-label" for="tags_account-suspension">account-suspension</label>
287-
</div>
288-
<div class="form-row-inline">
289-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_advertising" value="advertising">
290-
<label class="w-label" for="tags_advertising">advertising</label>
291-
</div>
292-
<div class="form-row-inline">
293-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_april-fools" value="april-fools">
294-
<label class="w-label" for="tags_april-fools">april-fools</label>
295-
</div>
296-
<div class="form-row-inline">
297-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_area51" value="area51">
298-
<label class="w-label" for="tags_area51">area51</label>
299-
</div>
300-
<div class="form-row-inline">
301-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_code-of-conduct" value="code-of-conduct">
302-
<label class="w-label" for="tags_code-of-conduct">code-of-conduct</label>
303-
</div>
304-
<div class="form-row-inline">
305-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_collectives" value="collectives">
306-
<label class="w-label" for="tags_collectives">collectives</label>
307-
</div>
308-
<div class="form-row-inline">
309-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_commonmark" value="commonmark">
310-
<label class="w-label" for="tags_commonmark">commonmark</label>
311-
</div>
312-
<div class="form-row-inline">
313-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_company" value="company">
314-
<label class="w-label" for="tags_company">company</label>
315-
</div>
316-
<div class="form-row-inline">
317-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_data-dump" value="data-dump">
318-
<label class="w-label" for="tags_data-dump">data-dump</label>
319-
</div>
320-
<div class="form-row-inline">
321-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_data-explorer" value="data-explorer">
322-
<label class="w-label" for="tags_data-explorer">data-explorer</label>
323-
</div>
324-
<div class="form-row-inline">
325-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_documentation" value="documentation">
326-
<label class="w-label" for="tags_documentation">documentation</label>
327-
</div>
328-
<div class="form-row-inline">
329-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_flags" value="flags">
330-
<label class="w-label" for="tags_flags">flags</label>
331-
</div>
332-
<div class="form-row-inline">
333-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_inappropriate-advertisements" value="inappropriate-advertisements">
334-
<label class="w-label" for="tags_inappropriate-advertisements">inappropriate-advertisements</label>
335-
</div>
336-
<div class="form-row-inline">
337-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_jobs" value="jobs">
338-
<label class="w-label" for="tags_jobs">jobs</label>
339-
</div>
340-
<div class="form-row-inline">
341-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_licensing" value="licensing">
342-
<label class="w-label" for="tags_licensing">licensing</label>
343-
</div>
344-
<div class="form-row-inline">
345-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_mentoring" value="mentoring">
346-
<label class="w-label" for="tags_mentoring">mentoring</label>
347-
</div>
348-
<div class="form-row-inline">
349-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_prompt-design-site" value="prompt-design-site">
350-
<label class="w-label" for="tags_prompt-design-site">prompt-design-site</label>
351-
</div>
352-
<div class="form-row-inline">
353-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_se-quality-project" value="se-quality-project">
354-
<label class="w-label" for="tags_se-quality-project">se-quality-project</label>
355-
</div>
356-
<div class="form-row-inline">
357-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_sponsored-sites" value="sponsored-sites">
358-
<label class="w-label" for="tags_sponsored-sites">sponsored-sites</label>
359-
</div>
360-
<div class="form-row-inline">
361-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_sponsored-tags" value="sponsored-tags">
362-
<label class="w-label" for="tags_sponsored-tags">sponsored-tags</label>
363-
</div>
364-
<div class="form-row-inline">
365-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_stack-overflow-for-teams" value="stack-overflow-for-teams">
366-
<label class="w-label" for="tags_stack-overflow-for-teams">stack-overflow-for-teams</label>
367-
</div>
368-
<div class="form-row-inline">
369-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_stack-overflow-labs" value="stack-overflow-labs">
370-
<label class="w-label" for="tags_stack-overflow-labs">stack-overflow-labs</label>
371-
</div>
372-
<div class="form-row-inline">
373-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_the-loop" value="the-loop">
374-
<label class="w-label" for="tags_the-loop">the-loop</label>
375-
</div>
376-
<div class="form-row-inline">
377-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_welcoming" value="welcoming">
378-
<label class="w-label" for="tags_welcoming">welcoming</label>
379-
</div>
380-
<div class="form-row-inline">
381-
<input class="w-checkbox" type="checkbox" name="tags" id="tags_winter-bash" value="winter-bash">
382-
<label class="w-label" for="tags_winter-bash">winter-bash</label>
383-
</div>
283+
<span>1.</span>
284+
<input class="w-input tagText" type="text" id="tagText0" data-pair="tagUrl0" placeholder="tag-text" maxlength="50" pattern="^[a-z0-9-]+$">
285+
<input class="w-input tagUrl" type="url" id="tagUrl0" data-pair="tagText0" placeholder="https://">
286+
<span>2.</span>
287+
<input class="w-input tagText" type="text" id="tagText1" data-pair="tagUrl1" placeholder="tag-text" maxlength="50" pattern="^[a-z0-9-]+$">
288+
<input class="w-input tagUrl" type="url" id="tagUrl1" data-pair="tagText1" placeholder="https://">
289+
<span>3.</span>
290+
<input class="w-input tagText" type="text" id="tagText2" data-pair="tagUrl2" placeholder="tag-text" maxlength="50" pattern="^[a-z0-9-]+$">
291+
<input class="w-input tagUrl" type="url" id="tagUrl2" data-pair="tagText2" placeholder="https://">
384292
</div>
385-
</fieldset>
293+
</div>
386294
<div class="form-row">
387295
<label class="w-label" for="linkedEvent">Linked Event</label>
388296
<div class="info">another event's slug prefixed with a #</div>

0 commit comments

Comments
 (0)