Limit organization name length (#671)

This commit is contained in:
sua yoo 2023-03-08 09:21:48 -08:00 committed by GitHub
parent 544346d1d4
commit 666c28f420
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 81 additions and 32 deletions

View File

@ -9,8 +9,6 @@ import LiteElement, { html } from "../utils/LiteElement";
import { maxLengthValidator } from "../utils/form"; import { maxLengthValidator } from "../utils/form";
import type { Crawl } from "../types/crawler"; import type { Crawl } from "../types/crawler";
const CRAWL_NOTES_MAXLENGTH = 500;
/** /**
* Usage: * Usage:
* ```ts * ```ts
@ -55,6 +53,8 @@ export class CrawlMetadataEditor extends LiteElement {
threshold: 0.2, // stricter; default is 0.6 threshold: 0.2, // stricter; default is 0.6
}); });
private validateCrawlNotesMax = maxLengthValidator(500);
willUpdate(changedProperties: Map<string, any>) { willUpdate(changedProperties: Map<string, any>) {
if (changedProperties.has("open") && this.open) { if (changedProperties.has("open") && this.open) {
this.fetchTags(); this.fetchTags();
@ -81,7 +81,7 @@ export class CrawlMetadataEditor extends LiteElement {
private renderEditMetadata() { private renderEditMetadata() {
if (!this.crawl) return; if (!this.crawl) return;
const { helpText, validate } = maxLengthValidator(CRAWL_NOTES_MAXLENGTH); const { helpText, validate } = this.validateCrawlNotesMax;
return html` return html`
<form <form
id="crawlDetailsForm" id="crawlDetailsForm"
@ -89,7 +89,7 @@ export class CrawlMetadataEditor extends LiteElement {
@reset=${this.requestClose} @reset=${this.requestClose}
> >
<sl-textarea <sl-textarea
class="mb-3" class="mb-3 with-max-help-text"
name="crawlNotes" name="crawlNotes"
label=${msg("Notes")} label=${msg("Notes")}
value=${this.crawl.notes || ""} value=${this.crawl.notes || ""}
@ -97,7 +97,6 @@ export class CrawlMetadataEditor extends LiteElement {
autocomplete="off" autocomplete="off"
resize="auto" resize="auto"
help-text=${helpText} help-text=${helpText}
style="--help-text-align: right"
@sl-input=${validate} @sl-input=${validate}
></sl-textarea> ></sl-textarea>
<btrix-tag-input <btrix-tag-input

View File

@ -379,10 +379,13 @@ export class App extends LiteElement {
return; return;
} }
// Limit org name display for orgs created before org name max length restriction
const orgNameLength = 50;
return html` return html`
<sl-dropdown placement="bottom-end"> <sl-dropdown placement="bottom-end">
<sl-button slot="trigger" variant="text" size="small" caret <sl-button slot="trigger" variant="text" size="small" caret
>${selectedOption.name}</sl-button >${selectedOption.name.slice(0, orgNameLength)}</sl-button
> >
<sl-menu <sl-menu
@sl-select=${(e: CustomEvent) => { @sl-select=${(e: CustomEvent) => {
@ -414,7 +417,7 @@ export class App extends LiteElement {
<sl-menu-item <sl-menu-item
value=${org.id} value=${org.id}
?checked=${org.id === selectedOption.id} ?checked=${org.id === selectedOption.id}
>${org.name}</sl-menu-item >${org.name.slice(0, orgNameLength)}</sl-menu-item
> >
` `
)} )}

View File

@ -8,6 +8,7 @@ import type { CurrentUser } from "../types/user";
import type { OrgData } from "../utils/orgs"; import type { OrgData } from "../utils/orgs";
import LiteElement, { html } from "../utils/LiteElement"; import LiteElement, { html } from "../utils/LiteElement";
import type { APIPaginatedList } from "../types/api"; import type { APIPaginatedList } from "../types/api";
import { maxLengthValidator } from "../utils/form";
@localized() @localized()
export class Home extends LiteElement { export class Home extends LiteElement {
@ -35,6 +36,8 @@ export class Home extends LiteElement {
@state() @state()
private isSubmittingNewOrg = false; private isSubmittingNewOrg = false;
private validateOrgNameMax = maxLengthValidator(50);
connectedCallback() { connectedCallback() {
if (this.authState) { if (this.authState) {
super.connectedCallback(); super.connectedCallback();
@ -190,11 +193,14 @@ export class Home extends LiteElement {
> >
<div class="mb-5"> <div class="mb-5">
<sl-input <sl-input
class="with-max-help-text"
name="name" name="name"
label=${msg("Org Name")} label=${msg("Org Name")}
placeholder=${msg("My Organization")} placeholder=${msg("My Organization")}
autocomplete="off" autocomplete="off"
required required
help-text=${this.validateOrgNameMax.helpText}
@sl-input=${this.validateOrgNameMax.validate}
> >
</sl-input> </sl-input>
</div> </div>

View File

@ -233,6 +233,8 @@ export class CrawlConfigEditor extends LiteElement {
threshold: 0.2, // stricter; default is 0.6 threshold: 0.2, // stricter; default is 0.6
}); });
private validateNameMax = maxLengthValidator(50);
private get formHasError() { private get formHasError() {
return ( return (
!this.hasRequiredFields() || !this.hasRequiredFields() ||
@ -1437,10 +1439,11 @@ https://archiveweb.page/images/${"logo.svg"}`}
}; };
private renderJobMetadata() { private renderJobMetadata() {
const { helpText, validate } = maxLengthValidator(50); const { helpText, validate } = this.validateNameMax;
return html` return html`
${this.renderFormCol(html` ${this.renderFormCol(html`
<sl-input <sl-input
class="with-max-help-text"
name="jobName" name="jobName"
label=${msg("Name")} label=${msg("Name")}
autocomplete="off" autocomplete="off"
@ -1449,7 +1452,6 @@ https://archiveweb.page/images/${"logo.svg"}`}
})} })}
value=${this.formState.jobName} value=${this.formState.jobName}
help-text=${helpText} help-text=${helpText}
style="--help-text-align: right"
@sl-input=${validate} @sl-input=${validate}
></sl-input> ></sl-input>
`)} `)}

View File

@ -10,6 +10,7 @@ import { isAdmin, isCrawler, AccessCode } from "../../utils/orgs";
import type { OrgData } from "../../utils/orgs"; import type { OrgData } from "../../utils/orgs";
import type { CurrentUser } from "../../types/user"; import type { CurrentUser } from "../../types/user";
import type { APIPaginatedList } from "../../types/api"; import type { APIPaginatedList } from "../../types/api";
import { maxLengthValidator } from "../../utils/form";
type Tab = "information" | "members"; type Tab = "information" | "members";
type User = { type User = {
@ -90,6 +91,8 @@ export class OrgSettings extends LiteElement {
}; };
} }
private validateOrgNameMax = maxLengthValidator(50);
async willUpdate(changedProperties: Map<string, any>) { async willUpdate(changedProperties: Map<string, any>) {
if (changedProperties.has("isAddingMember") && this.isAddingMember) { if (changedProperties.has("isAddingMember") && this.isAddingMember) {
this.isAddMemberFormVisible = true; this.isAddMemberFormVisible = true;
@ -162,29 +165,27 @@ export class OrgSettings extends LiteElement {
private renderInformation() { private renderInformation() {
return html`<div class="rounded border p-5"> return html`<div class="rounded border p-5">
<form @submit=${this.onOrgNameSubmit}> <form class="inline-control-form" @submit=${this.onOrgNameSubmit}>
<div class="flex items-end"> <sl-input
<div class="flex-1 mr-3"> class="inline-control-input with-max-help-text"
<sl-input name="orgName"
name="orgName" size="small"
size="small" label=${msg("Org Name")}
label=${msg("Org Name")} autocomplete="off"
autocomplete="off" value=${this.org.name}
value=${this.org.name} required
required help-text=${this.validateOrgNameMax.helpText}
></sl-input> @sl-input=${this.validateOrgNameMax.validate}
</div> ></sl-input>
<div class="flex-0"> <sl-button
<sl-button class="inline-control-button"
type="submit" type="submit"
size="small" size="small"
variant="primary" variant="primary"
?disabled=${this.isSavingOrgName} ?disabled=${this.isSavingOrgName}
?loading=${this.isSavingOrgName} ?loading=${this.isSavingOrgName}
>${msg("Save Changes")}</sl-button >${msg("Save Changes")}</sl-button
> >
</div>
</div>
</form> </form>
</div>`; </div>`;
} }

View File

@ -181,6 +181,44 @@ const theme = css`
min-width: min-content; min-width: min-content;
} }
/* For single-input forms with submit button inline */
/* Requires form control and button to be direct children */
.inline-control-input,
.inline-control-input::part(form-control) {
display: contents;
}
.inline-control-form {
display: grid;
grid-template-areas:
"label ."
"input button"
"help-text .";
grid-template-columns: 1fr max-content;
column-gap: var(--sl-spacing-small);
}
.inline-control-input::part(form-control-label) {
grid-area: label;
}
.inline-control-input::part(form-control-input) {
grid-area: input;
}
.inline-control-input::part(form-control-help-text) {
grid-area: help-text;
}
.inline-control-button {
grid-area: button;
}
/* Inputs with "Max N characters" help text */
.with-max-help-text {
--help-text-align: right;
}
/* Aesthetically closer to monospaced font: */ /* Aesthetically closer to monospaced font: */
.font-monostyle { .font-monostyle {
font-family: var(--font-monostyle-family); font-family: var(--font-monostyle-family);