generated from VLADIMIR/template_frontend
up
This commit is contained in:
+91
-78
@@ -44,48 +44,48 @@ service EveningDetectiveServer {
|
||||
rpc GetTasks(GetTasksReq) returns (GetTasksRsp) {
|
||||
option (google.api.http) = { get: "/api/tasks" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "Задачи";
|
||||
summary: "Получить общую доску задач";
|
||||
tags : "Задачи";
|
||||
summary : "Получить общую доску задач";
|
||||
description: "Доступно разработчикам и администратору.";
|
||||
};
|
||||
}
|
||||
rpc GetTaskAssignees(GetTaskAssigneesReq) returns (GetTaskAssigneesRsp) {
|
||||
option (google.api.http) = { get: "/api/tasks/assignees" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "Задачи";
|
||||
summary: "Получить разработчиков для назначения";
|
||||
tags : "Задачи";
|
||||
summary : "Получить разработчиков для назначения";
|
||||
description: "Доступно разработчикам и администратору.";
|
||||
};
|
||||
}
|
||||
rpc CreateTask(CreateTaskReq) returns (TaskRsp) {
|
||||
option (google.api.http) = { post: "/api/tasks" body: "*" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "Задачи";
|
||||
summary: "Создать задачу";
|
||||
tags : "Задачи";
|
||||
summary : "Создать задачу";
|
||||
description: "Доступно разработчикам и администратору.";
|
||||
};
|
||||
}
|
||||
rpc UpdateTask(UpdateTaskReq) returns (TaskRsp) {
|
||||
option (google.api.http) = { put: "/api/tasks/{ID}" body: "*" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "Задачи";
|
||||
summary: "Редактировать задачу";
|
||||
tags : "Задачи";
|
||||
summary : "Редактировать задачу";
|
||||
description: "Доступно разработчикам и администратору.";
|
||||
};
|
||||
}
|
||||
rpc SetTaskStatus(SetTaskStatusReq) returns (TaskRsp) {
|
||||
option (google.api.http) = { post: "/api/tasks/{ID}/status" body: "*" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "Задачи";
|
||||
summary: "Изменить статус задачи";
|
||||
tags : "Задачи";
|
||||
summary : "Изменить статус задачи";
|
||||
description: "Доступно разработчикам и администратору.";
|
||||
};
|
||||
}
|
||||
rpc DeleteTask(DeleteTaskReq) returns (DeleteTaskRsp) {
|
||||
option (google.api.http) = { post: "/api/tasks/{ID}/delete" body: "*" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "Задачи";
|
||||
summary: "Удалить задачу";
|
||||
tags : "Задачи";
|
||||
summary : "Удалить задачу";
|
||||
description: "Доступно разработчикам и администратору.";
|
||||
};
|
||||
}
|
||||
@@ -328,7 +328,7 @@ service EveningDetectiveServer {
|
||||
rpc GetPlaylists(GetPlaylistsReq) returns (GetPlaylistsRsp) {
|
||||
option (google.api.http) = { get: "/api/playlists" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "Музыка";
|
||||
tags : "Музыка";
|
||||
summary: "Получить плейлисты";
|
||||
};
|
||||
}
|
||||
@@ -336,7 +336,7 @@ service EveningDetectiveServer {
|
||||
rpc CreatePlaylist(CreatePlaylistReq) returns (CreatePlaylistRsp) {
|
||||
option (google.api.http) = { post: "/api/playlists" body: "*" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "Музыка";
|
||||
tags : "Музыка";
|
||||
summary: "Создать плейлист";
|
||||
};
|
||||
}
|
||||
@@ -344,7 +344,7 @@ service EveningDetectiveServer {
|
||||
rpc UpdatePlaylist(UpdatePlaylistReq) returns (UpdatePlaylistRsp) {
|
||||
option (google.api.http) = { put: "/api/playlists/{ID}" body: "*" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "Музыка";
|
||||
tags : "Музыка";
|
||||
summary: "Изменить плейлист";
|
||||
};
|
||||
}
|
||||
@@ -352,7 +352,7 @@ service EveningDetectiveServer {
|
||||
rpc DeletePlaylist(DeletePlaylistReq) returns (DeletePlaylistRsp) {
|
||||
option (google.api.http) = { delete: "/api/playlists/{ID}" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "Музыка";
|
||||
tags : "Музыка";
|
||||
summary: "Удалить плейлист";
|
||||
};
|
||||
}
|
||||
@@ -360,7 +360,7 @@ service EveningDetectiveServer {
|
||||
rpc UploadPlaylistTrack(UploadPlaylistTrackReq) returns (UploadPlaylistTrackRsp) {
|
||||
option (google.api.http) = { post: "/api/playlists/{playlistID}/tracks" body: "*" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "Музыка";
|
||||
tags : "Музыка";
|
||||
summary: "Загрузить MP3 в плейлист";
|
||||
};
|
||||
}
|
||||
@@ -368,7 +368,7 @@ service EveningDetectiveServer {
|
||||
rpc DeletePlaylistTrack(DeletePlaylistTrackReq) returns (DeletePlaylistTrackRsp) {
|
||||
option (google.api.http) = { delete: "/api/playlists/{playlistID}/tracks/{trackID}" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "Музыка";
|
||||
tags : "Музыка";
|
||||
summary: "Удалить MP3 из плейлиста";
|
||||
};
|
||||
}
|
||||
@@ -376,7 +376,7 @@ service EveningDetectiveServer {
|
||||
rpc SetScenarioPlaylist(SetScenarioPlaylistReq) returns (SetScenarioPlaylistRsp) {
|
||||
option (google.api.http) = { put: "/api/scenarios/{ID}/playlist" body: "*" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "Музыка";
|
||||
tags : "Музыка";
|
||||
summary: "Назначить плейлист сценарию";
|
||||
};
|
||||
}
|
||||
@@ -703,7 +703,7 @@ service EveningDetectiveServer {
|
||||
rpc GetGameMusic(GetGameMusicReq) returns (GetGameMusicRsp) {
|
||||
option (google.api.http) = { get: "/api/games/{gameID}/music" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "Музыка";
|
||||
tags : "Музыка";
|
||||
summary: "Получить музыку игры";
|
||||
};
|
||||
}
|
||||
@@ -711,7 +711,7 @@ service EveningDetectiveServer {
|
||||
rpc SetGameMusic(SetGameMusicReq) returns (SetGameMusicRsp) {
|
||||
option (google.api.http) = { post: "/api/games/{gameID}/music" body: "*" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
tags: "Музыка";
|
||||
tags : "Музыка";
|
||||
summary: "Изменить музыку игры";
|
||||
};
|
||||
}
|
||||
@@ -720,8 +720,8 @@ service EveningDetectiveServer {
|
||||
option (google.api.http) = { post: "/api/screens/music/advance" body: "*" };
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
security: { security_requirement: {} }
|
||||
tags: "Музыка";
|
||||
summary: "Перейти к следующему треку экрана";
|
||||
tags : "Музыка";
|
||||
summary : "Перейти к следующему треку экрана";
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1275,6 +1275,8 @@ message GetPermissionsReq {}
|
||||
|
||||
message GetPermissionsRsp {
|
||||
repeated string permissions = 1;
|
||||
// Actual server environment: prod or venue.
|
||||
string environment = 2;
|
||||
}
|
||||
|
||||
message UploadFileReq {
|
||||
@@ -1301,8 +1303,8 @@ message PlaylistTrack {
|
||||
}
|
||||
|
||||
message Playlist {
|
||||
int32 ID = 1;
|
||||
string name = 2;
|
||||
int32 ID = 1;
|
||||
string name = 2;
|
||||
repeated PlaylistTrack tracks = 3;
|
||||
}
|
||||
|
||||
@@ -1389,20 +1391,20 @@ message GetScenarioRsp {
|
||||
}
|
||||
|
||||
message Scenario {
|
||||
int32 ID = 1;
|
||||
string name = 2;
|
||||
optional string description = 3;
|
||||
optional string image = 4;
|
||||
Story story = 5;
|
||||
string status = 6;
|
||||
User author = 7;
|
||||
google.protobuf.Timestamp updated_at = 8;
|
||||
google.protobuf.Timestamp created_at = 9;
|
||||
google.protobuf.Timestamp published_at = 10;
|
||||
double average_rating = 11;
|
||||
int32 reviews_count = 12;
|
||||
string difficulty = 13;
|
||||
optional int32 music_playlist_id = 14 [json_name = "music_playlist_id"];
|
||||
int32 ID = 1;
|
||||
string name = 2;
|
||||
optional string description = 3;
|
||||
optional string image = 4;
|
||||
Story story = 5;
|
||||
string status = 6;
|
||||
User author = 7;
|
||||
google.protobuf.Timestamp updated_at = 8;
|
||||
google.protobuf.Timestamp created_at = 9;
|
||||
google.protobuf.Timestamp published_at = 10;
|
||||
double average_rating = 11;
|
||||
int32 reviews_count = 12;
|
||||
string difficulty = 13;
|
||||
optional int32 music_playlist_id = 14 [json_name = "music_playlist_id"];
|
||||
}
|
||||
|
||||
message Story {
|
||||
@@ -1719,13 +1721,13 @@ enum MusicPlaybackState {
|
||||
}
|
||||
|
||||
message MusicState {
|
||||
Playlist playlist = 1;
|
||||
int32 track_index = 2;
|
||||
int64 position_ms = 3;
|
||||
int32 volume = 4;
|
||||
bool loop = 5;
|
||||
MusicPlaybackState playback = 6;
|
||||
int64 state_version = 7;
|
||||
Playlist playlist = 1;
|
||||
int32 track_index = 2;
|
||||
int64 position_ms = 3;
|
||||
int32 volume = 4;
|
||||
bool loop = 5;
|
||||
MusicPlaybackState playback = 6;
|
||||
int64 state_version = 7;
|
||||
}
|
||||
|
||||
message GetGameMusicReq {
|
||||
@@ -1733,20 +1735,20 @@ message GetGameMusicReq {
|
||||
}
|
||||
|
||||
message GetGameMusicRsp {
|
||||
repeated Playlist playlists = 1;
|
||||
MusicState state = 2;
|
||||
repeated Playlist playlists = 1;
|
||||
MusicState state = 2;
|
||||
int32 scenario_playlist_id = 3;
|
||||
int32 game_playlist_id = 4;
|
||||
}
|
||||
|
||||
message SetGameMusicReq {
|
||||
int32 gameID = 1;
|
||||
int32 playlistID = 2;
|
||||
int32 track_index = 3;
|
||||
int32 gameID = 1;
|
||||
int32 playlistID = 2;
|
||||
int32 track_index = 3;
|
||||
int64 position_ms = 4;
|
||||
int32 volume = 5;
|
||||
bool loop = 6;
|
||||
MusicPlaybackState playback = 7;
|
||||
int32 volume = 5;
|
||||
bool loop = 6;
|
||||
MusicPlaybackState playback = 7;
|
||||
}
|
||||
|
||||
message SetGameMusicRsp {
|
||||
@@ -2239,53 +2241,64 @@ message TicketPage {
|
||||
|
||||
// Developer tasks use new, in_progress, review and done statuses.
|
||||
message DeveloperTask {
|
||||
int32 ID = 1;
|
||||
string title = 2;
|
||||
int32 ID = 1;
|
||||
string title = 2;
|
||||
string description = 3;
|
||||
string status = 4;
|
||||
string status = 4;
|
||||
// Omitted assignee means the task is unassigned.
|
||||
optional int32 assigneeID = 5;
|
||||
string assigneeName = 6;
|
||||
optional int32 authorID = 7;
|
||||
optional int32 assigneeID = 5;
|
||||
string assigneeName = 6;
|
||||
optional int32 authorID = 7;
|
||||
// Calendar deadline in YYYY-MM-DD format; empty means no deadline.
|
||||
string dueDate = 8;
|
||||
string dueDate = 8;
|
||||
google.protobuf.Timestamp createdAt = 9;
|
||||
google.protobuf.Timestamp updatedAt = 10;
|
||||
// Required for updates and deletion to detect concurrent edits.
|
||||
int32 version = 11;
|
||||
}
|
||||
|
||||
message TaskAssignee {
|
||||
int32 ID = 1;
|
||||
int32 ID = 1;
|
||||
string name = 2;
|
||||
}
|
||||
|
||||
message GetTasksReq {}
|
||||
|
||||
message GetTasksRsp { repeated DeveloperTask tasks = 1; }
|
||||
|
||||
message GetTaskAssigneesReq {}
|
||||
|
||||
message GetTaskAssigneesRsp { repeated TaskAssignee assignees = 1; }
|
||||
|
||||
message CreateTaskReq {
|
||||
string title = 1;
|
||||
string description = 2;
|
||||
string status = 3;
|
||||
optional int32 assigneeID = 4;
|
||||
string dueDate = 5;
|
||||
string title = 1;
|
||||
string description = 2;
|
||||
string status = 3;
|
||||
optional int32 assigneeID = 4;
|
||||
string dueDate = 5;
|
||||
}
|
||||
|
||||
message UpdateTaskReq {
|
||||
int32 ID = 1;
|
||||
string title = 2;
|
||||
string description = 3;
|
||||
string status = 4;
|
||||
optional int32 assigneeID = 5;
|
||||
string dueDate = 6;
|
||||
int32 version = 7;
|
||||
int32 ID = 1;
|
||||
string title = 2;
|
||||
string description = 3;
|
||||
string status = 4;
|
||||
optional int32 assigneeID = 5;
|
||||
string dueDate = 6;
|
||||
int32 version = 7;
|
||||
}
|
||||
|
||||
message SetTaskStatusReq {
|
||||
int32 ID = 1;
|
||||
string status = 2;
|
||||
int32 version = 3;
|
||||
int32 ID = 1;
|
||||
string status = 2;
|
||||
int32 version = 3;
|
||||
}
|
||||
|
||||
message DeleteTaskReq {
|
||||
int32 ID = 1;
|
||||
int32 ID = 1;
|
||||
int32 version = 2;
|
||||
}
|
||||
|
||||
message TaskRsp { DeveloperTask task = 1; }
|
||||
|
||||
message DeleteTaskRsp {}
|
||||
|
||||
@@ -184,6 +184,8 @@ export type GetPermissionsReq = {
|
||||
|
||||
export type GetPermissionsRsp = {
|
||||
permissions: string[] | undefined;
|
||||
// Actual server environment: prod or venue.
|
||||
environment: string | undefined;
|
||||
};
|
||||
|
||||
export type UploadFileReq = {
|
||||
|
||||
@@ -1,35 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
import { MenuOutlined } from '@vicons/material'
|
||||
import { Icon } from '@vicons/utils'
|
||||
import { useMessage } from 'naive-ui'
|
||||
import { ref, watch } from 'vue'
|
||||
import { NTag, useMessage } from 'naive-ui'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import { getAuthClient } from '@/api/auth_client'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { useUIStore } from '@/stores/ui'
|
||||
|
||||
const props = defineProps<{ active?: string }>()
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const router = useRouter()
|
||||
const client = getAuthClient()
|
||||
const uiStore = useUIStore()
|
||||
const message = useMessage()
|
||||
|
||||
const permissions = ref<string[]>([])
|
||||
const { permissions, environment, isLoadingEnvironment } = storeToRefs(uiStore)
|
||||
const environmentLabel = computed(() => {
|
||||
if (isLoadingEnvironment.value) return 'Среда: …'
|
||||
if (environment.value === 'prod') return 'Сервер'
|
||||
if (environment.value === 'venue') return 'Локальная сеть'
|
||||
return 'Среда: ?'
|
||||
})
|
||||
|
||||
async function getPermissions() {
|
||||
permissions.value = []
|
||||
if (!authStore.user) return
|
||||
const token = authStore.getToken()
|
||||
try {
|
||||
const res = await client.GetPermissions({})
|
||||
if (token === authStore.getToken()) permissions.value = res.permissions || []
|
||||
} catch (err) {
|
||||
message.error('Не удалось загрузить права доступа')
|
||||
console.error('Failed to load permissions:', err)
|
||||
}
|
||||
}
|
||||
watch(() => authStore.user, getPermissions, { immediate: true })
|
||||
watch(
|
||||
() => authStore.user,
|
||||
async () => {
|
||||
try {
|
||||
await uiStore.load()
|
||||
} catch (err) {
|
||||
message.error('Не удалось загрузить сведения сервера')
|
||||
console.error('Failed to load server information:', err)
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
function hasPermission(permission: string): boolean {
|
||||
return permissions.value.includes(permission)
|
||||
@@ -90,13 +96,7 @@ const openMenu = ref(false)
|
||||
>
|
||||
Игры
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="menu-item-block"
|
||||
@click="router.push('/screen')"
|
||||
>
|
||||
Экран
|
||||
</button>
|
||||
<button type="button" class="menu-item-block" @click="router.push('/screen')">Экран</button>
|
||||
<button
|
||||
type="button"
|
||||
class="menu-item-block"
|
||||
@@ -144,6 +144,14 @@ const openMenu = ref(false)
|
||||
</div>
|
||||
|
||||
<div class="right-group">
|
||||
<NTag
|
||||
size="small"
|
||||
:type="environment === 'venue' ? 'warning' : 'default'"
|
||||
:title="environment ? 'Среда подключённого сервера' : 'Среда сервера не определена'"
|
||||
role="status"
|
||||
>
|
||||
{{ environmentLabel }}
|
||||
</NTag>
|
||||
<button
|
||||
v-if="!authStore.isAuthenticated"
|
||||
type="button"
|
||||
@@ -196,6 +204,13 @@ const openMenu = ref(false)
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.right-group {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.right {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { getAuthClient } from '@/api/auth_client'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
export const useUIStore = defineStore('ui', () => {
|
||||
const permissions = ref<string[]>([])
|
||||
const environment = ref<'prod' | 'venue' | null>(null)
|
||||
const isLoadingEnvironment = ref(true)
|
||||
let requestId = 0
|
||||
|
||||
async function load() {
|
||||
const authStore = useAuthStore()
|
||||
const token = authStore.getToken()
|
||||
const currentRequest = ++requestId
|
||||
permissions.value = []
|
||||
environment.value = null
|
||||
isLoadingEnvironment.value = true
|
||||
try {
|
||||
const res = await getAuthClient().GetPermissions({})
|
||||
if (currentRequest !== requestId) return
|
||||
if (token === authStore.getToken()) permissions.value = res.permissions || []
|
||||
if (res.environment === 'prod' || res.environment === 'venue') {
|
||||
environment.value = res.environment
|
||||
}
|
||||
} catch (err) {
|
||||
if (currentRequest === requestId) throw err
|
||||
} finally {
|
||||
if (currentRequest === requestId) isLoadingEnvironment.value = false
|
||||
}
|
||||
}
|
||||
|
||||
return { permissions, environment, isLoadingEnvironment, load }
|
||||
})
|
||||
Reference in New Issue
Block a user