✨ Realm list
This commit is contained in:
		@@ -1,5 +1,13 @@
 | 
			
		||||
package models
 | 
			
		||||
 | 
			
		||||
type RealmType = int
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	RealmTypePublic = RealmType(iota)
 | 
			
		||||
	RealmTypeRestricted
 | 
			
		||||
	RealmTypePrivate
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Realm struct {
 | 
			
		||||
	BaseModel
 | 
			
		||||
 | 
			
		||||
@@ -8,7 +16,7 @@ type Realm struct {
 | 
			
		||||
	Articles    []Article     `json:"article"`
 | 
			
		||||
	Moments     []Moment      `json:"moments"`
 | 
			
		||||
	Members     []RealmMember `json:"members"`
 | 
			
		||||
	IsPublic    bool          `json:"is_public"`
 | 
			
		||||
	RealmType   RealmType     `json:"realm_type"`
 | 
			
		||||
	AccountID   uint          `json:"account_id"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -60,14 +60,14 @@ func createRealm(c *fiber.Ctx) error {
 | 
			
		||||
	var data struct {
 | 
			
		||||
		Name        string `json:"name" validate:"required"`
 | 
			
		||||
		Description string `json:"description"`
 | 
			
		||||
		IsPublic    bool   `json:"is_public"`
 | 
			
		||||
		RealmType   int    `json:"realm_type"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := BindAndValidate(c, &data); err != nil {
 | 
			
		||||
		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 {
 | 
			
		||||
		return fiber.NewError(fiber.StatusBadRequest, err.Error())
 | 
			
		||||
	}
 | 
			
		||||
@@ -150,7 +150,7 @@ func editRealm(c *fiber.Ctx) error {
 | 
			
		||||
	var data struct {
 | 
			
		||||
		Name        string `json:"name" validate:"required"`
 | 
			
		||||
		Description string `json:"description"`
 | 
			
		||||
		IsPublic    bool   `json:"is_public"`
 | 
			
		||||
		RealmType   int    `json:"realm_type"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := BindAndValidate(c, &data); err != nil {
 | 
			
		||||
@@ -165,7 +165,7 @@ func editRealm(c *fiber.Ctx) 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 {
 | 
			
		||||
		return fiber.NewError(fiber.StatusBadRequest, err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -274,7 +274,7 @@ func NewPost[T models.PostInterface](item T) (T, error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if item.GetRealm() != nil {
 | 
			
		||||
		if !item.GetRealm().IsPublic {
 | 
			
		||||
		if item.GetRealm().RealmType != models.RealmTypePublic {
 | 
			
		||||
			var member models.RealmMember
 | 
			
		||||
			if err := database.C.Where(&models.RealmMember{
 | 
			
		||||
				RealmID:   item.GetRealm().ID,
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@ func ListRealmIsAvailable(user models.Account) ([]models.Realm, error) {
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	if err := database.C.Where(&models.Realm{
 | 
			
		||||
		IsPublic: true,
 | 
			
		||||
		RealmType: models.RealmTypePublic,
 | 
			
		||||
	}).Or("id IN ?", idx).Find(&realms).Error; err != nil {
 | 
			
		||||
		return realms, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -46,12 +46,12 @@ func ListRealmIsAvailable(user models.Account) ([]models.Realm, error) {
 | 
			
		||||
	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{
 | 
			
		||||
		Name:        name,
 | 
			
		||||
		Description: description,
 | 
			
		||||
		AccountID:   user.ID,
 | 
			
		||||
		IsPublic:    isPublic,
 | 
			
		||||
		RealmType:   realmType,
 | 
			
		||||
		Members: []models.RealmMember{
 | 
			
		||||
			{AccountID: user.ID},
 | 
			
		||||
		},
 | 
			
		||||
@@ -86,10 +86,10 @@ func KickRealmMember(user models.Account, target models.Realm) 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.Description = description
 | 
			
		||||
	realm.IsPublic = isPublic
 | 
			
		||||
	realm.RealmType = realmType
 | 
			
		||||
 | 
			
		||||
	err := database.C.Save(&realm).Error
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
<html lang="en">
 | 
			
		||||
  <head>
 | 
			
		||||
    <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">
 | 
			
		||||
    <title>Solarplaza</title>
 | 
			
		||||
  </head>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								pkg/views/public/favicon.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											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  | 
							
								
								
									
										116
									
								
								pkg/views/src/components/realms/RealmList.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								pkg/views/src/components/realms/RealmList.vue
									
									
									
									
									
										Normal 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>
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <v-navigation-drawer v-model="drawerOpen" color="grey-lighten-5" floating>
 | 
			
		||||
    <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">
 | 
			
		||||
          <template #prepend>
 | 
			
		||||
            <v-avatar icon="mdi-account-circle" :image="id.userinfo.data?.avatar" />
 | 
			
		||||
@@ -27,7 +27,9 @@
 | 
			
		||||
        </v-list-item>
 | 
			
		||||
      </v-list>
 | 
			
		||||
 | 
			
		||||
      <v-list density="compact" class="flex-grow-1" nav> </v-list>
 | 
			
		||||
      <div class="flex-grow-1">
 | 
			
		||||
        <realm-list />
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div>
 | 
			
		||||
        <v-alert type="info" variant="tonal" class="text-sm">
 | 
			
		||||
@@ -95,6 +97,7 @@ import { useEditor } from "@/stores/editor"
 | 
			
		||||
import { useUserinfo } from "@/stores/userinfo"
 | 
			
		||||
import { useWellKnown } from "@/stores/wellKnown"
 | 
			
		||||
import PostAction from "@/components/publish/PostAction.vue"
 | 
			
		||||
import RealmList from "@/components/realms/RealmList.vue";
 | 
			
		||||
 | 
			
		||||
const id = useUserinfo()
 | 
			
		||||
const editor = useEditor()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user