Realm list

This commit is contained in:
LittleSheep 2024-03-17 22:08:33 +08:00
parent 1505244726
commit cbea87f74d
9 changed files with 141 additions and 37 deletions

View File

@ -1,5 +1,13 @@
package models package models
type RealmType = int
const (
RealmTypePublic = RealmType(iota)
RealmTypeRestricted
RealmTypePrivate
)
type Realm struct { type Realm struct {
BaseModel BaseModel
@ -8,7 +16,7 @@ type Realm struct {
Articles []Article `json:"article"` Articles []Article `json:"article"`
Moments []Moment `json:"moments"` Moments []Moment `json:"moments"`
Members []RealmMember `json:"members"` Members []RealmMember `json:"members"`
IsPublic bool `json:"is_public"` RealmType RealmType `json:"realm_type"`
AccountID uint `json:"account_id"` AccountID uint `json:"account_id"`
} }

View File

@ -60,14 +60,14 @@ func createRealm(c *fiber.Ctx) error {
var data struct { var data struct {
Name string `json:"name" validate:"required"` Name string `json:"name" validate:"required"`
Description string `json:"description"` Description string `json:"description"`
IsPublic bool `json:"is_public"` RealmType int `json:"realm_type"`
} }
if err := BindAndValidate(c, &data); err != nil { if err := BindAndValidate(c, &data); err != nil {
return err return err
} }
realm, err := services.NewRealm(user, data.Name, data.Description, data.IsPublic) realm, err := services.NewRealm(user, data.Name, data.Description, data.RealmType)
if err != nil { if err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error()) return fiber.NewError(fiber.StatusBadRequest, err.Error())
} }
@ -150,7 +150,7 @@ func editRealm(c *fiber.Ctx) error {
var data struct { var data struct {
Name string `json:"name" validate:"required"` Name string `json:"name" validate:"required"`
Description string `json:"description"` Description string `json:"description"`
IsPublic bool `json:"is_public"` RealmType int `json:"realm_type"`
} }
if err := BindAndValidate(c, &data); err != nil { if err := BindAndValidate(c, &data); err != nil {
@ -165,7 +165,7 @@ func editRealm(c *fiber.Ctx) error {
return fiber.NewError(fiber.StatusNotFound, err.Error()) return fiber.NewError(fiber.StatusNotFound, err.Error())
} }
realm, err := services.EditRealm(realm, data.Name, data.Description, data.IsPublic) realm, err := services.EditRealm(realm, data.Name, data.Description, data.RealmType)
if err != nil { if err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error()) return fiber.NewError(fiber.StatusBadRequest, err.Error())
} }

View File

@ -274,7 +274,7 @@ func NewPost[T models.PostInterface](item T) (T, error) {
} }
if item.GetRealm() != nil { if item.GetRealm() != nil {
if !item.GetRealm().IsPublic { if item.GetRealm().RealmType != models.RealmTypePublic {
var member models.RealmMember var member models.RealmMember
if err := database.C.Where(&models.RealmMember{ if err := database.C.Where(&models.RealmMember{
RealmID: item.GetRealm().ID, RealmID: item.GetRealm().ID,

View File

@ -38,7 +38,7 @@ func ListRealmIsAvailable(user models.Account) ([]models.Realm, error) {
}) })
if err := database.C.Where(&models.Realm{ if err := database.C.Where(&models.Realm{
IsPublic: true, RealmType: models.RealmTypePublic,
}).Or("id IN ?", idx).Find(&realms).Error; err != nil { }).Or("id IN ?", idx).Find(&realms).Error; err != nil {
return realms, err return realms, err
} }
@ -46,12 +46,12 @@ func ListRealmIsAvailable(user models.Account) ([]models.Realm, error) {
return realms, nil return realms, nil
} }
func NewRealm(user models.Account, name, description string, isPublic bool) (models.Realm, error) { func NewRealm(user models.Account, name, description string, realmType int) (models.Realm, error) {
realm := models.Realm{ realm := models.Realm{
Name: name, Name: name,
Description: description, Description: description,
AccountID: user.ID, AccountID: user.ID,
IsPublic: isPublic, RealmType: realmType,
Members: []models.RealmMember{ Members: []models.RealmMember{
{AccountID: user.ID}, {AccountID: user.ID},
}, },
@ -86,10 +86,10 @@ func KickRealmMember(user models.Account, target models.Realm) error {
return database.C.Delete(&member).Error return database.C.Delete(&member).Error
} }
func EditRealm(realm models.Realm, name, description string, isPublic bool) (models.Realm, error) { func EditRealm(realm models.Realm, name, description string, realmType int) (models.Realm, error) {
realm.Name = name realm.Name = name
realm.Description = description realm.Description = description
realm.IsPublic = isPublic realm.RealmType = realmType
err := database.C.Save(&realm).Error err := database.C.Save(&realm).Error

View File

@ -2,7 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="icon" type="image/xml+svg" href="/favicon.svg"> <link rel="icon" type="image/xml+svg" href="/favicon.png">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Solarplaza</title> <title>Solarplaza</title>
</head> </head>

BIN
pkg/views/public/favicon.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 51 KiB

View File

@ -0,0 +1,116 @@
<template>
<v-list density="comfortable">
<v-list-subheader>Realms</v-list-subheader>
<v-list-item v-for="item in realms" prepend-icon="mdi-account-multiple" :title="item.name" />
<v-divider v-if="realms.length > 0" class="border-opacity-75 my-2" />
<v-list-item
prepend-icon="mdi-plus"
title="Create a realm"
:disabled="!id.userinfo.isLoggedIn"
@click="creating = true"
/>
</v-list>
<v-dialog v-model="creating" class="max-w-[540px]">
<v-card title="Create a realm" prepend-icon="mdi-account-multiple-plus" :loading="loading">
<v-form @submit.prevent="submit">
<v-card-text>
<v-text-field
label="Name"
variant="outlined"
density="comfortable"
v-model="requestData.name"
/>
<v-textarea
label="Description"
variant="outlined"
density="comfortable"
v-model="requestData.description"
/>
<v-select
label="Realm type"
item-title="label"
item-value="value"
variant="outlined"
density="comfortable"
:items="realmTypeOptions"
v-model="requestData.realm_type"
/>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn type="reset" color="grey-darken-3" @click="creating = false">Cancel</v-btn>
<v-btn type="submit" :disabled="loading">Save</v-btn>
</v-card-actions>
</v-form>
</v-card>
</v-dialog>
<!-- @vue-ignore -->
<v-snackbar v-model="error" :timeout="5000">Something went wrong... {{ error }}</v-snackbar>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { getAtk, useUserinfo } from "@/stores/userinfo";
const id = useUserinfo();
const realms = ref<any[]>([]);
const requestData = ref({
name: "",
description: "",
realm_type: 0
});
const realmTypeOptions = [
{ label: "Public Realm", value: 0 },
{ label: "Restricted Realm", value: 1 },
{ label: "Private Realm", value: 2 }
];
const creating = ref(false);
const error = ref<string | null>(null);
const reverting = ref(false);
const loading = ref(false);
async function list() {
reverting.value = true;
const res = await fetch("/api/realms/me/available", {
headers: { Authorization: `Bearer ${getAtk()}` }
});
if (res.status !== 200) {
error.value = await res.text();
} else {
realms.value = await res.json();
}
reverting.value = false;
}
async function submit(evt: SubmitEvent) {
const form = evt.target as HTMLFormElement;
const payload = requestData.value;
if (!payload.name) return;
loading.value = true;
const res = await fetch("/api/realms", {
method: "POST",
headers: { "Content-Type": "application/json", Authorization: `Bearer ${getAtk()}` },
body: JSON.stringify(payload)
});
if (res.status !== 200) {
error.value = await res.text();
} else {
await list();
form.reset();
creating.value = false;
}
loading.value = false;
}
list();
</script>

View File

@ -1,7 +1,7 @@
<template> <template>
<v-navigation-drawer v-model="drawerOpen" color="grey-lighten-5" floating> <v-navigation-drawer v-model="drawerOpen" color="grey-lighten-5" floating>
<div class="flex flex-col h-full"> <div class="flex flex-col h-full">
<v-list> <v-list class="border-b border-opacity-15 h-[64px]" style="border-bottom-width: thin">
<v-list-item :subtitle="username" :title="nickname"> <v-list-item :subtitle="username" :title="nickname">
<template #prepend> <template #prepend>
<v-avatar icon="mdi-account-circle" :image="id.userinfo.data?.avatar" /> <v-avatar icon="mdi-account-circle" :image="id.userinfo.data?.avatar" />
@ -27,7 +27,9 @@
</v-list-item> </v-list-item>
</v-list> </v-list>
<v-list density="compact" class="flex-grow-1" nav> </v-list> <div class="flex-grow-1">
<realm-list />
</div>
<div> <div>
<v-alert type="info" variant="tonal" class="text-sm"> <v-alert type="info" variant="tonal" class="text-sm">
@ -95,6 +97,7 @@ import { useEditor } from "@/stores/editor"
import { useUserinfo } from "@/stores/userinfo" import { useUserinfo } from "@/stores/userinfo"
import { useWellKnown } from "@/stores/wellKnown" import { useWellKnown } from "@/stores/wellKnown"
import PostAction from "@/components/publish/PostAction.vue" import PostAction from "@/components/publish/PostAction.vue"
import RealmList from "@/components/realms/RealmList.vue";
const id = useUserinfo() const id = useUserinfo()
const editor = useEditor() const editor = useEditor()