diff --git a/DM/Services/DM.Services.DataAccess/BusinessObjects/Users/Token.cs b/DM/Services/DM.Services.DataAccess/BusinessObjects/Users/Token.cs
index d3cc85cc..d4ffceea 100644
--- a/DM/Services/DM.Services.DataAccess/BusinessObjects/Users/Token.cs
+++ b/DM/Services/DM.Services.DataAccess/BusinessObjects/Users/Token.cs
@@ -9,6 +9,7 @@ namespace DM.Services.DataAccess.BusinessObjects.Users;
///
/// DAL model for authorization token
///
+[Table("Tokens")]
public class Token : IRemovable
{
///
diff --git a/DM/Services/DM.Services.Gaming/BusinessProcesses/Games/Reading/GameReadingService.cs b/DM/Services/DM.Services.Gaming/BusinessProcesses/Games/Reading/GameReadingService.cs
index 28e9dc60..b3b54886 100644
--- a/DM/Services/DM.Services.Gaming/BusinessProcesses/Games/Reading/GameReadingService.cs
+++ b/DM/Services/DM.Services.Gaming/BusinessProcesses/Games/Reading/GameReadingService.cs
@@ -88,7 +88,7 @@ await unreadCountersRepository.FillEntityCounters(
var gameRoomIds = roomIds.ToArray();
game.UnreadPostsCount = gameRoomIds.Sum(id =>
unreadPostCounters.TryGetValue(id, out var count) ? count : 0);
- game.Pendings = pendingPosts.Where(p => gameRoomIds.Contains(p.RoomId));
+ game.PendingPosts = pendingPosts.Where(p => gameRoomIds.Contains(p.RoomId));
}
return games;
diff --git a/DM/Services/DM.Services.Gaming/Dto/Output/Game.cs b/DM/Services/DM.Services.Gaming/Dto/Output/Game.cs
index df2be661..9f72deef 100644
--- a/DM/Services/DM.Services.Gaming/Dto/Output/Game.cs
+++ b/DM/Services/DM.Services.Gaming/Dto/Output/Game.cs
@@ -57,7 +57,6 @@ public class Game
///
/// Pending assistant if any
- /// Due to some issues in EFCore 3.1.5 had to move to IEnumerable, but make no mistake - that is a single assistant every time!
///
public GeneralUser PendingAssistant { get; set; }
@@ -79,7 +78,7 @@ public class Game
///
/// Game pending posts
///
- public IEnumerable Pendings { get; set; }
+ public IEnumerable PendingPosts { get; set; }
///
/// Game title
diff --git a/DM/Web/DM.Web.API/Startup.cs b/DM/Web/DM.Web.API/Startup.cs
index 67b61313..bc33da73 100644
--- a/DM/Web/DM.Web.API/Startup.cs
+++ b/DM/Web/DM.Web.API/Startup.cs
@@ -154,7 +154,7 @@ public void Configure(IApplicationBuilder appBuilder,
if (migrateOnStart)
{
dbContext.Database.Migrate();
- throw new Exception("Migration is complete");
+ Environment.Exit(-1);
}
appBuilder
diff --git a/DM/Web/DM.Web.Modern/src/api/models/gaming/index.ts b/DM/Web/DM.Web.Modern/src/api/models/gaming/index.ts
index f9078296..0c86e27c 100644
--- a/DM/Web/DM.Web.Modern/src/api/models/gaming/index.ts
+++ b/DM/Web/DM.Web.Modern/src/api/models/gaming/index.ts
@@ -1,4 +1,15 @@
+import { User } from '@/api/models/community';
+
export * from './games';
export * from './attributes';
export * from './characters';
export * from './rooms';
+
+export interface Comment {
+ id: string;
+ author: User;
+ created: string;
+ updated: string | null;
+ text: string;
+ likes: User[];
+}
diff --git a/DM/Web/DM.Web.Modern/src/api/requests/gamingApi.ts b/DM/Web/DM.Web.Modern/src/api/requests/gamingApi.ts
index 4e142b84..d6a9891e 100644
--- a/DM/Web/DM.Web.Modern/src/api/requests/gamingApi.ts
+++ b/DM/Web/DM.Web.Modern/src/api/requests/gamingApi.ts
@@ -1,5 +1,5 @@
-import { ApiResult, Envelope, ListEnvelope } from '@/api/models/common';
-import { Game, AttributeSchema, Tag, Character, Room } from '@/api/models/gaming';
+import { ApiResult, Envelope, ListEnvelope, PagingQuery } from '@/api/models/common';
+import { Game, AttributeSchema, Tag, Character, Room, Comment } from '@/api/models/gaming';
import { User } from '@/api/models/community';
import Api from '@/api';
@@ -33,6 +33,11 @@ export default new class {
return data!;
}
+ public async getComments(gameId: string, query: PagingQuery): Promise> {
+ const { data } = await Api.get>(`games/${gameId}/comments`, query);
+ return data!;
+ }
+
public async getSchemas(): Promise> {
const { data } = await Api.get>('schemata');
return data!;
@@ -51,15 +56,27 @@ export default new class {
return await Api.post>('games', game);
}
- public async createCharacter(id: string, character: Character): Promise>> {
- return await Api.post>(`games/${id}/characters`, character);
+ public async createCharacter(gameId: string, character: Character): Promise>> {
+ return await Api.post>(`games/${gameId}/characters`, character);
+ }
+
+ public async createComment(gameId: string, comment: Comment): Promise>> {
+ return await Api.post>(`games/${gameId}/comments`, comment);
+ }
+
+ public async subscribe(gameId: string): Promise>> {
+ return await Api.post>(`games/${gameId}/readers`);
+ }
+
+ public async unsubscribe(gameId: string): Promise> {
+ return await Api.delete(`games/${gameId}/readers`);
}
- public async subscribe(id: string): Promise>> {
- return await Api.post>(`games/${id}/readers`);
+ public async updateComment(commentId: string, comment: Comment): Promise>> {
+ return await Api.patch>(`games/comments/${commentId}`, comment);
}
- public async unsubscribe(id: string): Promise> {
- return await Api.delete(`games/${id}/readers`);
+ public async deleteComment(commentId: string): Promise> {
+ return await Api.delete(`games/comments/${commentId}`);
}
}();
diff --git a/DM/Web/DM.Web.Modern/src/router.ts b/DM/Web/DM.Web.Modern/src/router.ts
index 7bb32c73..a0506ed6 100644
--- a/DM/Web/DM.Web.Modern/src/router.ts
+++ b/DM/Web/DM.Web.Modern/src/router.ts
@@ -2,7 +2,7 @@ import Vue from 'vue';
import Router from 'vue-router';
import GeneralMenu from './views/layout/GeneralMenu.vue';
-import GameMenu from './views/pages/game/GameMenu.vue';
+import GameMenu from './views/pages/game/menu/GameMenu.vue';
import GeneralSidebar from './views/layout/GeneralSidebar.vue';
Vue.use(Router);
@@ -173,10 +173,15 @@ export default new Router({
children: [{
name: 'game',
path: '',
- component: () => import('./views/pages/game/Information.vue'),
+ component: () => import('./views/pages/game/information/Information.vue'),
}, {
- name: 'game-comments',
path: 'out-of-session',
+ component: () => import('./views/pages/game/comments/GameComments.vue'),
+ children: [{
+ name: 'game-comments',
+ path: ':n?',
+ component: () => import('./views/pages/game/comments/GameCommentsList.vue'),
+ }],
}, {
name: 'create-character',
path: 'create-character',
diff --git a/DM/Web/DM.Web.Modern/src/store/forum/actions.ts b/DM/Web/DM.Web.Modern/src/store/forum/actions.ts
index 675baada..2d628556 100644
--- a/DM/Web/DM.Web.Modern/src/store/forum/actions.ts
+++ b/DM/Web/DM.Web.Modern/src/store/forum/actions.ts
@@ -83,7 +83,7 @@ const actions: ActionTree = {
commit('updateComment', data?.resource);
}
},
- async deleteComment(_0, { id }): Promise {
+ async deleteComment(_, { id }): Promise {
await forumApi.deleteComment(id);
},
async markAllTopicsAsRead({ commit }, { id }): Promise {
diff --git a/DM/Web/DM.Web.Modern/src/store/gaming/actions.ts b/DM/Web/DM.Web.Modern/src/store/gaming/actions.ts
index 6d198204..cfd10600 100644
--- a/DM/Web/DM.Web.Modern/src/store/gaming/actions.ts
+++ b/DM/Web/DM.Web.Modern/src/store/gaming/actions.ts
@@ -2,7 +2,8 @@ import { ActionTree } from 'vuex';
import gamingApi from '@/api/requests/gamingApi';
import GamingState from './gamingState';
import RootState from './../rootState';
-import { AttributeSchema } from '@/api/models/gaming';
+import {AttributeSchema, Comment} from '@/api/models/gaming';
+import { PagingQuery } from '@/api/models/common';
const actions: ActionTree = {
async fetchOwnGames({ commit }): Promise {
@@ -10,7 +11,7 @@ const actions: ActionTree = {
commit('updateOwnGames', games);
},
- async fetchPopularGames({commit}): Promise {
+ async fetchPopularGames({ commit }): Promise {
const { resources: games } = await gamingApi.getPopularGames();
commit('updatePopularGames', games);
},
@@ -44,15 +45,6 @@ const actions: ActionTree = {
$router.push({ name: 'game', params: { id: game.id } });
}
},
- async createCharacter({ state }, { character, $router }): Promise {
- const { data, error } = await gamingApi.createCharacter(state.selectedGame!.id, character);
- if (error) {
- $router.push({ name: 'error', params: { code: error.code } });
- } else {
- const { resource: character } = data!;
- $router.push({ name: 'game-characters', params: { id: state.selectedGame!.id, characterId: character.id } })
- }
- },
async selectGame({ commit }, { id, router }): Promise {
commit('updateSelectedGame', null);
@@ -65,26 +57,16 @@ const actions: ActionTree = {
commit('updateSelectedGame', game);
}
},
- async fetchSelectedGameCharacters({ commit }, { id }): Promise {
- commit('updateSelectedGameCharacters', null);
- const { resources: characters } = await gamingApi.getCharacters(id);
- commit('updateSelectedGameCharacters', characters);
- },
- async fetchSelectedGameRooms({ commit }, { id }): Promise {
- commit('updateSelectedGameRooms', null);
- const { resources: rooms } = await gamingApi.getRooms(id);
- commit('updateSelectedGameRooms', rooms);
- },
+
async fetchSelectedGameReaders({ commit }, { id }): Promise {
commit('updateSelectedGameReaders', null);
const { resources: readers } = await gamingApi.getReaders(id);
commit('updateSelectedGameReaders', readers);
},
-
async subscribe({ commit, state }, { router }): Promise {
const { data, error } = await gamingApi.subscribe(state.selectedGame!.id);
if (error) {
- router.push({ name: 'error', params: { code: error.code }});
+ router.push({ name: 'error', params: { code: error.code } });
} else {
const { resource: reader } = data!;
commit('addReader', reader);
@@ -93,11 +75,55 @@ const actions: ActionTree = {
async unsubscribe({ commit, state, rootState }, { router }): Promise {
const { error } = await gamingApi.unsubscribe(state.selectedGame!.id);
if (error) {
- router.push({ name: 'error', params: { code: error.code }});
+ router.push({ name: 'error', params: { code: error.code } });
} else {
commit('removeReader', rootState.user);
}
},
+
+ async fetchSelectedGameCharacters({ commit }, { id }): Promise {
+ commit('updateSelectedGameCharacters', null);
+ const { resources: characters } = await gamingApi.getCharacters(id);
+ commit('updateSelectedGameCharacters', characters);
+ },
+ async createCharacter({ state }, { character, $router }): Promise {
+ const { data, error } = await gamingApi.createCharacter(state.selectedGame!.id, character);
+ if (error) {
+ $router.push({ name: 'error', params: { code: error.code } });
+ } else {
+ const { resource: character } = data!;
+ $router.push({ name: 'game-characters', params: { id: state.selectedGame!.id, characterId: character.id } })
+ }
+ },
+
+ async fetchSelectedGameComments({ commit }, { id, n }): Promise {
+ commit('updateSelectedGameComments', null);
+ const data = await gamingApi.getComments(id, { number: n } as PagingQuery);
+ commit('updateSelectedGameComments', data!);
+ },
+ async createComment({ state }, { comment, $router }): Promise {
+ const { id } = state.selectedGame!;
+ const { error: postCommentError } = await gamingApi.createComment(id, comment);
+ if (postCommentError) return Promise.reject();
+
+ const data = await gamingApi.getComments(id, { size: 0, number: 0, skip: 0 });
+ $router.push({ name: 'game-comments', params: { id, n: data.paging!.total } });
+ },
+ async updateComment({ commit }, { id, comment }): Promise {
+ const { data, error } = await gamingApi.updateComment(id, comment as Comment);
+ if (!error) {
+ commit('updateComment', data!.resource);
+ }
+ },
+ async deleteComment(_, { id }) {
+ await gamingApi.deleteComment(id);
+ },
+
+ async fetchSelectedGameRooms({ commit }, { id }): Promise {
+ commit('updateSelectedGameRooms', null);
+ const { resources: rooms } = await gamingApi.getRooms(id);
+ commit('updateSelectedGameRooms', rooms);
+ },
};
export default actions;
diff --git a/DM/Web/DM.Web.Modern/src/store/gaming/gamingState.ts b/DM/Web/DM.Web.Modern/src/store/gaming/gamingState.ts
index 21e0cddb..a6760731 100644
--- a/DM/Web/DM.Web.Modern/src/store/gaming/gamingState.ts
+++ b/DM/Web/DM.Web.Modern/src/store/gaming/gamingState.ts
@@ -1,5 +1,6 @@
-import {Game, AttributeSchema, Tag, Character, Room} from '@/api/models/gaming';
-import {User} from '@/api/models/community';
+import { Game, AttributeSchema, Tag, Character, Room, Comment } from '@/api/models/gaming';
+import { User } from '@/api/models/community';
+import { ListEnvelope } from '@/api/models/common';
export default interface GamingState {
ownGames: Game[] | null;
@@ -12,4 +13,5 @@ export default interface GamingState {
selectedGameCharacters: Character[] | null;
selectedGameRooms: Room[] | null;
selectedGameReaders: User[] | null;
+ selectedGameComments: ListEnvelope | null;
}
diff --git a/DM/Web/DM.Web.Modern/src/store/gaming/getters.ts b/DM/Web/DM.Web.Modern/src/store/gaming/getters.ts
index a8f8a0e3..5311cac9 100644
--- a/DM/Web/DM.Web.Modern/src/store/gaming/getters.ts
+++ b/DM/Web/DM.Web.Modern/src/store/gaming/getters.ts
@@ -13,6 +13,7 @@ const getters: GetterTree = {
selectedGameCharacters: (state) => state.selectedGameCharacters,
selectedGameRooms: (state) => state.selectedGameRooms,
selectedGameReaders: (state) => state.selectedGameReaders,
+ selectedGameComments: (state) => state.selectedGameComments,
};
export default getters;
diff --git a/DM/Web/DM.Web.Modern/src/store/gaming/index.ts b/DM/Web/DM.Web.Modern/src/store/gaming/index.ts
index 60ef122d..1f5fbc40 100644
--- a/DM/Web/DM.Web.Modern/src/store/gaming/index.ts
+++ b/DM/Web/DM.Web.Modern/src/store/gaming/index.ts
@@ -15,6 +15,7 @@ const state: GamingState = {
selectedGameCharacters: null,
selectedGameRooms: null,
selectedGameReaders: null,
+ selectedGameComments: null,
};
const gaming: Module = {
diff --git a/DM/Web/DM.Web.Modern/src/store/gaming/mutations.ts b/DM/Web/DM.Web.Modern/src/store/gaming/mutations.ts
index 8ce129a0..3a037f63 100644
--- a/DM/Web/DM.Web.Modern/src/store/gaming/mutations.ts
+++ b/DM/Web/DM.Web.Modern/src/store/gaming/mutations.ts
@@ -1,7 +1,8 @@
import { MutationTree } from 'vuex';
import GamingState from './gamingState';
-import {Game, AttributeSchema, Tag, Character, Room, GameParticipation} from '@/api/models/gaming';
-import {User} from '@/api/models/community';
+import { Game, AttributeSchema, Tag, Character, Room, GameParticipation, Comment } from '@/api/models/gaming';
+import { User } from '@/api/models/community';
+import { ListEnvelope } from '@/api/models/common';
const mutations: MutationTree = {
updateOwnGames(state, payload: Game[]) {
@@ -34,6 +35,18 @@ const mutations: MutationTree = {
updateSelectedGameReaders(state, payload: User[]) {
state.selectedGameReaders = payload;
},
+ updateSelectedGameComments(state, payload: ListEnvelope) {
+ state.selectedGameComments = payload;
+ },
+ updateComment(state, payload: Comment) {
+ state.selectedGameComments!.resources = state.selectedGameComments!.resources.map(comment => {
+ if (comment.id === payload.id) {
+ return payload;
+ }
+
+ return comment;
+ });
+ },
addReader(state, payload: User) {
if (state.selectedGame === null || state.selectedGameReaders === null) return;
diff --git a/DM/Web/DM.Web.Modern/src/views/layout/menu/MenuLink.vue b/DM/Web/DM.Web.Modern/src/views/layout/menu/MenuLink.vue
index 2d3555b3..059e4586 100644
--- a/DM/Web/DM.Web.Modern/src/views/layout/menu/MenuLink.vue
+++ b/DM/Web/DM.Web.Modern/src/views/layout/menu/MenuLink.vue
@@ -3,7 +3,7 @@
{{ game.title }}
-
+