Skip to content

Commit 04850af

Browse files
mohsin-rszczz
andcommitted
Implement one user concurrent access for storylines.
Co-authored-by: szczz <matt.szczerba55@gmail.com>
1 parent bc2f3c0 commit 04850af

File tree

16 files changed

+817
-160
lines changed

16 files changed

+817
-160
lines changed

.env

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
VITE_APP_API_URL=#{API_URL}#
2+
VITE_APP_SOCKET_URL=#{SOCKET_URL}#
23
VITE_APP_CURR_ENV=#{CURR_ENV}#
3-
VITE_APP_NET_API_URL=#{NET_API_URL}#
4+
VITE_APP_NET_API_URL=#{NET_API_URL}#
5+
VITE_SESSION_END=#{SESSION_END}#
6+
VITE_SESSION_WARN=#{SESSION_WARN}#

server/.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ SERVER_CURR_ENV=#{CURR_ENV}#
22
SERVER_LOG_PATH=#{LOG_PATH}#
33
SERVER_UPLOAD_PATH=#{UPLOAD_PATH}#
44
SERVER_TARGET_PATH=#{TARGET_PATH}#
5-
SERVER_API_URL=#{NET_API_URL}#
5+
SERVER_API_URL=#{NET_API_URL}#

server/index.js

Lines changed: 222 additions & 44 deletions
Large diffs are not rendered by default.

server/package-lock.json

Lines changed: 36 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
"moment": "^2.29.4",
2222
"path": "^0.12.7",
2323
"recursive-readdir": "^2.2.3",
24-
"simple-git": "^3.27.0"
24+
"simple-git": "^3.27.0",
25+
"uuid": "^11.0.3",
26+
"ws": "^8.18.0"
2527
}
2628
}

server/web.config

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
<configuration>
22
<system.webServer>
33
<handlers>
4-
<add name="StorylinesExpress" path="index.js" verb="*" modules="iisnode" />
4+
<add name="StorylinesExpress" path="index.js" verb="*" modules="iisnode" resourceType="Unspecified" />
55
</handlers>
6+
<webSocket enabled="true" />
67
<rewrite>
78
<rules>
9+
<rule name="WebSocket remove keep-alive header" stopProcessing="true">
10+
<match url="(.*)" />
11+
<serverVariables>
12+
<set name="HTTP_CONNECTION" value="Upgrade" />
13+
</serverVariables>
14+
<action type="Rewrite" url="index.js" />
15+
<conditions logicalGrouping="MatchAny">
16+
<add input="{HTTP_CONNECTION}" pattern="keep-alive, Upgrade" />
17+
<add input="{HTTP_CONNECTION}" pattern="Upgrade, keep-alive" />
18+
</conditions>
19+
</rule>
820
<rule name="sendToNode">
921
<match url="/*" />
1022
<action type="Rewrite" url="index.js" />

src/app.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import { Vue, Watch } from 'vue-property-decorator';
99
import { RouteLocationNormalized } from 'vue-router';
1010
import { useUserStore } from './stores/userStore';
11+
import { useLockStore } from './stores/lockStore';
1112
1213
export default class App extends Vue {
1314
@Watch('$route', { immediate: true })
@@ -24,10 +25,10 @@ export default class App extends Vue {
2425
if (import.meta.env.VITE_APP_CURR_ENV) {
2526
userStore.fetchUserProfile();
2627
}
28+
const lockStore = useLockStore();
29+
lockStore.initConnection(); // start the handshake with the web socket server as soon as the app starts to save time
2730
}
2831
}
29-
30-
3132
</script>
3233

3334
<style lang="scss">

src/components/editor.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ import MetadataContentV from './helpers/metadata-content.vue';
351351
import ConfirmationModalV from './helpers/confirmation-modal.vue';
352352
import HelpPanelV from './help-panel.vue';
353353
import HelpSectionV from './helpers/help-section.vue';
354+
import { useLockStore } from '@/stores/lockStore';
354355
355356
@Options({
356357
components: {
@@ -561,7 +562,7 @@ export default class EditorV extends Vue {
561562
previewConfigs.fr!.slides = previewConfigs.fr!.slides.map((slide) => {
562563
return slide ?? JSON.parse(JSON.stringify(this.defaultBlankSlide));
563564
});
564-
565+
const lockStore = useLockStore();
565566
setTimeout(() => {
566567
const routeData = this.$router.resolve({
567568
name: 'preview',
@@ -570,7 +571,9 @@ export default class EditorV extends Vue {
570571
const previewTab = window.open(routeData.href, '_blank');
571572
(previewTab as Window).props = {
572573
configs: previewConfigs,
573-
configFileStructure: this.configFileStructure
574+
configFileStructure: this.configFileStructure,
575+
secret: lockStore.secret,
576+
timeRemaining: lockStore.timeRemaining
574577
};
575578
}, 5);
576579
}

src/components/helpers/confirmation-modal.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
<template>
22
<vue-final-modal
3+
:clickToClose="false"
4+
:escToClose="false"
35
:modalId="name"
46
class="flex justify-center items-center"
57
content-class="flex flex-col max-w-xl mx-4 p-4 bg-white dark:bg-gray-900 border dark:border-gray-700 rounded-lg space-y-2"
68
>
7-
<h2 slot="header" class="text-lg font-bold">{{ message }}</h2>
9+
<h2 slot="header" :class="messageClass ?? 'text-lg font-bold'">{{ message }}</h2>
810
<div class="w-full flex justify-end">
911
<button class="editor-button confirm-button hover:bg-gray-800" @click.stop="onOk">
1012
{{ $t('editor.confirm') }}
@@ -28,6 +30,7 @@ import { VueFinalModal } from 'vue-final-modal';
2830
export default class MetadataEditorV extends Vue {
2931
@Prop() message!: string;
3032
@Prop() name!: string;
33+
@Prop() messageClass?: string;
3134
3235
onOk(): void {
3336
this.$emit('ok');

src/components/home.vue

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,33 @@
1010
</router-link>
1111
</div>
1212
<div class="relative" style="margin-right: 10%; margin-left: 10%">
13+
<div v-if="showExpired" class="w-full rounded-md bg-red-100 p-2 mt-5">
14+
<span class="flex flex-row items-center">
15+
<svg
16+
version="1.1"
17+
xmlns="http://www.w3.org/2000/svg"
18+
viewBox="0 0 1024 1024"
19+
style="color: rgb(245, 108, 108)"
20+
class="w-10 h-10 pr-2"
21+
>
22+
<path
23+
fill="currentColor"
24+
d="M512,952C269,952,72,755,72,512S269,72,512,72s440,197,440,440S755,952,512,952z M579.7,512l101.6-101.6 c18.7-18.7,18.7-49,0-67.7c-18.7-18.7-49-18.7-67.7,0l0,0L512,444.3L410.4,342.7c-18.7-18.7-49-18.7-67.7,0s-18.7,49,0,67.7 L444.3,512L342.7,613.6c-18.7,18.7-18.7,49,0,67.7c18.7,18.7,49,18.7,67.7,0L512,579.7l101.6,101.6c18.7,18.7,49,18.7,67.7,0 c18.7-18.7,18.7-49,0-67.7L579.7,512z"
25+
></path>
26+
</svg>
27+
{{ $t('editor.session.ended') }}
28+
<button
29+
@click.stop="
30+
() => {
31+
showExpired = false;
32+
}
33+
"
34+
class="editor-button bg-black text-white hover:bg-gray-800 ml-auto"
35+
>
36+
{{ $t('editor.ok') }}
37+
</button>
38+
</span>
39+
</div>
1340
<h2 class="pt-10 text-4xl font-semibold">{{ $t('editor.dashboard') }}</h2>
1441
<div class="text-xl font-semibold text-right pt-2 pb-2">
1542
{{ $t('editor.landing.greeting') }} {{ userName }}!
@@ -163,18 +190,26 @@
163190
</template>
164191

165192
<script lang="ts">
166-
import { Vue } from 'vue-property-decorator';
193+
import { Prop, Vue } from 'vue-property-decorator';
167194
import { Storyline, UserProfile, useUserStore } from '../stores/userStore';
195+
import Message from 'vue-m-message';
168196
169197
export default class HomeV extends Vue {
198+
@Prop({ default: false }) sessionExpired!: boolean; // true if user was redirected here due to session expiring, false otherwise
199+
170200
userStore = useUserStore();
171201
currLang = 'en';
172202
sourceFile = 'index.html#';
173203
profile: UserProfile = {};
204+
showExpired: boolean = false;
174205
175206
mounted(): void {
176207
this.currLang = (this.$route.params.lang as string) || 'en';
177208
this.sourceFile = window.location.href.split('/').find((s) => s.includes('#'));
209+
// If the user was redirected here due to session end, show session end popup.
210+
if (this.sessionExpired) {
211+
this.showExpired = true;
212+
}
178213
this.userStore
179214
.fetchUserProfile()
180215
.then(() => {

0 commit comments

Comments
 (0)