Skip to content

Commit

Permalink
Merge pull request #1107 from solaris-games/dev
Browse files Browse the repository at this point in the history
Update 243
  • Loading branch information
SpacialCircumstances authored Jul 22, 2024
2 parents 011d00c + ebe9c8e commit 28d0976
Show file tree
Hide file tree
Showing 83 changed files with 1,336 additions and 752 deletions.
33 changes: 29 additions & 4 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@
"core-js": "^3.8.3",
"jquery": "^3.6.0",
"js-cookie": "^3.0.5",
"marked": "^13.0.2",
"moment": "^2.29.1",
"pixi-viewport": "^5.0.2",
"pixi.js-legacy": "^7.4.0",
"random-seed": "^0.3.0",
"uuid": "^10.0.0",
"voronoi": "^1.0.0",
"vue": "^2.6.12",
"vue-chartjs": "^3.5.1",
Expand Down
4 changes: 4 additions & 0 deletions client/src/game/star.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ class Star extends EventEmitter {
this.graphics_star.tint = 0xa0a0a0
}

if (gameHelper.isCapitalElimination(this.game) && gameHelper.isOwnerCapital(this.game, this.data)) {
this.graphics_star.tint = 0xFF0000
}

this.graphics_star.anchor.set(0.5)
this.graphics_star.width = 24.0/2.0
this.graphics_star.height = 24.0/2.0
Expand Down
13 changes: 13 additions & 0 deletions client/src/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import Reports from "./views/admin/Reports.vue";
import Insights from "./views/admin/Insights.vue";
import PasswordResets from "./views/admin/PasswordResets.vue";
import CommunityGuidelines from "./views/CommunityGuidelines.vue";
import AdminAnnouncements from './views/admin/Announcements.vue';
import Announcements from "./views/Announcements.vue";

Vue.use(Router)

Expand Down Expand Up @@ -138,10 +140,16 @@ export default new Router({
component: MyGuild
},
{

path: '/guild/details/:guildId',
name: 'guild-details',
component: GuildDetails
},
{
path: '/administration/announcements',
name: 'administration-announcements',
component: AdminAnnouncements
},
{
path: '/administration/games',
name: 'administration-games',
Expand Down Expand Up @@ -196,6 +204,11 @@ export default new Router({
path: '/guidelines',
name: 'guidelines',
component: CommunityGuidelines
},
{
path: '/announcements',
name: 'announcements',
component: Announcements
}
]
})
12 changes: 12 additions & 0 deletions client/src/services/api/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,18 @@ class AdminService extends BaseApiService {
getConversationForReport (reportId) {
return axios.get(`${this.BASE_URL}admin/reports/${reportId}/conversation`, { withCredentials: true })
}

createAnnouncement (announcement) {
return axios.post(`${this.BASE_URL}admin/announcements/`, announcement, { withCredentials: true })
}

deleteAnnouncement (announcementId) {
return axios.delete(`${this.BASE_URL}admin/announcements/${announcementId}`, { withCredentials: true })
}

getAllAnnouncements () {
return axios.get(`${this.BASE_URL}admin/announcements/`, { withCredentials: true })
}
}

export default new AdminService()
22 changes: 22 additions & 0 deletions client/src/services/api/announcements.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import BaseApiService from "./base";
import axios from "axios";

class AnnouncementsService extends BaseApiService {
getCurrentAnnouncements () {
return axios.get(`${this.BASE_URL}announcements/`, { withCredentials: true });
}

getLatestAnnouncement () {
return axios.get(`${this.BASE_URL}announcements/latest/`, { withCredentials: true });
}

getAnnouncementState () {
return axios.get(`${this.BASE_URL}announcements/state/`, { withCredentials: true });
}

markAsRead () {
return axios.patch(`${this.BASE_URL}announcements/state/markAsRead/`, {}, { withCredentials: true });
}
}

export default new AnnouncementsService();
27 changes: 24 additions & 3 deletions client/src/services/api/base.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,43 @@
import axios from 'axios'
import router from '../../router'
import axios from 'axios';
import { v7 as generateV7Uuid } from 'uuid';
import router from '../../router';

class BaseApiService {
constructor () {
this.BASE_URL = process.env.VUE_APP_API_HOST + '/api/'

axios.interceptors.request.use(config => {
config.headers['Idempotency-Key'] = this.buildIdempotencyKey();

return config;
},
error => {
return Promise.reject(error);
}, { synchronous: true, runWhen: this.isUnsafeMethod });

axios.interceptors.response.use(
response => {
return response
}, error => {
console.log(error);
// If any Unauthorized responses come back, redirect to login page.
if (error.response.status === 401) {
if (error.response?.status === 401) {
router.push({ name: 'home' })
}

return Promise.reject({ ...error })
})
}

isUnsafeMethod(config) {
// Rather than just going for idempotent methods, ie the safe ones and put and delete,
// We are electing here to NOT trust that put or delete currently behave in an idempotent way on the server...
return !['get', 'head', 'options', 'trace'].includes(config.method);
}

buildIdempotencyKey() {
return `${generateV7Uuid()}`;
}
}

export default BaseApiService
16 changes: 16 additions & 0 deletions client/src/services/gameHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,10 @@ class GameHelper {
return game.settings.general.mode === 'conquest' && game.settings.conquest.victoryCondition === 'homeStarPercentage'
}

isCapitalElimination (game) {
return game.settings.conquest.capitalStarElimination === 'enabled';
}

isKingOfTheHillMode (game) {
return game.settings.general.mode === 'kingOfTheHill'
}
Expand Down Expand Up @@ -603,6 +607,18 @@ class GameHelper {
return 'Unknown'
}

isOwnerCapital (game, star) {
if (!star.homeStar || !star.ownedByPlayerId) {
return false;
}

const ownersHomeStarId = this.getPlayerById(game, star.ownedByPlayerId).homeStarId;

console.log(ownersHomeStarId, star._id);

return ownersHomeStarId && ownersHomeStarId === star._id;
}

playerHasLowestTechLevel (game, techKey, player) {
const levels = [...new Set(game.galaxy.players
.filter(p => p.research != null)
Expand Down
9 changes: 9 additions & 0 deletions client/src/util/markdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { marked } from 'marked';

marked.use({
gfm: true,
});

export const renderMarkdown = (markdown) => {
return marked.parse(markdown);
};
82 changes: 82 additions & 0 deletions client/src/views/Announcements.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<template>
<view-container :hideTopBar="true">
<view-title
title="Announcements"
:showSocialLinks="true"
/>

<loading-spinner v-if="!announcementState || !announcements" />

<div v-else>
<p>
<a href="https://discord.com/invite/v7PD33d" target="_blank" title="Discord" style="text-decoration: none;">
Join the Discord
</a>to stay up-to-date, discuss the game and chat with the community!
</p>

<announcement
v-for="announcement in announcements"
:key="announcement._id"
:announcement="announcement"
:highlighted="isUnread(announcement)"
/>
</div>
</view-container>
</template>

<script>
import ViewContainer from "./components/ViewContainer.vue";
import ViewTitle from "./components/ViewTitle.vue";
import LoadingSpinner from "./components/LoadingSpinner.vue";
import Announcement from "./components/Announcement.vue";
import AnnouncementsApiService from "../services/api/announcements";
export default {
name: "Announcements",
components: {
'view-container': ViewContainer,
'view-title': ViewTitle,
'loading-spinner': LoadingSpinner,
'announcement': Announcement
},
data() {
return {
announcements: null,
announcementState: null
}
},
async mounted () {
const resp1 = await AnnouncementsApiService.getAnnouncementState();
if (resp1.status === 200) {
this.announcementState = resp1.data;
const resp2 = await AnnouncementsApiService.getCurrentAnnouncements();
if (resp2.status === 200) {
this.announcements = resp2.data;
await AnnouncementsApiService.markAsRead();
} else {
console.error(resp2);
}
} else {
console.error(resp1);
}
},
methods: {
isUnread (announcement) {
if (!announcement || !this.announcementState) {
return false;
}
return this.announcementState.unreadAnnouncements.includes(announcement._id);
}
}
}
</script>

<style scoped>
</style>
10 changes: 7 additions & 3 deletions client/src/views/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
<p class="mb-2 mt-2">Play <span class="text-warning">Solaris</span> on <a href="https://solaris.games" target="_blank" title="Web"><i class="fab fa-chrome me-1"></i>Web</a>, <a href="https://store.steampowered.com/app/1623930/Solaris/" target="_blank" title="Steam"><i class="fab fa-steam me-1"></i>Steam</a> and <a href="https://play.google.com/store/apps/details?id=com.voxel.solaris_android" target="_blank" title="Android"><i class="fab fa-google-play me-1"></i>Android</a>.</p>
</div>
</div>

<latest-announcement />
</view-container>

<parallax />
</div>
</template>
Expand All @@ -38,14 +40,16 @@ import ApiAuthService from '../services/api/auth'
import router from '../router'
import LoadingSpinnerVue from './components/LoadingSpinner.vue'
import ParallaxVue from './components/Parallax'
import LatestAnnouncement from "./components/LatestAnnouncement.vue";
export default {
components: {
'view-container': ViewContainer,
'view-title': ViewTitle,
'account-login': AccountLoginVue,
'loading-spinner': LoadingSpinnerVue,
'parallax': ParallaxVue
'parallax': ParallaxVue,
'latest-announcement': LatestAnnouncement
},
data () {
return {
Expand All @@ -54,7 +58,7 @@ export default {
},
async mounted () {
this.isAutoLoggingIn = true
try {
let response = await ApiAuthService.verify()
Expand Down
Loading

0 comments on commit 28d0976

Please sign in to comment.