mirror of
https://github.com/HangarMC/Hangar.git
synced 2024-12-21 06:51:19 +08:00
implement project flagging
This commit is contained in:
parent
97a49e3886
commit
ed404fc6bf
68
frontend-new/src/components/modals/FlagModal.vue
Normal file
68
frontend-new/src/components/modals/FlagModal.vue
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import Button from "~/components/design/Button.vue";
|
||||||
|
import Modal from "~/components/modals/Modal.vue";
|
||||||
|
import Tooltip from "~/components/design/Tooltip.vue";
|
||||||
|
import { useContext } from "vite-ssr/vue";
|
||||||
|
import { Project } from "hangar-api";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import InputRadio from "~/components/ui/InputRadio.vue";
|
||||||
|
import { useBackendDataStore } from "~/store/backendData";
|
||||||
|
import { ref } from "vue";
|
||||||
|
import InputTextarea from "~/components/ui/InputTextarea.vue";
|
||||||
|
import { required } from "~/composables/useValidationHelpers";
|
||||||
|
import { useInternalApi } from "~/composables/useApi";
|
||||||
|
import { HangarProject } from "hangar-internal";
|
||||||
|
import { handleRequestError } from "~/composables/useErrorHandling";
|
||||||
|
import { AxiosError } from "axios";
|
||||||
|
import { useNotificationStore } from "~/store/notification";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
project: HangarProject;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const i18n = useI18n();
|
||||||
|
const ctx = useContext();
|
||||||
|
const router = useRouter();
|
||||||
|
const backendData = useBackendDataStore();
|
||||||
|
|
||||||
|
const flagReason = ref<string>();
|
||||||
|
const flagComment = ref<string>();
|
||||||
|
|
||||||
|
async function submit(close: () => void) {
|
||||||
|
try {
|
||||||
|
await useInternalApi("flags/", true, "POST", {
|
||||||
|
projectId: props.project.id,
|
||||||
|
reason: flagReason.value,
|
||||||
|
comment: flagComment.value,
|
||||||
|
});
|
||||||
|
close();
|
||||||
|
useNotificationStore().success(i18n.t("project.flag.flagSend"));
|
||||||
|
await router.go(0);
|
||||||
|
} catch (e) {
|
||||||
|
handleRequestError(e as AxiosError, ctx, i18n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Modal :title="i18n.t('project.flag.flagProject', [project.name])">
|
||||||
|
<template #default="{ on }">
|
||||||
|
<InputRadio v-for="(reason, index) in backendData.flagReasons" :key="index" v-model="flagReason" :label="i18n.t(reason.title)" :value="reason.type" />
|
||||||
|
<div class="py-2"></div>
|
||||||
|
<InputTextarea v-model.trim="flagComment" rows="3" :rules="[required()]" :label="i18n.t('general.comment')" />
|
||||||
|
|
||||||
|
<Button button-type="secondary" class="mt-4" @click="on.click">{{ i18n.t("general.close") }}</Button>
|
||||||
|
<Button button-type="primary" class="mt-4 ml-2" @click="submit(on.click)">{{ i18n.t("general.submit") }}</Button>
|
||||||
|
</template>
|
||||||
|
<template #activator="{ on }">
|
||||||
|
<Tooltip>
|
||||||
|
<template #content> Flag </template>
|
||||||
|
<Button button-type="secondary" size="small" :disabled="project.userActions.flagged" v-on="on">
|
||||||
|
<IconMdiFlag />
|
||||||
|
<span class="w-0 overflow-hidden !m-0">0</span>
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</template>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
@ -13,6 +13,7 @@ import { useContext } from "vite-ssr/vue";
|
|||||||
import Tooltip from "~/components/design/Tooltip.vue";
|
import Tooltip from "~/components/design/Tooltip.vue";
|
||||||
import { useAuthStore } from "~/store/auth";
|
import { useAuthStore } from "~/store/auth";
|
||||||
import { useNotificationStore } from "~/store/notification";
|
import { useNotificationStore } from "~/store/notification";
|
||||||
|
import FlagModal from "~/components/modals/FlagModal.vue";
|
||||||
|
|
||||||
const ctx = useContext();
|
const ctx = useContext();
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
@ -111,6 +112,8 @@ function toggleWatch() {
|
|||||||
<span class="ml-2">{{ watchingCount }}</span>
|
<span class="ml-2">{{ watchingCount }}</span>
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
<div class="px-1"></div>
|
||||||
|
<FlagModal :project="project" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { computed, ref } from "vue";
|
import { computed, ref } from "vue";
|
||||||
|
|
||||||
import { IPlatform, IProjectCategory, IPrompt, IVisibility, Color } from "hangar-internal";
|
import { IPlatform, IProjectCategory, IPrompt, IVisibility, Color, FlagReason } from "hangar-internal";
|
||||||
import { NamedPermission, Platform, ProjectCategory, Prompt } from "~/types/enums";
|
import { NamedPermission, Platform, ProjectCategory, Prompt } from "~/types/enums";
|
||||||
|
|
||||||
import { Announcement as AnnouncementObject, Announcement, IPermission, Role } from "hangar-api";
|
import { Announcement as AnnouncementObject, Announcement, IPermission, Role } from "hangar-api";
|
||||||
@ -45,6 +45,7 @@ export const useBackendDataStore = defineStore("backendData", () => {
|
|||||||
const orgRoles = ref<Role[]>([]);
|
const orgRoles = ref<Role[]>([]);
|
||||||
const projectRoles = ref<Role[]>([]);
|
const projectRoles = ref<Role[]>([]);
|
||||||
const channelColors = ref<Color[]>([]);
|
const channelColors = ref<Color[]>([]);
|
||||||
|
const flagReasons = ref<FlagReason[]>([]);
|
||||||
|
|
||||||
async function initBackendData() {
|
async function initBackendData() {
|
||||||
try {
|
try {
|
||||||
@ -85,6 +86,7 @@ export const useBackendDataStore = defineStore("backendData", () => {
|
|||||||
fetchIfNeeded(async () => useInternalApi("data/orgRoles", false), orgRoles),
|
fetchIfNeeded(async () => useInternalApi("data/orgRoles", false), orgRoles),
|
||||||
fetchIfNeeded(async () => useInternalApi("data/channelColors", false), channelColors),
|
fetchIfNeeded(async () => useInternalApi("data/channelColors", false), channelColors),
|
||||||
fetchIfNeeded(async () => useInternalApi("data/projectRoles", false), projectRoles),
|
fetchIfNeeded(async () => useInternalApi("data/projectRoles", false), projectRoles),
|
||||||
|
fetchIfNeeded(async () => useInternalApi("data/flagReasons", false), flagReasons),
|
||||||
]);
|
]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("ERROR FETCHING BACKEND DATA");
|
console.error("ERROR FETCHING BACKEND DATA");
|
||||||
@ -112,6 +114,7 @@ export const useBackendDataStore = defineStore("backendData", () => {
|
|||||||
orgRoles,
|
orgRoles,
|
||||||
projectRoles,
|
projectRoles,
|
||||||
channelColors,
|
channelColors,
|
||||||
|
flagReasons,
|
||||||
initBackendData,
|
initBackendData,
|
||||||
visibleCategories,
|
visibleCategories,
|
||||||
visiblePlatforms,
|
visiblePlatforms,
|
||||||
|
Loading…
Reference in New Issue
Block a user