UX: move admin flag form to form-kit (#28187)

Rewrite the admin flag form to use FormKit. This is a draft because waiting for Checkbox improvements.
This commit is contained in:
Krzysztof Kotlarek
2024-08-05 11:01:25 +10:00
committed by GitHub
parent 2b577950af
commit 300ef67481
28 changed files with 648 additions and 416 deletions

View File

@@ -1,18 +1,13 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { fn, hash } from "@ember/helper";
import { TextArea } from "@ember/legacy-built-in-components";
import { on } from "@ember/modifier";
import { cached } from "@glimmer/tracking";
import { hash } from "@ember/helper";
import { action } from "@ember/object";
import { LinkTo } from "@ember/routing";
import { service } from "@ember/service";
import { isEmpty } from "@ember/utils";
import { not } from "truth-helpers";
import DButton from "discourse/components/d-button";
import withEventValue from "discourse/helpers/with-event-value";
import Form from "discourse/components/form";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
import dIcon from "discourse-common/helpers/d-icon";
import icon from "discourse-common/helpers/d-icon";
import i18n from "discourse-common/helpers/i18n";
import { bind } from "discourse-common/utils/decorators";
import I18n from "discourse-i18n";
@@ -23,33 +18,26 @@ export default class AdminFlagsForm extends Component {
@service router;
@service site;
@tracked enabled = true;
@tracked requireMessage = false;
@tracked name;
@tracked description;
@tracked appliesTo;
constructor() {
super(...arguments);
if (this.isUpdate) {
this.name = this.args.flag.name;
this.description = this.args.flag.description;
this.appliesTo = this.args.flag.applies_to;
this.requireMessage = this.args.flag.require_message;
this.enabled = this.args.flag.enabled;
}
}
get isUpdate() {
return this.args.flag;
}
get isValid() {
return (
!isEmpty(this.name) &&
!isEmpty(this.description) &&
!isEmpty(this.appliesTo)
);
@cached
get formData() {
if (this.isUpdate) {
return {
name: this.args.flag.name,
description: this.args.flag.description,
appliesTo: this.args.flag.applies_to,
requireMessage: this.args.flag.require_message,
enabled: this.args.flag.enabled,
};
} else {
return {
enabled: true,
requireMessage: false,
};
}
}
get header() {
@@ -71,64 +59,59 @@ export default class AdminFlagsForm extends Component {
});
}
@action
save() {
this.isUpdate ? this.update() : this.create();
}
@action
onToggleRequireMessage(e) {
this.requireMessage = e.target.checked;
}
@action
onToggleEnabled(e) {
this.enabled = e.target.checked;
}
@bind
create() {
return ajax(`/admin/config/flags`, {
type: "POST",
data: this.#formData,
})
.then((response) => {
this.site.flagTypes.push(response.flag);
this.router.transitionTo("adminConfig.flags");
})
.catch((error) => {
return popupAjaxError(error);
validateAppliesTo(name, value, { addError }) {
if (value && value.length === 0) {
addError("appliesTo", {
title: i18n("admin.config_areas.flags.form.applies_to"),
message: i18n("admin.config_areas.flags.form.invalid_applies_to"),
});
}
}
@bind
update() {
return ajax(`/admin/config/flags/${this.args.flag.id}`, {
type: "PUT",
data: this.#formData,
})
.then((response) => {
this.args.flag.name = response.flag.name;
this.args.flag.description = response.flag.description;
this.args.flag.applies_to = response.flag.applies_to;
this.args.flag.require_message = response.flag.require_message;
this.args.flag.enabled = response.flag.enabled;
this.router.transitionTo("adminConfig.flags");
})
.catch((error) => {
return popupAjaxError(error);
});
}
@bind
get #formData() {
return {
name: this.name,
description: this.description,
applies_to: this.appliesTo,
require_message: this.requireMessage,
enabled: this.enabled,
@action
save({ name, description, appliesTo, requireMessage, enabled }) {
const createOrUpdate = this.isUpdate ? this.update : this.create;
const data = {
name,
description,
enabled,
applies_to: appliesTo,
require_message: requireMessage,
};
createOrUpdate(data);
}
@bind
async create(data) {
try {
const response = await ajax("/admin/config/flags", {
type: "POST",
data,
});
this.site.flagTypes.push(response.flag);
this.router.transitionTo("adminConfig.flags");
} catch (error) {
popupAjaxError(error);
}
}
@bind
async update(data) {
try {
const response = await ajax(`/admin/config/flags/${this.args.flag.id}`, {
type: "PUT",
data,
});
this.args.flag.name = response.flag.name;
this.args.flag.description = response.flag.description;
this.args.flag.applies_to = response.flag.applies_to;
this.args.flag.require_message = response.flag.require_message;
this.args.flag.enabled = response.flag.enabled;
this.router.transitionTo("adminConfig.flags");
} catch (error) {
popupAjaxError(error);
}
}
<template>
@@ -138,89 +121,78 @@ export default class AdminFlagsForm extends Component {
@route="adminConfig.flags"
class="btn-default btn btn-icon-text btn-back"
>
{{dIcon "chevron-left"}}
{{icon "chevron-left"}}
{{i18n "admin.config_areas.flags.back"}}
</LinkTo>
<div class="admin-config-area__primary-content admin-flag-form">
<AdminConfigAreaCard @heading={{this.header}}>
<div class="control-group">
<label for="name">
{{i18n "admin.config_areas.flags.form.name"}}
</label>
<input
name="name"
type="text"
value={{this.name}}
maxlength="200"
class="admin-flag-form__name"
{{on "input" (withEventValue (fn (mut this.name)))}}
/>
</div>
<Form @onSubmit={{this.save}} @data={{this.formData}} as |form|>
<form.Field
@name="name"
@title={{i18n "admin.config_areas.flags.form.name"}}
@validation="required|length:3,200"
@format="large"
as |field|
>
<field.Input />
</form.Field>
<div class="control-group">
<label for="description">
{{i18n "admin.config_areas.flags.form.description"}}
</label>
<TextArea
@value={{this.description}}
maxlength="1000"
class="admin-flag-form__description"
/>
</div>
<form.Field
@name="description"
@title={{i18n "admin.config_areas.flags.form.description"}}
@validation="length:0,1000"
as |field|
>
<field.Textarea @height={{60}} />
</form.Field>
<div class="control-group">
<label for="applies-to">
{{i18n "admin.config_areas.flags.form.applies_to"}}
</label>
<MultiSelect
@value={{this.appliesTo}}
@content={{this.appliesToValues}}
@options={{hash allowAny=false}}
class="admin-flag-form__applies-to"
/>
</div>
<form.Field
@name="appliesTo"
@title={{i18n "admin.config_areas.flags.form.applies_to"}}
@validation="required"
@validate={{this.validateAppliesTo}}
as |field|
>
<field.Custom>
<MultiSelect
@id={{field.id}}
@value={{field.value}}
@onChange={{field.set}}
@content={{this.appliesToValues}}
@options={{hash allowAny=false}}
class="admin-flag-form__applies-to"
/>
</field.Custom>
</form.Field>
<div class="control-group">
<label class="checkbox-label admin-flag-form__require-reason">
<input
{{on "input" this.onToggleRequireMessage}}
type="checkbox"
checked={{this.requireMessage}}
/>
<div>
{{i18n "admin.config_areas.flags.form.require_message"}}
<div class="admin-flag-form__require-message-description">
<form.CheckboxGroup as |checkboxGroup|>
<checkboxGroup.Field
@name="requireMessage"
@title={{i18n "admin.config_areas.flags.form.require_message"}}
as |field|
>
<field.Checkbox>
{{i18n
"admin.config_areas.flags.form.require_message_description"
}}
</div>
</div>
</label>
</div>
</field.Checkbox>
</checkboxGroup.Field>
<div class="control-group">
<label class="checkbox-label admin-flag-form__enabled">
<input
{{on "input" this.onToggleEnabled}}
type="checkbox"
checked={{this.enabled}}
/>
{{i18n "admin.config_areas.flags.form.enabled"}}
</label>
</div>
<checkboxGroup.Field
@name="enabled"
@title={{i18n "admin.config_areas.flags.form.enabled"}}
as |field|
>
<field.Checkbox />
</checkboxGroup.Field>
</form.CheckboxGroup>
<div class="alert alert-info admin_flag_form__info">
{{dIcon "info-circle"}}
{{i18n "admin.config_areas.flags.form.alert"}}
</div>
<form.Alert @icon="info-circle">
{{i18n "admin.config_areas.flags.form.alert"}}
</form.Alert>
<DButton
@action={{this.save}}
@label="admin.config_areas.flags.form.save"
@ariaLabel="admin.config_areas.flags.form.save"
@disabled={{not this.isValid}}
class="btn-primary admin-flag-form__save"
/>
<form.Submit @label="admin.config_areas.flags.form.save" />
</Form>
</AdminConfigAreaCard>
</div>
</div>