Introduce a commercial license option alongside AGPL-3.0-only, require a CLA for contributors, and document the terms in COMMERCIAL.md and NOTICE. Add a script to stamp SPDX headers on Go files and apply it across the tree.
61 lines
2.1 KiB
Go
61 lines
2.1 KiB
Go
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial
|
|
// SPDX-FileCopyrightText: 2025-2026 Christian Galo
|
|
|
|
package web
|
|
|
|
import "git.coopcloud.tech/wiki-cafe/member-console/internal/forms"
|
|
|
|
// The group-mapping form (spec discourse-operator-surface "Entitlement-to-
|
|
// group mapping management"; spec form-library; design D2, D12; finding
|
|
// FA-8). A dense sub-record form, like every other add-a-row panel on the
|
|
// operator surface: the entitlement select opens with a disabled, selected
|
|
// "Choose an entitlement" placeholder, so the browser cannot preselect a
|
|
// resource key the operator never chose, and a submission whose entitlement
|
|
// is not one of the offered options is refused rather than resolved to a
|
|
// default.
|
|
//
|
|
// This file is the form's home; the registry is only the index (design
|
|
// D1). It sits beside operator.go, which parses through the declaration
|
|
// and never through r.FormValue. The integration imports internal/forms
|
|
// directly and registers through the same forms.Register every console
|
|
// form uses.
|
|
|
|
const mappingFormName = "discourse.mapping.create"
|
|
|
|
var mappingForm = forms.Register(forms.FormSpec{
|
|
Name: mappingFormName,
|
|
Kind: forms.KindSubRecord,
|
|
Family: forms.Dense,
|
|
Method: "POST",
|
|
Path: "/partials/operator/discourse/mappings",
|
|
Target: "#operator-body",
|
|
Swap: "innerHTML",
|
|
Fields: []forms.Field{
|
|
{
|
|
Name: "resource_key",
|
|
Label: "Entitlement",
|
|
Control: forms.Select,
|
|
RuntimeOptions: true,
|
|
},
|
|
{
|
|
Name: "group_name",
|
|
Label: "Discourse group name",
|
|
Control: forms.Text,
|
|
Placeholder: "e.g. members",
|
|
Autocomplete: "off",
|
|
},
|
|
},
|
|
Commit: "Map group",
|
|
})
|
|
|
|
// mappingFormOptions is the option map both the render and the parse read,
|
|
// so what the select offered and what the handler accepts are one list
|
|
// (finding FA-8).
|
|
func mappingFormOptions(keys []ResourceKeyOption) map[string][]forms.Option {
|
|
options := []forms.Option{forms.ChooseOption("an entitlement")}
|
|
for _, k := range keys {
|
|
options = append(options, forms.Option{Value: k.Key, Label: k.DisplayName + " (" + k.Key + ")"})
|
|
}
|
|
return map[string][]forms.Option{"resource_key": options}
|
|
}
|