landed code for creating community (untested)
This commit is contained in:
+133
-7
@@ -54,6 +54,7 @@ func CommunityAdminMenu(ctxt ui.AmContext) (string, any, error) {
|
||||
return "framed_template", "menu.jet", nil
|
||||
}
|
||||
|
||||
// setupCommunityProfileDialog sets up fields in the Community Profile dialog.
|
||||
func setupCommunityProfileDialog(dlg *ui.Dialog, comm *database.Community) {
|
||||
dlg.SetCommunity(comm)
|
||||
if comm.IsAdmin {
|
||||
@@ -108,7 +109,6 @@ func CommunityProfileForm(ctxt ui.AmContext) (string, any, error) {
|
||||
dlg, err := ui.AmLoadDialog("commprofile")
|
||||
if err == nil {
|
||||
setupCommunityProfileDialog(dlg, comm)
|
||||
dlg.Field("cc").Value = fmt.Sprintf("%d", comm.Id)
|
||||
dlg.Field("name").Value = comm.Name
|
||||
dlg.Field("alias").Value = comm.Alias
|
||||
dlg.Field("synopsis").SetVal(comm.Synopsis)
|
||||
@@ -143,10 +143,16 @@ func CommunityProfileForm(ctxt ui.AmContext) (string, any, error) {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
|
||||
// levelFld is a quick routine to extract a level value from a drop-down.
|
||||
func levelFld(d *ui.Dialog, name string) uint16 {
|
||||
v, _ := strconv.Atoi(d.Field(name).Value)
|
||||
return uint16(v)
|
||||
// validateJoinKey is an extra validation step for the join key.
|
||||
func validateJoinKey(dlg *ui.Dialog) error {
|
||||
if dlg.Field("comtype").Value == "1" {
|
||||
if dlg.Field("joinkey").IsEmpty() {
|
||||
return errors.New("private community must specify a join key")
|
||||
}
|
||||
} else {
|
||||
dlg.Field("joinkey").Value = ""
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/* EditCommunityProfile updates the community's profile from the dialog.
|
||||
@@ -182,6 +188,10 @@ func EditCommunityProfile(ctxt ui.AmContext) (string, any, error) {
|
||||
if err != nil {
|
||||
return dlg.RenderError(ctxt, err.Error())
|
||||
}
|
||||
err = validateJoinKey(dlg)
|
||||
if err != nil {
|
||||
return dlg.RenderError(ctxt, err.Error())
|
||||
}
|
||||
var ci *database.ContactInfo
|
||||
ci, err = comm.ContactInfo()
|
||||
if err != nil {
|
||||
@@ -222,8 +232,8 @@ func EditCommunityProfile(ctxt ui.AmContext) (string, any, error) {
|
||||
}
|
||||
err = comm.SetProfileData(dlg.Field("name").Value, dlg.Field("alias").Value, dlg.Field("synopsis").ValPtr(),
|
||||
dlg.Field("rules").ValPtr(), dlg.Field("language").ValPtr(), joinkey, dlg.Field("membersonly").IsChecked(),
|
||||
hidedir, hidesearch, levelFld(dlg, "read_lvl"), levelFld(dlg, "write_lvl"), levelFld(dlg, "create_lvl"),
|
||||
levelFld(dlg, "delete_lvl"), levelFld(dlg, "join_lvl"))
|
||||
hidedir, hidesearch, dlg.Field("read_lvl").GetLevel(), dlg.Field("write_lvl").GetLevel(),
|
||||
dlg.Field("create_lvl").GetLevel(), dlg.Field("delete_lvl").GetLevel(), dlg.Field("join_lvl").GetLevel())
|
||||
}
|
||||
if err == nil {
|
||||
flags.Set(database.CommunityFlagPicturesInPosts, dlg.Field("pic_in_post").IsChecked())
|
||||
@@ -241,6 +251,14 @@ func EditCommunityProfile(ctxt ui.AmContext) (string, any, error) {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
|
||||
/* CommunityLogoForm renders the form for changing the community logo.
|
||||
* Parameters:
|
||||
* ctxt - The AmContext for the request.
|
||||
* Returns:
|
||||
* Command string dictating what to be rendered.
|
||||
* Data as a parameter for the command string.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func CommunityLogoForm(ctxt ui.AmContext) (string, any, error) {
|
||||
err := ctxt.SetCommunityContext(ctxt.URLParam("cid"))
|
||||
if err != nil {
|
||||
@@ -263,6 +281,14 @@ func CommunityLogoForm(ctxt ui.AmContext) (string, any, error) {
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
|
||||
/* EditCommunityLogo handles setting the community logo.
|
||||
* Parameters:
|
||||
* ctxt - The AmContext for the request.
|
||||
* Returns:
|
||||
* Command string dictating what to be rendered.
|
||||
* Data as a parameter for the command string.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func EditCommunityLogo(ctxt ui.AmContext) (string, any, error) {
|
||||
err := ctxt.SetCommunityContext(ctxt.URLParam("cid"))
|
||||
if err != nil {
|
||||
@@ -341,3 +367,103 @@ func EditCommunityLogo(ctxt ui.AmContext) (string, any, error) {
|
||||
}
|
||||
return ui.ErrorPage(ctxt, errors.New("invalid button detected in logo upload"))
|
||||
}
|
||||
|
||||
/* CreateCommunityForm renders the form for creating a new community.
|
||||
* Parameters:
|
||||
* ctxt - The AmContext for the request.
|
||||
* Returns:
|
||||
* Command string dictating what to be rendered.
|
||||
* Data as a parameter for the command string.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func CreateCommunityForm(ctxt ui.AmContext) (string, any, error) {
|
||||
user := ctxt.CurrentUser()
|
||||
if user.BaseLevel < uint16(ctxt.Globals().CommunityCreateLevel) {
|
||||
ctxt.SetRC(http.StatusForbidden)
|
||||
return ui.ErrorPage(ctxt, errors.New("you are not permitted to create a community"))
|
||||
}
|
||||
dlg, err := ui.AmLoadDialog("create_comm")
|
||||
if err != nil {
|
||||
dlg.Field("language").Value = "en-US"
|
||||
dlg.Field("country").Value = "US"
|
||||
return dlg.Render(ctxt)
|
||||
}
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
|
||||
/* CreateCommunity creates a new community.
|
||||
* Parameters:
|
||||
* ctxt - The AmContext for the request.
|
||||
* Returns:
|
||||
* Command string dictating what to be rendered.
|
||||
* Data as a parameter for the command string.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func CreateCommunity(ctxt ui.AmContext) (string, any, error) {
|
||||
user := ctxt.CurrentUser()
|
||||
if user.BaseLevel < uint16(ctxt.Globals().CommunityCreateLevel) {
|
||||
ctxt.SetRC(http.StatusForbidden)
|
||||
return ui.ErrorPage(ctxt, errors.New("you are not permitted to create a community"))
|
||||
}
|
||||
dlg, err := ui.AmLoadDialog("create_comm")
|
||||
if err != nil {
|
||||
dlg.LoadFromForm(ctxt)
|
||||
action := dlg.WhichButton(ctxt)
|
||||
if action == "cancel" {
|
||||
return "redirect", "/", nil
|
||||
}
|
||||
if action == "create" {
|
||||
err = dlg.Validate()
|
||||
if err != nil {
|
||||
return dlg.RenderError(ctxt, err.Error())
|
||||
}
|
||||
err = validateJoinKey(dlg)
|
||||
if err != nil {
|
||||
return dlg.RenderError(ctxt, err.Error())
|
||||
}
|
||||
var testcomm *database.Community
|
||||
testcomm, err = database.AmGetCommunityByAlias(dlg.Field("alias").Value)
|
||||
if err != nil {
|
||||
return dlg.RenderError(ctxt, err.Error())
|
||||
}
|
||||
if testcomm != nil {
|
||||
return dlg.RenderError(ctxt, fmt.Sprintf("A community with the alias \"%s\" already exists; please try again.", testcomm.Alias))
|
||||
}
|
||||
var hideDir, hideSearch bool
|
||||
switch dlg.Field("hidemode").Value {
|
||||
case "NONE":
|
||||
hideDir = false
|
||||
hideSearch = false
|
||||
case "DIRECTORY":
|
||||
hideDir = true
|
||||
hideSearch = false
|
||||
case "BOTH":
|
||||
hideDir = true
|
||||
hideSearch = true
|
||||
}
|
||||
var comm *database.Community
|
||||
comm, err = database.AmCreateCommunity(dlg.Field("name").Value, dlg.Field("alias").Value, user.Uid,
|
||||
dlg.Field("language").ValPtr(), dlg.Field("synopsis").ValPtr(), dlg.Field("rules").ValPtr(),
|
||||
dlg.Field("joinkey").ValPtr(), hideDir, hideSearch, ctxt.RemoteIP())
|
||||
if err != nil {
|
||||
return dlg.RenderError(ctxt, err.Error())
|
||||
}
|
||||
ci := database.AmNewCommunityContactInfo(user.Uid, comm.Id)
|
||||
ci.Locality = dlg.Field("loc").ValPtr()
|
||||
ci.Region = dlg.Field("reg").ValPtr()
|
||||
ci.PostalCode = dlg.Field("pcode").ValPtr()
|
||||
ci.Country = dlg.Field("country").ValPtr()
|
||||
_, err = ci.Save()
|
||||
if err == nil {
|
||||
err = comm.SetContactID(ci.ContactId)
|
||||
}
|
||||
if err != nil {
|
||||
return dlg.RenderError(ctxt, err.Error())
|
||||
}
|
||||
// new community is now created! redirect to the new profile
|
||||
return "redirect", fmt.Sprintf("/comm/%s/profile", comm.Alias), nil
|
||||
}
|
||||
return dlg.RenderError(ctxt, "No known button click on POST to community creation.")
|
||||
}
|
||||
return ui.ErrorPage(ctxt, err)
|
||||
}
|
||||
|
||||
@@ -46,6 +46,18 @@ const (
|
||||
AuditAdminChangeUserAccount = 111
|
||||
AuditAdminSetAccountSecurity = 112
|
||||
AuditAdminLockUnlockAccount = 113
|
||||
AuditCommunityCreate = 201
|
||||
AuditCommunitySetMembership = 202
|
||||
AuditCommuntiyContactInfo = 203
|
||||
AuditCommunityFeatureSet = 204
|
||||
AuditCommunityName = 205
|
||||
AuditCommunityAlias = 206
|
||||
AuditCommunityCategory = 207
|
||||
AuditCommunityHideInfo = 208
|
||||
AuditCommunityMembersOnly = 209
|
||||
AuditCommunityJoinKey = 210
|
||||
AuditCommunitySecurity = 211
|
||||
AuditCommunityDelete = 212
|
||||
)
|
||||
|
||||
// auditWriteQueue is a channel to store audit records in the background.
|
||||
|
||||
+125
-9
@@ -10,6 +10,7 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strconv"
|
||||
@@ -248,10 +249,11 @@ func (c *Community) Flags() (*util.OptionSet, error) {
|
||||
return nil, err
|
||||
}
|
||||
if s == nil {
|
||||
return nil, fmt.Errorf("missing flags for community %d", c.Id)
|
||||
}
|
||||
c.flags = util.NewOptionSet()
|
||||
} else {
|
||||
c.flags = util.OptionSetFromString(*s)
|
||||
}
|
||||
}
|
||||
return c.flags, nil
|
||||
}
|
||||
|
||||
@@ -302,6 +304,17 @@ func (c *Community) SetProfileData(name string, alias string, synopsis *string,
|
||||
return err
|
||||
}
|
||||
|
||||
// SetContactID sets the contact ID for the community.
|
||||
func (c *Community) SetContactID(cid int32) error {
|
||||
c.Mutex.Lock()
|
||||
defer c.Mutex.Unlock()
|
||||
if _, err := amdb.Exec("UPDATE communities SET contactid = ? WHERE commid = ?", cid, c.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
c.ContactId = cid
|
||||
return nil
|
||||
}
|
||||
|
||||
/* AmGetCommunity returns a reference to the specified community.
|
||||
* Parameters:
|
||||
* id - The ID of the community.
|
||||
@@ -331,6 +344,27 @@ func AmGetCommunity(id int32) (*Community, error) {
|
||||
return rc.(*Community), err
|
||||
}
|
||||
|
||||
/* AmGetCommunityByAlias returns a reference to the specified community.
|
||||
* Parameters:
|
||||
* alias - The alias for the community.
|
||||
* Returns:
|
||||
* Pointer to Community containing community data, or nil
|
||||
* Standard Go error status (nil if community not found)
|
||||
*/
|
||||
func AmGetCommunityByAlias(alias string) (*Community, error) {
|
||||
rs, err := amdb.Query("SELECT commid FROM communities WHERE alias = ?", alias)
|
||||
if err == nil {
|
||||
if rs.Next() {
|
||||
var cid int32
|
||||
rs.Scan(&cid)
|
||||
return AmGetCommunity(cid)
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
/* AmGetCommunityFromParam returns a reference to the specified community based on the parameter.
|
||||
* If the parameter is numeric, it's interpreted as a community ID. Otherwise, it's interpreted
|
||||
* as a community alias.
|
||||
@@ -349,17 +383,13 @@ func AmGetCommunityFromParam(param string) (*Community, error) {
|
||||
}
|
||||
// else fall through to trying as alias
|
||||
}
|
||||
rs, err := amdb.Query("SELECT commid FROM communities WHERE alias = ?", param)
|
||||
rc, err := AmGetCommunityByAlias(param)
|
||||
if err == nil {
|
||||
if rs.Next() {
|
||||
var cid int32
|
||||
rs.Scan(&cid)
|
||||
return AmGetCommunity(cid)
|
||||
} else {
|
||||
if rc == nil {
|
||||
return nil, fmt.Errorf("community with alias \"%s\" not found", param)
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
return rc, err
|
||||
}
|
||||
|
||||
/* AmGetCommunitiesForUser returns a list of communities the user is a member of.
|
||||
@@ -482,6 +512,8 @@ func AmGetCommunityProperty(cid int32, ndx int32) (*string, error) {
|
||||
p, err := internalGetCommProp(cid, ndx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if p == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return p.Data, nil
|
||||
}
|
||||
@@ -515,3 +547,87 @@ func AmSetCommunityProperty(cid int32, ndx int32, val *string) error {
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
/* AmCreateCommunity creates a new community.
|
||||
* Parameters:
|
||||
* name - The name for the new community.
|
||||
* alias - The alias for the new community. Must be unique.
|
||||
* hostUid - The UID of the creator and new host of the community.
|
||||
* language - Community default language.
|
||||
* synopsis - Community synopsis string.
|
||||
* rules - Community rules string.
|
||||
* joinkey - Community join key, or empty string for a public community.
|
||||
* hideDirectory - true to hide this community from the directory listings.
|
||||
* hideSearch - true to hide this community from searches.
|
||||
* remoteIP - Remote IP address for audit record.
|
||||
* Returns:
|
||||
* Pointer to new Community record, or nil.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmCreateCommunity(name string, alias string, hostUid int32, language *string, synopsis *string,
|
||||
rules *string, joinkey *string, hideDirectory bool, hideSearch bool, remoteIP string) (*Community, error) {
|
||||
var ar *AuditRecord = nil
|
||||
defer func() {
|
||||
AmStoreAudit(ar)
|
||||
}()
|
||||
|
||||
unlock := true
|
||||
amdb.Exec("LOCK TABLES communities WRITE, commftrs WRITE, commmember WRITE;")
|
||||
defer func() {
|
||||
if unlock {
|
||||
amdb.Exec("UNLOCK TABLES;")
|
||||
}
|
||||
}()
|
||||
|
||||
// validate alias does not already exist
|
||||
rs, err := amdb.Query("SELECT commid FROM communities WHERE alias = ?", alias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rs.Next() {
|
||||
return nil, errors.New("a community with that alias already exists")
|
||||
}
|
||||
|
||||
// establish the community record
|
||||
_, err = amdb.Exec(`INSERT INTO communities (createdate, lastaccess, lastupdate, read_lvl, write_lvl,
|
||||
create_lvl, delete_lvl, join_lvl, host_uid, hide_dir, hide_search, commname, language,
|
||||
synopsis, rules, joinkey, alias) VALUES (NOW(), NOW(), NOW(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
AmRoleList("Community.Read").Default().Level(), AmRoleList("Community.Write").Default().Level(),
|
||||
AmRoleList("Community.Create").Default().Level(), AmRoleList("Community.Delete").Default().Level(),
|
||||
AmRoleList("Community.Join").Default().Level(), hostUid, hideDirectory, hideSearch, name, language,
|
||||
synopsis, rules, joinkey, alias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Read back the community, which also puts it in the cache.
|
||||
comm, err := AmGetCommunityByAlias(alias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if comm == nil {
|
||||
return nil, errors.New("unable to find newly-generated community")
|
||||
}
|
||||
|
||||
// Establish the community services.
|
||||
err = AmEstablishCommunityServices(comm.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the new host has host privileges in the community. The host's membership is "locked" so they
|
||||
// can't unjoin and leave the community hostless.
|
||||
_, err = amdb.Exec("INSERT INTO commmember (commid, uid, granted_lvl, locked) VALUES (?, ?, ?, 1)", comm.Id, hostUid,
|
||||
AmDefaultRole("Community.Creator").Level())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stuffMembership(comm.Id, hostUid, true, true, AmDefaultRole("Community.Creator").Level())
|
||||
|
||||
amdb.Exec("UNLOCK TABLES;")
|
||||
unlock = false
|
||||
|
||||
// operation was a success - add an audit record
|
||||
ar = AmNewAudit(AuditCommunityCreate, hostUid, remoteIP, fmt.Sprintf("id=%d", comm.Id),
|
||||
fmt.Sprintf("name=%s", comm.Name), fmt.Sprintf("alias=%s", comm.Alias))
|
||||
return comm, nil
|
||||
}
|
||||
|
||||
@@ -250,3 +250,15 @@ func AmNewUserContactInfo(uid int32) *ContactInfo {
|
||||
rc := ContactInfo{OwnerUid: uid, OwnerCommId: -1}
|
||||
return &rc
|
||||
}
|
||||
|
||||
/* AmNewCommunityContactInfo creates a new contact info record for the community.
|
||||
* Parameters:
|
||||
* uid - The UID of the host of this community.
|
||||
* cid - The community ID of the owning community.
|
||||
* Returns:
|
||||
* New ContactInfo structure.
|
||||
*/
|
||||
func AmNewCommunityContactInfo(uid int32, cid int32) *ContactInfo {
|
||||
rc := ContactInfo{OwnerUid: uid, OwnerCommId: cid}
|
||||
return &rc
|
||||
}
|
||||
|
||||
@@ -114,3 +114,27 @@ func AmGetCommunityServices(cid int32) ([]*ServiceDef, error) {
|
||||
}
|
||||
return rc.([]*ServiceDef), nil
|
||||
}
|
||||
|
||||
/* AmEstablishCommunityServices extablishes the service (feature) records for a new community.
|
||||
* Parameters:
|
||||
* cid - ID of the new community.
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func AmEstablishCommunityServices(cid int32) error {
|
||||
dom := serviceRoot.byName["community"]
|
||||
a := make([]*ServiceDef, 0, len(dom.Services))
|
||||
for i, svc := range dom.Services {
|
||||
if svc.Default {
|
||||
_, err := amdb.Exec("INSERT INTO commftrs (commid, ftr_code) VALUES (?, ?)", cid, svc.Index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a = append(a, &(dom.Services[i]))
|
||||
}
|
||||
}
|
||||
servicesCacheMutex.Lock()
|
||||
servicesCache.Add(cid, a)
|
||||
servicesCacheMutex.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -64,6 +64,8 @@ func setupEcho() *echo.Echo {
|
||||
e.GET("/user/:uname", ui.AmWrap(ShowProfile))
|
||||
e.POST("/quick_email", ui.AmWrap(QuickEMail))
|
||||
e.GET("/sysadmin", ui.AmWrap(SysAdminMenu))
|
||||
e.GET("/create_comm", ui.AmWrap(CreateCommunityForm))
|
||||
e.POST("/create_comm", ui.AmWrap(CreateCommunity))
|
||||
e.GET("/comm/:cid/profile", ui.AmWrap(ShowCommunity))
|
||||
e.GET("/comm/:cid/admin", ui.AmWrap(CommunityAdminMenu))
|
||||
e.GET("/comm/:cid/admin/profile", ui.AmWrap(CommunityProfileForm))
|
||||
|
||||
@@ -13,9 +13,6 @@ title: "Edit Community Profile:"
|
||||
subtitle: "[CNAME]"
|
||||
action: "/comm/[CID]/admin/profile"
|
||||
fields:
|
||||
- type: "hidden"
|
||||
name: "cc"
|
||||
value: ""
|
||||
- type: "header"
|
||||
name: "header1"
|
||||
caption: "Basic Information"
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
#
|
||||
# Amsterdam Web Communities System
|
||||
# Copyright (c) 2025 Erbosoft Metaverse Design Solutions, All Rights Reserved
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
name: "create.community"
|
||||
formName: "createcommform"
|
||||
menuSelector: "top"
|
||||
title: "Create New Community"
|
||||
action: "/create_comm"
|
||||
fields:
|
||||
- type: "header"
|
||||
name: "header1"
|
||||
caption: "Basic Information"
|
||||
- type: "text"
|
||||
name: "name"
|
||||
caption: "Community Name"
|
||||
required: true
|
||||
size: 32
|
||||
maxlength: 128
|
||||
- type: "ams_id"
|
||||
name: "alias"
|
||||
caption: "Community Alias"
|
||||
required: true
|
||||
size: 32
|
||||
maxlength: 32
|
||||
- type: "text"
|
||||
name: "synopsis"
|
||||
caption: "Synopsis"
|
||||
size: 32
|
||||
maxlength: 255
|
||||
- type: "text"
|
||||
name: "rules"
|
||||
caption: "Rules"
|
||||
size: 32
|
||||
maxlength: 255
|
||||
- type: "localelist"
|
||||
name: "language"
|
||||
caption: "Primary Language"
|
||||
required: true
|
||||
- type: "header"
|
||||
name: "header2"
|
||||
caption: "Location"
|
||||
- type: "text"
|
||||
name: "loc"
|
||||
caption: "City"
|
||||
required: true
|
||||
size: 32
|
||||
maxlength: 64
|
||||
- type: "text"
|
||||
name: "reg"
|
||||
caption: "State/Province"
|
||||
required: true
|
||||
size: 32
|
||||
maxlength: 64
|
||||
- type: "text"
|
||||
name: "pcode"
|
||||
caption: "Zip/Postal Code"
|
||||
required: true
|
||||
size: 32
|
||||
maxlength: 64
|
||||
- type: "countrylist"
|
||||
name: "country"
|
||||
caption: "Country"
|
||||
required: true
|
||||
- type: "header"
|
||||
name: "header3"
|
||||
caption: "Security"
|
||||
- type: "dropdown"
|
||||
name: "comtype"
|
||||
caption: "Community type"
|
||||
required: true
|
||||
choices:
|
||||
- id: "0"
|
||||
text: "Public"
|
||||
default: true
|
||||
- id: "1"
|
||||
text: "Private"
|
||||
- type: "text"
|
||||
name: "joinkey"
|
||||
caption: "Join Key"
|
||||
subcaption: "(for private communities)"
|
||||
size: 32
|
||||
maxlength: 64
|
||||
- type: "dropdown"
|
||||
name: "hidemode"
|
||||
caption: "Community visibility"
|
||||
required: true
|
||||
choices:
|
||||
- id: "NONE"
|
||||
text: "Show in both directory and search"
|
||||
default: true
|
||||
- id: "DIRECTORY"
|
||||
text: "Hide in directory, but not in search"
|
||||
- id: "BOTH"
|
||||
text: "Hide in both directory and search"
|
||||
- type: "button"
|
||||
name: "create"
|
||||
caption: "Create"
|
||||
param: "blue"
|
||||
- type: "button"
|
||||
name: "cancel"
|
||||
caption: "Cancel"
|
||||
param: "red"
|
||||
@@ -35,7 +35,7 @@
|
||||
{{ if sb.Flags["canCreate"] }}|{{ end }}
|
||||
{{ end }}
|
||||
{{ if sb.Flags["canCreate"] }}
|
||||
<a href="/TODO/create_comm" class="text-blue-700 hover:text-blue-900">Create New</a>
|
||||
<a href="/create_comm" class="text-blue-700 hover:text-blue-900">Create New</a>
|
||||
{{ end }}
|
||||
]
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user