✨ More places will show menu
This commit is contained in:
		
							
								
								
									
										8
									
								
								.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,8 +0,0 @@
 | 
				
			|||||||
# Default ignored files
 | 
					 | 
				
			||||||
/shelf/
 | 
					 | 
				
			||||||
/workspace.xml
 | 
					 | 
				
			||||||
# Editor-based HTTP Client requests
 | 
					 | 
				
			||||||
/httpRequests/
 | 
					 | 
				
			||||||
# Datasource local storage ignored files
 | 
					 | 
				
			||||||
/dataSources/
 | 
					 | 
				
			||||||
/dataSources.local.xml
 | 
					 | 
				
			||||||
							
								
								
									
										9
									
								
								.idea/Interactive.iml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										9
									
								
								.idea/Interactive.iml
									
									
									
										generated
									
									
									
								
							@@ -1,9 +0,0 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					 | 
				
			||||||
<module type="WEB_MODULE" version="4">
 | 
					 | 
				
			||||||
  <component name="Go" enabled="true" />
 | 
					 | 
				
			||||||
  <component name="NewModuleRootManager">
 | 
					 | 
				
			||||||
    <content url="file://$MODULE_DIR$" />
 | 
					 | 
				
			||||||
    <orderEntry type="inheritedJdk" />
 | 
					 | 
				
			||||||
    <orderEntry type="sourceFolder" forTests="false" />
 | 
					 | 
				
			||||||
  </component>
 | 
					 | 
				
			||||||
</module>
 | 
					 | 
				
			||||||
							
								
								
									
										53
									
								
								.idea/codeStyles/Project.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										53
									
								
								.idea/codeStyles/Project.xml
									
									
									
										generated
									
									
									
								
							@@ -1,53 +0,0 @@
 | 
				
			|||||||
<component name="ProjectCodeStyleConfiguration">
 | 
					 | 
				
			||||||
  <code_scheme name="Project" version="173">
 | 
					 | 
				
			||||||
    <HTMLCodeStyleSettings>
 | 
					 | 
				
			||||||
      <option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
 | 
					 | 
				
			||||||
    </HTMLCodeStyleSettings>
 | 
					 | 
				
			||||||
    <JSCodeStyleSettings version="0">
 | 
					 | 
				
			||||||
      <option name="FORCE_SEMICOLON_STYLE" value="true" />
 | 
					 | 
				
			||||||
      <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
 | 
					 | 
				
			||||||
      <option name="FORCE_QUOTE_STYlE" value="true" />
 | 
					 | 
				
			||||||
      <option name="ENFORCE_TRAILING_COMMA" value="Remove" />
 | 
					 | 
				
			||||||
      <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
 | 
					 | 
				
			||||||
      <option name="SPACES_WITHIN_IMPORTS" value="true" />
 | 
					 | 
				
			||||||
    </JSCodeStyleSettings>
 | 
					 | 
				
			||||||
    <TypeScriptCodeStyleSettings version="0">
 | 
					 | 
				
			||||||
      <option name="FORCE_SEMICOLON_STYLE" value="true" />
 | 
					 | 
				
			||||||
      <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
 | 
					 | 
				
			||||||
      <option name="FORCE_QUOTE_STYlE" value="true" />
 | 
					 | 
				
			||||||
      <option name="ENFORCE_TRAILING_COMMA" value="Remove" />
 | 
					 | 
				
			||||||
      <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
 | 
					 | 
				
			||||||
      <option name="SPACES_WITHIN_IMPORTS" value="true" />
 | 
					 | 
				
			||||||
    </TypeScriptCodeStyleSettings>
 | 
					 | 
				
			||||||
    <codeStyleSettings language="HTML">
 | 
					 | 
				
			||||||
      <option name="SOFT_MARGINS" value="120" />
 | 
					 | 
				
			||||||
      <indentOptions>
 | 
					 | 
				
			||||||
        <option name="INDENT_SIZE" value="2" />
 | 
					 | 
				
			||||||
        <option name="CONTINUATION_INDENT_SIZE" value="2" />
 | 
					 | 
				
			||||||
        <option name="TAB_SIZE" value="2" />
 | 
					 | 
				
			||||||
      </indentOptions>
 | 
					 | 
				
			||||||
    </codeStyleSettings>
 | 
					 | 
				
			||||||
    <codeStyleSettings language="JavaScript">
 | 
					 | 
				
			||||||
      <option name="SOFT_MARGINS" value="120" />
 | 
					 | 
				
			||||||
      <indentOptions>
 | 
					 | 
				
			||||||
        <option name="INDENT_SIZE" value="2" />
 | 
					 | 
				
			||||||
        <option name="CONTINUATION_INDENT_SIZE" value="2" />
 | 
					 | 
				
			||||||
        <option name="TAB_SIZE" value="2" />
 | 
					 | 
				
			||||||
      </indentOptions>
 | 
					 | 
				
			||||||
    </codeStyleSettings>
 | 
					 | 
				
			||||||
    <codeStyleSettings language="TypeScript">
 | 
					 | 
				
			||||||
      <option name="SOFT_MARGINS" value="120" />
 | 
					 | 
				
			||||||
      <indentOptions>
 | 
					 | 
				
			||||||
        <option name="INDENT_SIZE" value="2" />
 | 
					 | 
				
			||||||
        <option name="CONTINUATION_INDENT_SIZE" value="2" />
 | 
					 | 
				
			||||||
        <option name="TAB_SIZE" value="2" />
 | 
					 | 
				
			||||||
      </indentOptions>
 | 
					 | 
				
			||||||
    </codeStyleSettings>
 | 
					 | 
				
			||||||
    <codeStyleSettings language="Vue">
 | 
					 | 
				
			||||||
      <option name="SOFT_MARGINS" value="120" />
 | 
					 | 
				
			||||||
      <indentOptions>
 | 
					 | 
				
			||||||
        <option name="CONTINUATION_INDENT_SIZE" value="2" />
 | 
					 | 
				
			||||||
      </indentOptions>
 | 
					 | 
				
			||||||
    </codeStyleSettings>
 | 
					 | 
				
			||||||
  </code_scheme>
 | 
					 | 
				
			||||||
</component>
 | 
					 | 
				
			||||||
							
								
								
									
										5
									
								
								.idea/codeStyles/codeStyleConfig.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								.idea/codeStyles/codeStyleConfig.xml
									
									
									
										generated
									
									
									
								
							@@ -1,5 +0,0 @@
 | 
				
			|||||||
<component name="ProjectCodeStyleConfiguration">
 | 
					 | 
				
			||||||
  <state>
 | 
					 | 
				
			||||||
    <option name="USE_PER_PROJECT_SETTINGS" value="true" />
 | 
					 | 
				
			||||||
  </state>
 | 
					 | 
				
			||||||
</component>
 | 
					 | 
				
			||||||
							
								
								
									
										12
									
								
								.idea/dataSources.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										12
									
								
								.idea/dataSources.xml
									
									
									
										generated
									
									
									
								
							@@ -1,12 +0,0 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					 | 
				
			||||||
<project version="4">
 | 
					 | 
				
			||||||
  <component name="DataSourceManagerImpl" format="xml" multifile-model="true">
 | 
					 | 
				
			||||||
    <data-source source="LOCAL" name="hy_interactive@localhost" uuid="2e2101b2-4037-47ee-88ed-456dc2cb4423">
 | 
					 | 
				
			||||||
      <driver-ref>postgresql</driver-ref>
 | 
					 | 
				
			||||||
      <synchronize>true</synchronize>
 | 
					 | 
				
			||||||
      <jdbc-driver>org.postgresql.Driver</jdbc-driver>
 | 
					 | 
				
			||||||
      <jdbc-url>jdbc:postgresql://localhost:5432/hy_interactive</jdbc-url>
 | 
					 | 
				
			||||||
      <working-dir>$ProjectFileDir$</working-dir>
 | 
					 | 
				
			||||||
    </data-source>
 | 
					 | 
				
			||||||
  </component>
 | 
					 | 
				
			||||||
</project>
 | 
					 | 
				
			||||||
							
								
								
									
										11
									
								
								.idea/inspectionProfiles/Project_Default.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										11
									
								
								.idea/inspectionProfiles/Project_Default.xml
									
									
									
										generated
									
									
									
								
							@@ -1,11 +0,0 @@
 | 
				
			|||||||
<component name="InspectionProjectProfileManager">
 | 
					 | 
				
			||||||
  <profile version="1.0">
 | 
					 | 
				
			||||||
    <option name="myName" value="Project Default" />
 | 
					 | 
				
			||||||
    <inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
 | 
					 | 
				
			||||||
      <Languages>
 | 
					 | 
				
			||||||
        <language minSize="54" name="TypeScript" />
 | 
					 | 
				
			||||||
      </Languages>
 | 
					 | 
				
			||||||
    </inspection_tool>
 | 
					 | 
				
			||||||
    <inspection_tool class="SqlDialectInspection" enabled="false" level="WARNING" enabled_by_default="false" />
 | 
					 | 
				
			||||||
  </profile>
 | 
					 | 
				
			||||||
</component>
 | 
					 | 
				
			||||||
							
								
								
									
										8
									
								
								.idea/modules.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								.idea/modules.xml
									
									
									
										generated
									
									
									
								
							@@ -1,8 +0,0 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					 | 
				
			||||||
<project version="4">
 | 
					 | 
				
			||||||
  <component name="ProjectModuleManager">
 | 
					 | 
				
			||||||
    <modules>
 | 
					 | 
				
			||||||
      <module fileurl="file://$PROJECT_DIR$/.idea/Interactive.iml" filepath="$PROJECT_DIR$/.idea/Interactive.iml" />
 | 
					 | 
				
			||||||
    </modules>
 | 
					 | 
				
			||||||
  </component>
 | 
					 | 
				
			||||||
</project>
 | 
					 | 
				
			||||||
							
								
								
									
										7
									
								
								.idea/sqldialects.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										7
									
								
								.idea/sqldialects.xml
									
									
									
										generated
									
									
									
								
							@@ -1,7 +0,0 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					 | 
				
			||||||
<project version="4">
 | 
					 | 
				
			||||||
  <component name="SqlDialectMappings">
 | 
					 | 
				
			||||||
    <file url="file://$PROJECT_DIR$/pkg/server/moments_api.go" dialect="PostgreSQL" />
 | 
					 | 
				
			||||||
    <file url="file://$APPLICATION_CONFIG_DIR$/consoles/db/2e2101b2-4037-47ee-88ed-456dc2cb4423/console.sql" dialect="PostgreSQL" />
 | 
					 | 
				
			||||||
  </component>
 | 
					 | 
				
			||||||
</project>
 | 
					 | 
				
			||||||
							
								
								
									
										6
									
								
								.idea/vcs.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								.idea/vcs.xml
									
									
									
										generated
									
									
									
								
							@@ -1,6 +0,0 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					 | 
				
			||||||
<project version="4">
 | 
					 | 
				
			||||||
  <component name="VcsDirectoryMappings">
 | 
					 | 
				
			||||||
    <mapping directory="$PROJECT_DIR$" vcs="Git" />
 | 
					 | 
				
			||||||
  </component>
 | 
					 | 
				
			||||||
</project>
 | 
					 | 
				
			||||||
@@ -11,5 +11,9 @@ module.exports = {
 | 
				
			|||||||
  ],
 | 
					  ],
 | 
				
			||||||
  parserOptions: {
 | 
					  parserOptions: {
 | 
				
			||||||
    ecmaVersion: 'latest'
 | 
					    ecmaVersion: 'latest'
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  rules: {
 | 
				
			||||||
 | 
					    'vue/multi-word-component-names': 'off',
 | 
				
			||||||
 | 
					    'vue/valid-v-for': 'off'
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										43
									
								
								pkg/views/src/components/posts/PostAction.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								pkg/views/src/components/posts/PostAction.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <v-menu>
 | 
				
			||||||
 | 
					    <template #activator="{ props }">
 | 
				
			||||||
 | 
					      <v-btn v-bind="props" icon="mdi-dots-vertical" variant="text" size="x-small" />
 | 
				
			||||||
 | 
					    </template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <v-list density="compact" lines="one">
 | 
				
			||||||
 | 
					      <v-list-item disabled append-icon="mdi-flag" title="Report" />
 | 
				
			||||||
 | 
					      <v-list-item v-if="isOwned" append-icon="mdi-pencil" title="Edit" @click="editPost" />
 | 
				
			||||||
 | 
					      <v-list-item v-if="isOwned" append-icon="mdi-delete" title="Delete" @click="deletePost" />
 | 
				
			||||||
 | 
					    </v-list>
 | 
				
			||||||
 | 
					  </v-menu>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					import { useEditor } from "@/stores/editor"
 | 
				
			||||||
 | 
					import { useUserinfo } from "@/stores/userinfo";
 | 
				
			||||||
 | 
					import { computed } from "vue"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const id = useUserinfo()
 | 
				
			||||||
 | 
					const editor = useEditor()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps<{ item: any }>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const isOwned = computed(() => props.item?.author_id === id.userinfo.data.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function editPost() {
 | 
				
			||||||
 | 
					  editor.related.edit_to = props.item
 | 
				
			||||||
 | 
					  if (editor.show.hasOwnProperty(props.item.model_type)) {
 | 
				
			||||||
 | 
					    // @ts-ignore
 | 
				
			||||||
 | 
					    editor.show[props.item.model_type] = true
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (props.item.model_type === "comment") {
 | 
				
			||||||
 | 
					    editor.related.comment_to = props.item
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function deletePost() {
 | 
				
			||||||
 | 
					  editor.related.delete_to = JSON.parse(JSON.stringify(props.item))
 | 
				
			||||||
 | 
					  editor.related.delete_to.model_type = props.item.model_type + "s"
 | 
				
			||||||
 | 
					  editor.show.delete = true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
@@ -9,7 +9,7 @@
 | 
				
			|||||||
      />
 | 
					      />
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div class="flex-grow-1 relative">
 | 
					    <div class="flex-grow-1">
 | 
				
			||||||
      <div class="font-bold">{{ props.item?.author.nick }}</div>
 | 
					      <div class="font-bold">{{ props.item?.author.nick }}</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div v-if="props.item?.model_type === 'article'" class="text-xs text-grey-darken-4 mb-2">
 | 
					      <div v-if="props.item?.model_type === 'article'" class="text-xs text-grey-darken-4 mb-2">
 | 
				
			||||||
@@ -36,66 +36,35 @@
 | 
				
			|||||||
      <div class="mt-1 text-xs opacity-80 flex gap-2 items-center">
 | 
					      <div class="mt-1 text-xs opacity-80 flex gap-2 items-center">
 | 
				
			||||||
        <span>Posted at {{ new Date(props.item?.created_at).toLocaleString() }}</span>
 | 
					        <span>Posted at {{ new Date(props.item?.created_at).toLocaleString() }}</span>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <v-menu>
 | 
					    <div>
 | 
				
			||||||
        <template #activator="{ props }">
 | 
					      <post-action :item="props.item" />
 | 
				
			||||||
          <div class="absolute right-0 top-0">
 | 
					 | 
				
			||||||
            <v-btn v-bind="props" icon="mdi-dots-vertical" variant="text" size="x-small" />
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <v-list density="compact" lines="one">
 | 
					 | 
				
			||||||
          <v-list-item disabled append-icon="mdi-flag" title="Report" />
 | 
					 | 
				
			||||||
          <v-list-item v-if="isOwned" append-icon="mdi-pencil" title="Edit" @click="editPost" />
 | 
					 | 
				
			||||||
          <v-list-item v-if="isOwned" append-icon="mdi-delete" title="Delete" @click="deletePost" />
 | 
					 | 
				
			||||||
        </v-list>
 | 
					 | 
				
			||||||
      </v-menu>
 | 
					 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { computed, type Component } from "vue"
 | 
					import { type Component } from "vue"
 | 
				
			||||||
import { useUserinfo } from "@/stores/userinfo"
 | 
					import { useUserinfo } from "@/stores/userinfo"
 | 
				
			||||||
import { useEditor } from "@/stores/editor"
 | 
					 | 
				
			||||||
import ArticleContent from "@/components/posts/ArticleContent.vue"
 | 
					import ArticleContent from "@/components/posts/ArticleContent.vue"
 | 
				
			||||||
import MomentContent from "@/components/posts/MomentContent.vue"
 | 
					import MomentContent from "@/components/posts/MomentContent.vue"
 | 
				
			||||||
import CommentContent from "@/components/posts/CommentContent.vue"
 | 
					import CommentContent from "@/components/posts/CommentContent.vue"
 | 
				
			||||||
import PostAttachment from "./PostAttachment.vue"
 | 
					import PostAttachment from "@/components/posts/PostAttachment.vue"
 | 
				
			||||||
import PostReaction from "@/components/posts/PostReaction.vue"
 | 
					import PostReaction from "@/components/posts/PostReaction.vue"
 | 
				
			||||||
 | 
					import PostAction from "@/components/posts/PostAction.vue"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const id = useUserinfo()
 | 
					const id = useUserinfo()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = defineProps<{ item: any; brief?: boolean }>()
 | 
					const props = defineProps<{ item: any; brief?: boolean }>()
 | 
				
			||||||
const emits = defineEmits(["update:item"])
 | 
					const emits = defineEmits(["update:item"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const editor = useEditor()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const renderer: { [id: string]: Component } = {
 | 
					const renderer: { [id: string]: Component } = {
 | 
				
			||||||
  article: ArticleContent,
 | 
					  article: ArticleContent,
 | 
				
			||||||
  moment: MomentContent,
 | 
					  moment: MomentContent,
 | 
				
			||||||
  comment: CommentContent
 | 
					  comment: CommentContent
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const isOwned = computed(() => props.item?.author_id === id.userinfo.data.id)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function editPost() {
 | 
					 | 
				
			||||||
  editor.related.edit_to = props.item
 | 
					 | 
				
			||||||
  if (editor.show.hasOwnProperty(props.item.model_type)) {
 | 
					 | 
				
			||||||
    // @ts-ignore
 | 
					 | 
				
			||||||
    editor.show[props.item.model_type] = true
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (props.item.model_type === "comment") {
 | 
					 | 
				
			||||||
    editor.related.comment_to = props.item
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function deletePost() {
 | 
					 | 
				
			||||||
  editor.related.delete_to = JSON.parse(JSON.stringify(props.item))
 | 
					 | 
				
			||||||
  editor.related.delete_to.model_type = props.item.model_type + "s"
 | 
					 | 
				
			||||||
  editor.show.delete = true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function updateReactions(symbol: string, num: number) {
 | 
					function updateReactions(symbol: string, num: number) {
 | 
				
			||||||
  const item = JSON.parse(JSON.stringify(props.item))
 | 
					  const item = JSON.parse(JSON.stringify(props.item))
 | 
				
			||||||
  if (item.reaction_list == null) {
 | 
					  if (item.reaction_list == null) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										71
									
								
								pkg/views/src/components/realms/RealmEditor.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								pkg/views/src/components/realms/RealmEditor.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <v-dialog :model-value="props.show" @update:model-value="(val) => emits('update:show', val)" class="max-w-[540px]">
 | 
				
			||||||
 | 
					    <v-card title="Organize a realm" prepend-icon="mdi-account-multiple" :loading="loading">
 | 
				
			||||||
 | 
					      <v-form @submit.prevent="submit">
 | 
				
			||||||
 | 
					        <v-card-text>
 | 
				
			||||||
 | 
					          <v-text-field label="Name" variant="outlined" density="comfortable" v-model="data.name" />
 | 
				
			||||||
 | 
					          <v-textarea label="Description" variant="outlined" density="comfortable" v-model="data.description" />
 | 
				
			||||||
 | 
					          <v-select
 | 
				
			||||||
 | 
					            label="Realm type"
 | 
				
			||||||
 | 
					            item-title="label"
 | 
				
			||||||
 | 
					            item-value="value"
 | 
				
			||||||
 | 
					            variant="outlined"
 | 
				
			||||||
 | 
					            density="comfortable"
 | 
				
			||||||
 | 
					            :items="realmTypeOptions"
 | 
				
			||||||
 | 
					            v-model="data.realm_type"
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					        </v-card-text>
 | 
				
			||||||
 | 
					        <v-card-actions>
 | 
				
			||||||
 | 
					          <v-spacer></v-spacer>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <v-btn type="reset" color="grey-darken-3" @click="emits('update:show', false)">Cancel</v-btn>
 | 
				
			||||||
 | 
					          <v-btn type="submit" :disabled="loading">Save</v-btn>
 | 
				
			||||||
 | 
					        </v-card-actions>
 | 
				
			||||||
 | 
					      </v-form>
 | 
				
			||||||
 | 
					    </v-card>
 | 
				
			||||||
 | 
					  </v-dialog>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					import { ref } from "vue"
 | 
				
			||||||
 | 
					import { getAtk } from "@/stores/userinfo"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps<{ show: boolean }>()
 | 
				
			||||||
 | 
					const emits = defineEmits(["update:show", "relist"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const realmTypeOptions = [
 | 
				
			||||||
 | 
					  { label: "Public Realm", value: 0 },
 | 
				
			||||||
 | 
					  { label: "Restricted Realm", value: 1 },
 | 
				
			||||||
 | 
					  { label: "Private Realm", value: 2 }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const error = ref<null | string>(null)
 | 
				
			||||||
 | 
					const loading = ref(false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const data = ref({
 | 
				
			||||||
 | 
					  name: "",
 | 
				
			||||||
 | 
					  description: "",
 | 
				
			||||||
 | 
					  realm_type: 0
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function submit(evt: SubmitEvent) {
 | 
				
			||||||
 | 
					  const form = evt.target as HTMLFormElement
 | 
				
			||||||
 | 
					  const payload = data.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 {
 | 
				
			||||||
 | 
					    emits("relist")
 | 
				
			||||||
 | 
					    form.reset()
 | 
				
			||||||
 | 
					    emits("update:show", false)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  loading.value = false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
@@ -2,11 +2,7 @@
 | 
				
			|||||||
  <v-list density="comfortable">
 | 
					  <v-list density="comfortable">
 | 
				
			||||||
    <v-list-subheader>
 | 
					    <v-list-subheader>
 | 
				
			||||||
      Realms
 | 
					      Realms
 | 
				
			||||||
      <v-badge
 | 
					      <v-badge color="warning" content="Alpha" inline />
 | 
				
			||||||
        color="warning"
 | 
					 | 
				
			||||||
        content="Alpha"
 | 
					 | 
				
			||||||
        inline
 | 
					 | 
				
			||||||
      />
 | 
					 | 
				
			||||||
    </v-list-subheader>
 | 
					    </v-list-subheader>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <v-list-item
 | 
					    <v-list-item
 | 
				
			||||||
@@ -27,101 +23,35 @@
 | 
				
			|||||||
    />
 | 
					    />
 | 
				
			||||||
  </v-list>
 | 
					  </v-list>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <v-dialog v-model="creating" class="max-w-[540px]">
 | 
					  <realm-editor v-model:show="creating" @relist="list" />
 | 
				
			||||||
    <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 -->
 | 
					  <!-- @vue-ignore -->
 | 
				
			||||||
  <v-snackbar v-model="error" :timeout="5000">Something went wrong... {{ error }}</v-snackbar>
 | 
					  <v-snackbar v-model="error" :timeout="5000">Something went wrong... {{ error }}</v-snackbar>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { computed, ref } from "vue";
 | 
					import { computed, ref } from "vue"
 | 
				
			||||||
import { getAtk, useUserinfo } from "@/stores/userinfo";
 | 
					import { useUserinfo } from "@/stores/userinfo"
 | 
				
			||||||
import { useEditor } from "@/stores/editor";
 | 
					import { useEditor } from "@/stores/editor"
 | 
				
			||||||
 | 
					import RealmEditor from "@/components/realms/RealmEditor.vue"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const id = useUserinfo();
 | 
					const id = useUserinfo()
 | 
				
			||||||
const editor = useEditor();
 | 
					const editor = useEditor()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const realms = computed(() => editor.availableRealms);
 | 
					const realms = computed(() => editor.availableRealms)
 | 
				
			||||||
const requestData = ref({
 | 
					 | 
				
			||||||
  name: "",
 | 
					 | 
				
			||||||
  description: "",
 | 
					 | 
				
			||||||
  realm_type: 0
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const realmTypeOptions = [
 | 
					const creating = ref(false)
 | 
				
			||||||
  { 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 error = ref<string | null>(null);
 | 
					 | 
				
			||||||
const reverting = ref(false);
 | 
					 | 
				
			||||||
const loading = ref(false);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function list() {
 | 
					async function list() {
 | 
				
			||||||
  reverting.value = true;
 | 
					  reverting.value = true
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    await editor.listRealms();
 | 
					    await editor.listRealms()
 | 
				
			||||||
  } catch (err) {
 | 
					  } catch (err) {
 | 
				
			||||||
    error.value = (err as Error).message;
 | 
					    error.value = (err as Error).message
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  reverting.value = false;
 | 
					  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;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,16 +1,16 @@
 | 
				
			|||||||
import { defineStore } from "pinia";
 | 
					import { defineStore } from "pinia"
 | 
				
			||||||
import { reactive, ref } from "vue";
 | 
					import { reactive, ref } from "vue"
 | 
				
			||||||
import { checkLoggedIn, getAtk } from "@/stores/userinfo";
 | 
					import { checkLoggedIn, getAtk } from "@/stores/userinfo"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const useEditor = defineStore("editor", () => {
 | 
					export const useEditor = defineStore("editor", () => {
 | 
				
			||||||
  const done = ref(false);
 | 
					  const done = ref(false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const show = reactive({
 | 
					  const show = reactive({
 | 
				
			||||||
    moment: false,
 | 
					    moment: false,
 | 
				
			||||||
    article: false,
 | 
					    article: false,
 | 
				
			||||||
    comment: false,
 | 
					    comment: false,
 | 
				
			||||||
    delete: false
 | 
					    delete: false
 | 
				
			||||||
  });
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const related = reactive<{
 | 
					  const related = reactive<{
 | 
				
			||||||
    edit_to: any
 | 
					    edit_to: any
 | 
				
			||||||
@@ -24,24 +24,24 @@ export const useEditor = defineStore("editor", () => {
 | 
				
			|||||||
    reply_to: null,
 | 
					    reply_to: null,
 | 
				
			||||||
    repost_to: null,
 | 
					    repost_to: null,
 | 
				
			||||||
    delete_to: null
 | 
					    delete_to: null
 | 
				
			||||||
  });
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const availableRealms = ref<any[]>([]);
 | 
					  const availableRealms = ref<any[]>([])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async function listRealms() {
 | 
					  async function listRealms() {
 | 
				
			||||||
    if (!checkLoggedIn()) return;
 | 
					    if (!checkLoggedIn()) return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const res = await fetch("/api/realms/me/available", {
 | 
					    const res = await fetch("/api/realms/me/available", {
 | 
				
			||||||
      headers: { Authorization: `Bearer ${getAtk()}` }
 | 
					      headers: { Authorization: `Bearer ${getAtk()}` }
 | 
				
			||||||
    });
 | 
					    })
 | 
				
			||||||
    if (res.status !== 200) {
 | 
					    if (res.status !== 200) {
 | 
				
			||||||
      throw new Error(await res.text());
 | 
					      throw new Error(await res.text())
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      availableRealms.value = await res.json();
 | 
					      availableRealms.value = await res.json()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  listRealms().then(() => console.log("[STARTUP HOOK] Fetch available realm successes."));
 | 
					  listRealms().then(() => console.log("[STARTUP HOOK] Fetch available realm successes."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return { show, related, availableRealms, listRealms, done };
 | 
					  return { show, related, availableRealms, listRealms, done }
 | 
				
			||||||
});
 | 
					})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,9 +4,15 @@
 | 
				
			|||||||
      <v-card :loading="loading">
 | 
					      <v-card :loading="loading">
 | 
				
			||||||
        <article>
 | 
					        <article>
 | 
				
			||||||
          <v-card-text>
 | 
					          <v-card-text>
 | 
				
			||||||
            <div class="px-3">
 | 
					            <div class="flex justify-between px-3">
 | 
				
			||||||
              <h1 class="text-lg font-medium">{{ post?.title }}</h1>
 | 
					              <div>
 | 
				
			||||||
              <p class="text-sm">{{ post?.description }}</p>
 | 
					                <h1 class="text-lg font-medium">{{ post?.title }}</h1>
 | 
				
			||||||
 | 
					                <p class="text-sm">{{ post?.description }}</p>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              <div>
 | 
				
			||||||
 | 
					                <post-action :item="post" />
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <v-divider class="my-5 mx-[-16px] border-opacity-50" />
 | 
					            <v-divider class="my-5 mx-[-16px] border-opacity-50" />
 | 
				
			||||||
@@ -56,11 +62,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { ref } from "vue"
 | 
					import { ref } from "vue"
 | 
				
			||||||
 | 
					import { useRoute } from "vue-router"
 | 
				
			||||||
import { request } from "@/scripts/request"
 | 
					import { request } from "@/scripts/request"
 | 
				
			||||||
import ArticleContent from "@/components/posts/ArticleContent.vue"
 | 
					import ArticleContent from "@/components/posts/ArticleContent.vue"
 | 
				
			||||||
import PostReaction from "@/components/posts/PostReaction.vue"
 | 
					import PostReaction from "@/components/posts/PostReaction.vue"
 | 
				
			||||||
 | 
					import PostAction from "@/components/posts/PostAction.vue"
 | 
				
			||||||
import CommentList from "@/components/comments/CommentList.vue"
 | 
					import CommentList from "@/components/comments/CommentList.vue"
 | 
				
			||||||
import { useRoute } from "vue-router"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const loading = ref(false)
 | 
					const loading = ref(false)
 | 
				
			||||||
const error = ref<string | null>(null)
 | 
					const error = ref<string | null>(null)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,19 +4,25 @@
 | 
				
			|||||||
      <v-card :loading="loading">
 | 
					      <v-card :loading="loading">
 | 
				
			||||||
        <article>
 | 
					        <article>
 | 
				
			||||||
          <v-card-text>
 | 
					          <v-card-text>
 | 
				
			||||||
            <div class="flex gap-2">
 | 
					            <div class="flex justify-between px-3">
 | 
				
			||||||
              <v-avatar
 | 
					              <div class="flex gap-1">
 | 
				
			||||||
                color="grey-lighten-2"
 | 
					                <v-avatar
 | 
				
			||||||
                icon="mdi-account-circle"
 | 
					                  color="grey-lighten-2"
 | 
				
			||||||
                class="rounded-card"
 | 
					                  icon="mdi-account-circle"
 | 
				
			||||||
                :image="post?.author.avatar"
 | 
					                  class="rounded-card me-2"
 | 
				
			||||||
              />
 | 
					                  :image="post?.author.avatar"
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <div>
 | 
				
			||||||
 | 
					                  <p class="font-bold">{{ post?.author.nick }}</p>
 | 
				
			||||||
 | 
					                  <p class="opacity-80">
 | 
				
			||||||
 | 
					                    {{ post?.author.description ? post?.author.description : "No description yet." }}
 | 
				
			||||||
 | 
					                  </p>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              <div>
 | 
					              <div>
 | 
				
			||||||
                <p class="font-bold">{{ post?.author.nick }}</p>
 | 
					                <post-action :item="post" />
 | 
				
			||||||
                <p class="opacity-80">
 | 
					 | 
				
			||||||
                  {{ post?.author.description ? post?.author.description : "No description yet." }}
 | 
					 | 
				
			||||||
                </p>
 | 
					 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -69,6 +75,7 @@ import MomentContent from "@/components/posts/MomentContent.vue"
 | 
				
			|||||||
import PostReaction from "@/components/posts/PostReaction.vue"
 | 
					import PostReaction from "@/components/posts/PostReaction.vue"
 | 
				
			||||||
import CommentList from "@/components/comments/CommentList.vue"
 | 
					import CommentList from "@/components/comments/CommentList.vue"
 | 
				
			||||||
import PostAttachment from "@/components/posts/PostAttachment.vue"
 | 
					import PostAttachment from "@/components/posts/PostAttachment.vue"
 | 
				
			||||||
 | 
					import PostAction from "@/components/posts/PostAction.vue"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const loading = ref(false)
 | 
					const loading = ref(false)
 | 
				
			||||||
const error = ref<string | null>(null)
 | 
					const error = ref<string | null>(null)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user