✨ 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