From 5c638990cb381c67438868afad4a7438baaa7587 Mon Sep 17 00:00:00 2001 From: lcduong Date: Tue, 23 Jul 2024 13:46:59 +0700 Subject: [PATCH 1/6] use the same ico with eventyay-talk --- webapp/public/favicon.ico | Bin 15406 -> 15406 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/webapp/public/favicon.ico b/webapp/public/favicon.ico index f87d31458f950dcf5ce2cef33b7459f62f88ef16..c9d25512759f55676cd382e9224cf5adc809e9ec 100644 GIT binary patch literal 15406 zcmeHO+iz4w7#|~l06zF$z+j^$6do|BiTFU`3r{?F2{G_yKoi0X@PI)@}T5bjN{SHGZ6l4o+Ieh zA6?N$tKWhC+O=>axGHT-xAbGN2>jBt5yx1Q6aDz`O^9^`p#S*Voao1fC}@?7LD~62 zPV~2XYG6b^4TEj_bE3DK3p@K6mxG`lUg-$hR-1YLLiIq~PdUQuJe!f;k9C+aC}h#e z<4hT1IfBP0yUP#VB+n-|w#&KoXl_jkMoSIGv^p?akAd0O?rH4e`z|w$6i>b%GpeP2 z7s3yC%vO)C&y2uo&`xZeLG6d22H(s4ERI31oXlD_{rtYP{mpLQa?`J$t(5$;%xNEI z|KBcbgIISk4Fh%SZ0D=c_P;+6g81Y=aIe2DgE*-`E(|D^t}gK;nkul1j}`v>Z~K!C^gN83M~7)@a) z^o?iskJhY)frbrfVBf9ujK7xcUcVLex-A93X3#J{;B^PL zc?q`{4K;#!?dO6(Z~7E-v@5RpM;J}kI4&IlqX00w&bjBEc?{&E9s8hQ@-uvQQG@B{ z;%@32`8=cISps8)Suaw4clBs-zNGzU_V#T2N8R-zXnU8~Liu8$Z9TLY?Ehy=C5(^U zvPHD&t)iAc)*awS5RkyLhX;Sh((zXeqSfz~g#6>f{nock{Cg%5>Yhah2jRJDzuCd#;1u@=uQ4ff2PqKs^kcS`XpR?a!m8ZC?!X zTWfgg95H#G7>B|311LW~TXWve{IzLkv*Gv(Y1E4j249rmS(!uPy0D8kV;Q#Nz^gho(yMF?m%a1(sslD<4 zKhaNbw``#`eu8(8Q2!CuQL7)RqvoOuGs4N5WnTzuo8Ew_T_`)v%l5hGDrsi+9cc?` T3+V&)K7gMG$xB)wXAArbaV>9v literal 15406 zcmeHO3s4hB7(T1*C~ZY+ow4Ik8C#f$j`Aplf?5HgKERHM7IoBE5zwktd}HmzvE`w> z0)&uYQ9vM#L6ZVft2Na+$aH88d6PE;6N@6)$JEZ$UiZYS;ke`yNMbs@o%v>O_x9ia z-*5N+yZ!GDg2q5&p-GbFW3?`a`#LyG^D;}3ElY}tM9jSy$8filXVSgNtWl3 zWA(+I6VX29Ws6d7ef|bK1X)kZqO3QEo&#;gC+8Mg%8NjIM?fSmE(rcfS`d5%0XS~M z_Dv+OVlQ7TWk#)%6o&4T6@}%ENWLhzhy|OMR{B*whtox;*+x~4d>DlE&ICDQT?K(eiI#rxnnKs9X;0a_WK!l=|Q%j<)xPON%%fk z=mmQ>>CUBXv?Yt4gQZ;D`v&m$H;4FotnWw4I6fbh5oP-iyC0zE&>XpEn3|8wz~ctd zkM#%6FO&NJ%lylk(cg8RPRzuEygc?x;`K7R`R}ZV&&FH3NS%_sbUm`ZZQI}+{pz}n zDUza4vn9lNfdjU6BhL&@(qEmln^+g#Gm7){KlVk4KY9ZD>~W6%`|T|6d#xoD6n9!n zV?^101at2^{*B*$Hr*iD6@{X^B{SKb`qg0mQJ;?H?&KfQZ=XKw8g$P58~D2-RFx}o zEg>(9ZX~wJIr{N@kc<)Ia{nXA59*T^M=0?iDGV{Wdi=!wW9J)N9v%Orek`AkmWT7N zZY!RsWW{l$^vGYpJq&go=7GNF!OBw!46sLh4!wp{XV=Fo*l}48jK)`fHLIt(8VdH3 z^SZ`^^HBYUrUSF&jCWg=Rmn-J>UD{(g!0UqH9*&o=Ig~E8uc{kIn;0|eSU_N9^qP) z&d<MF2TO7+FGh#CwJp? zeLdB;>#K}-bxrcco=dc7PaQ$e`NLB*XE!jrn~yBSv+;g=)$1BC27@3Y2=Dx}uG8`N zBxugA-wU_1p0{R;reQ~5vXf7@NQqt{;*%l z4YUSx8!HN24`)EXn;q#JZQFHWR|t_WFbeiB5$Ddnhwi=X&a;QVv%!-U@^R%PSpTzAYMPa1<4!*Z@<~)-86R%Nc@{R3_}BbAkTVuuvuC|v+qjE=P0i{zK`g=CkxTgl5276Zzp%F1 zQ+AjAimH|V(&ETr-!Rx?qpdci{lk3%%9rK!i}H`Yzp>2G_9MyN#lNw&V8YMWOCs-F z&yTT0?+yAgWyO-ON8)>s@w&@?YtQF!d!rY)PgHuk{o2bp-iD^bTMQRI-Z2D%-5GLb z4EUCS=v^%SI&~NSgX=${A8!vel68;DxYvHtf13D1uIU02k?#K zi0*CfvLA_m!g~F9*ktm;gPa*#fpY3d?k@YS`A@W7&WQH7=TC7#$nW4A$7_mH@j@a< z>EX8>;T>)3O8y6RAb#B*;QM#fPHVaA?H`$4*6hXBllHroUo79)GRgn5=HGVwx$j!O z4~VrN5}gQmfSo%}D1-RYg`O)}Q_%Z}W!~FX?gwH|3TerLe&C-UN$BCQ=OAp*mV%Jq zIxAOQ#QV-zQ@`O8SxKbyVb}LF;eNC4!-1}uo`&9=?4{zoAahU4r!kh?Bgfi0>LI{; zhhA8S{Kn&vsjsavK%5`k-Q99{1=c|D-isnDU2qrdPx-3qwYjRA%$F zrWp{|KK>5_I|e;}Ul{mz<$pFa!$pFc~|D1t; E05jD%5dZ)H From ec412bfa7e1fbb7a9126340f6a8afc9795345f33 Mon Sep 17 00:00:00 2001 From: lcduong Date: Tue, 17 Sep 2024 15:07:26 +0700 Subject: [PATCH 2/6] update base path for webapp using basePath from config file --- .../migrations/0066_alter_world_domain.py | 28 +++++++++++++++++++ server/venueless/core/models/world.py | 2 +- server/venueless/settings.py | 7 ++--- webapp/config.js | 5 ++-- webapp/src/main.js | 12 ++++++-- webapp/src/router/index.js | 4 ++- webapp/src/theme.js | 2 +- webapp/vue.config.js | 6 ++-- 8 files changed, 51 insertions(+), 15 deletions(-) create mode 100644 server/venueless/core/migrations/0066_alter_world_domain.py diff --git a/server/venueless/core/migrations/0066_alter_world_domain.py b/server/venueless/core/migrations/0066_alter_world_domain.py new file mode 100644 index 00000000..541011dc --- /dev/null +++ b/server/venueless/core/migrations/0066_alter_world_domain.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2.14 on 2024-09-17 03:37 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0065_chat_mentions"), + ] + + operations = [ + migrations.AlterField( + model_name="world", + name="domain", + field=models.CharField( + blank=True, + max_length=250, + null=True, + unique=True, + validators=[ + django.core.validators.RegexValidator( + regex="^[a-z0-9-.:]+(/[a-zA-Z0-9-_./]*)?$" + ) + ], + ), + ), + ] diff --git a/server/venueless/core/models/world.py b/server/venueless/core/models/world.py index adcf256f..cb7695b4 100644 --- a/server/venueless/core/models/world.py +++ b/server/venueless/core/models/world.py @@ -138,7 +138,7 @@ class World(VersionedModel): unique=True, null=True, blank=True, - validators=[RegexValidator(regex=r"^[a-z0-9-.:]+$")], + validators=[RegexValidator(regex=r"^[a-z0-9-.:]+(/[a-zA-Z0-9-_./]*)?$")], ) locale = models.CharField( max_length=100, diff --git a/server/venueless/settings.py b/server/venueless/settings.py index 304718ce..46bbfd9b 100644 --- a/server/venueless/settings.py +++ b/server/venueless/settings.py @@ -309,10 +309,9 @@ ROOT_URLCONF = "venueless.urls" CORS_ORIGIN_REGEX_WHITELIST = [ - r"^https?://(\w+\.)?eventyay\.com$", # Allow any subdomain of eventyay.com - r"^https?://video\.eventyay\.com(:\d+)?$", # Allow video.eventyay.com with any port - r"^https?://video-dev\.eventyay\.com(:\d+)?$", # Allow video-dev.eventyay.com with any port - r"^https?://wikimania-live\.eventyay\.com(:\d+)?$", # Allow wikimania-live.eventyay.com with any port + r"^https?://([\w\-]+\.)?eventyay\.com$", # Allow any subdomain of eventyay.com + r"^https?://app-test\.eventyay\.com(:\d+)?$", # Allow video-dev.eventyay.com with any port + r"^https?://app\.eventyay\.com(:\d+)?$", # Allow wikimania-live.eventyay.com with any port ] if DEBUG: CORS_ORIGIN_REGEX_WHITELIST = [ diff --git a/webapp/config.js b/webapp/config.js index 616ed23e..74cc3ed2 100644 --- a/webapp/config.js +++ b/webapp/config.js @@ -17,7 +17,7 @@ if (ENV_DEVELOPMENT || !window.venueless) { locales: ['en', 'de', 'pt_BR', 'ar', 'fr', 'es', 'uk', 'ru'], theme: { logo: { - url: '/eventyay-video-logo.svg', + url: '/video/eventyay-video-logo.svg', fitToWidth: false }, colors: { @@ -25,7 +25,8 @@ if (ENV_DEVELOPMENT || !window.venueless) { sidebar: '#2185d0', bbb_background: '#ffffff', } - } + }, + basePath: '/video', } } else { // load from index.html as `window.venueless = {…}` diff --git a/webapp/src/main.js b/webapp/src/main.js index 2b16d074..4a8d86dd 100644 --- a/webapp/src/main.js +++ b/webapp/src/main.js @@ -50,19 +50,25 @@ async function init({token, inviteToken}) { window.vapp = app store.commit('setUserLocale', i18n.resolvedLanguage) store.dispatch('updateUserTimezone', localStorage.userTimezone || moment.tz.guess()) + // Get the path relative to the publicPath + const basePath = config.basePath || '' + let relativePath = location.pathname.replace(basePath, '') + if (!relativePath) { + relativePath = '/' + } - const { route } = router.resolve(location.pathname) + const { route } = router.resolve(relativePath) const anonymousRoomId = route.name === 'standalone:anonymous' ? route.params.roomId : null if (token) { localStorage.token = token - router.replace(location.pathname) + router.replace(relativePath) store.dispatch('login', {token}) } else if (localStorage.token) { store.dispatch('login', {token: localStorage.token}) } else if (inviteToken && anonymousRoomId) { const clientId = uuid() localStorage[`clientId:room:${anonymousRoomId}`] = clientId - router.replace(location.pathname) + router.replace(relativePath) store.dispatch('login', {clientId, inviteToken}) } else if (anonymousRoomId && localStorage[`clientId:room:${anonymousRoomId}`]) { const clientId = localStorage[`clientId:room:${anonymousRoomId}`] diff --git a/webapp/src/router/index.js b/webapp/src/router/index.js index 9d1b7a1f..3ba2992b 100644 --- a/webapp/src/router/index.js +++ b/webapp/src/router/index.js @@ -13,6 +13,8 @@ import Speaker from 'views/schedule/speakers/item' import Exhibitor from 'views/exhibitors/item' import ContactRequests from 'views/contact-requests' import Preferences from 'views/preferences' +import config from 'config' + Vue.use(VueRouter) @@ -240,7 +242,7 @@ const routes = [{ const router = new VueRouter({ mode: 'history', - base: process.env.BASE_URL, + base: config.basePath, routes }) diff --git a/webapp/src/theme.js b/webapp/src/theme.js index d07038d8..53d8cabb 100644 --- a/webapp/src/theme.js +++ b/webapp/src/theme.js @@ -53,7 +53,7 @@ const DEFAULT_COLORS = { } const DEFAULT_LOGO = { - url: '/eventyay-video-logo.svg', + url: '/video/eventyay-video-logo.svg', fitToWidth: false } diff --git a/webapp/vue.config.js b/webapp/vue.config.js index 0c388c8c..4e0338c2 100644 --- a/webapp/vue.config.js +++ b/webapp/vue.config.js @@ -11,12 +11,12 @@ module.exports = { devServer: { host: '0.0.0.0', port: 8880, - public: 'video-dev.eventyay.com', + public: 'app-test.eventyay.com', allowedHosts: [ '.localhost', '.eventyay.com', - 'video-dev.eventyay.com', - 'video.eventyay.com' + 'app-test.eventyay.com', + 'app.eventyay.com' ], }, pwa: { From d8aba6e2e477ca44dbb78c36479a2e20dfbcf88d Mon Sep 17 00:00:00 2001 From: lcduong Date: Mon, 7 Oct 2024 17:42:11 +0700 Subject: [PATCH 3/6] update route to run multiple world at ssame time --- server/venueless/control/views.py | 2 +- webapp/config.js | 7 +- webapp/src/router/index.js | 473 ++++++++++++++++-------------- 3 files changed, 264 insertions(+), 218 deletions(-) diff --git a/server/venueless/control/views.py b/server/venueless/control/views.py index 553864a2..316794c2 100644 --- a/server/venueless/control/views.py +++ b/server/venueless/control/views.py @@ -205,7 +205,7 @@ def get(self, request, *args, **kwargs): action_type="world.adminaccess", data={}, ) - return redirect(f"https://{world.domain}{base_path}/#token={token}") + return redirect(f"https://{world.domain}#token={token}") class FormsetMixin: diff --git a/webapp/config.js b/webapp/config.js index 74cc3ed2..dcab1a12 100644 --- a/webapp/config.js +++ b/webapp/config.js @@ -5,10 +5,13 @@ if (ENV_DEVELOPMENT || !window.venueless) { const hostname = window.location.hostname const wsProtocol = window.location.protocol === 'https:' ? 'wss' : 'ws' const httpProtocol = window.location.protocol + // Extract the world name from the URL path + const pathSegments = window.location.pathname.split('/'); + const worldName = pathSegments.length > 2 ? pathSegments[2] : 'sample'; config = { api: { - base: `${httpProtocol}//${hostname}:8443/api/v1/worlds/sample/`, - socket: `${wsProtocol}://${hostname}:8443/ws/world/sample/`, + base: `${httpProtocol}//${hostname}:8443/api/v1/worlds/${worldName}/`, + socket: `${wsProtocol}://${hostname}:8443/ws/world/${worldName}/`, upload: `${httpProtocol}//${hostname}:8443/storage/upload/`, scheduleImport: `${httpProtocol}//${hostname}:8443/storage/schedule_import/`, feedback: `${httpProtocol}//${hostname}:8443/_feedback/`, diff --git a/webapp/src/router/index.js b/webapp/src/router/index.js index 3ba2992b..b1088228 100644 --- a/webapp/src/router/index.js +++ b/webapp/src/router/index.js @@ -18,227 +18,270 @@ import config from 'config' Vue.use(VueRouter) -const routes = [{ - path: '/standalone/:roomId', - name: 'standalone', - component: () => import(/* webpackChunkName: "standalone" */ 'views/standalone'), - children: [{ - path: 'chat', - name: 'standalone:chat', - component: () => import(/* webpackChunkName: "standalone" */ 'views/standalone/Chat') - }, { - path: 'poll', - name: 'standalone:poll', - component: () => import(/* webpackChunkName: "standalone" */ 'views/standalone/Poll') - }, { - path: 'question', - name: 'standalone:question', - component: () => import(/* webpackChunkName: "standalone" */ 'views/standalone/Question') - }, { - path: 'kiosk', - name: 'standalone:kiosk', - component: () => import(/* webpackChunkName: "standalone" */ 'views/standalone/kiosk') - }, { - path: 'anonymous', - name: 'standalone:anonymous', - component: () => import(/* webpackChunkName: "standalone" */ 'views/standalone/anonymous') - }] -}, { - path: '/rooms/:roomId/presentation/:mode', - redirect(to) { - return { - path: `/standalone/${to.params.roomId}/${to.params.mode}` - } - } -}, { - path: '/', - component: App, - children: [{ - // we can't alias this because vue-router links seem to explode - // manage view gets linked to room url - path: '/', - component: RoomHeader, - children: [{ - path: '', - name: 'home', - component: Room - }] - }, { - path: '/rooms/:roomId', - component: RoomHeader, - props: true, - children: [{ - path: '', - name: 'room', - component: Room - }, { - path: 'manage', - name: 'room:manage', - component: RoomManager - }] - }, { - path: '/channels/:channelId', - name: 'channel', - component: Channel, - props: true - }, { - path: '/schedule', - name: 'schedule', - component: Schedule - }, { - path: '/schedule/talks/:talkId', - name: 'schedule:talk', - component: Talk, - props: true - }, { - path: '/sessions', - name: 'schedule:sessions', - component: Session, - props: true - }, { - path: '/schedule/speakers', - name: 'schedule:speakers', - component: Speakers - }, { - path: '/schedule/speakers/:speakerId', - name: 'schedule:speaker', - component: Speaker, - props: true - }, { - path: '/exhibitors/:exhibitorId', - name: 'exhibitor', - component: Exhibitor, - props: true - }, { - path: '/contact-requests', - name: 'contactRequests', - component: ContactRequests, - props: true - }, { - path: '/preferences', - name: 'preferences', - component: Preferences - }, { - path: '/posters/:posterId', - name: 'poster', - component: () => import(/* webpackChunkName: "posters" */ 'views/posters/item'), - props: true - }, { - path: '/manage-exhibitors', - name: 'exhibitors', - component: () => import(/* webpackChunkName: "exhibitors" */ 'views/exhibitor-manager') - }, { - path: '/manage-exhibitors/:exhibitorId', - name: 'exhibitors:exhibitor', - component: () => import(/* webpackChunkName: "exhibitors" */ 'views/exhibitor-manager/exhibitor'), - props: true - }, { - path: '/manage-posters', - name: 'posters', - component: () => import(/* webpackChunkName: "posters" */ 'views/poster-manager') - }, { - path: '/manage-posters/create', - name: 'posters:create-poster', - component: () => import(/* webpackChunkName: "posters" */ 'views/poster-manager/poster'), - props: { - create: true - } - }, { - path: '/manage-posters/:posterId', - name: 'posters:poster', - component: () => import(/* webpackChunkName: "posters" */ 'views/poster-manager/poster'), - props: true - }, { - path: '/admin', - name: 'admin', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin') - }, { - path: '/admin/users', - name: 'admin:users', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/users') - }, { - path: '/admin/users/:userId', - name: 'admin:user', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/user'), - props: true - }, { - path: '/admin/rooms', - name: 'admin:rooms:index', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/rooms/index') - }, { - path: '/admin/rooms/new/:type?', - name: 'admin:rooms:new', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/rooms/new') - }, { - path: '/admin/rooms/:roomId', - name: 'admin:rooms:item', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/rooms/item'), - props: true - }, { - path: '/admin/announcements', - name: 'admin:announcements', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/announcements'), +const routes = [ + { + path: '/standalone/:roomId', + name: 'standalone', + component: () => import(/* webpackChunkName: "standalone" */ 'views/standalone'), children: [{ - path: ':announcementId', - name: 'admin:announcements:item', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/announcements/item'), - props: true - }] - }, { - path: '/admin/kiosks', - name: 'admin:kiosks:index', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/kiosks/index') - }, { - path: '/admin/kiosks/new', - name: 'admin:kiosks:new', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/kiosks/new') - }, { - path: '/admin/kiosks/:kioskId', - name: 'admin:kiosks:item', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/kiosks/item'), - props: true - }, { - path: '/admin/config', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config'), - children: [{ - path: '', - name: 'admin:config', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/main') - }, { - path: 'schedule', - name: 'admin:config:schedule', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/schedule') - }, { - path: 'theme', - name: 'admin:config:theme', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/theme') - }, { - path: 'permissions', - name: 'admin:config:permissions', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/permissions') + path: 'chat', + name: 'standalone:chat', + component: () => import(/* webpackChunkName: "standalone" */ 'views/standalone/Chat') }, { - path: 'token-generator', - name: 'admin:config:token-generator', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/token-generator') + path: 'poll', + name: 'standalone:poll', + component: () => import(/* webpackChunkName: "standalone" */ 'views/standalone/Poll') }, { - path: 'registration', - name: 'admin:config:registration', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/registration') + path: 'question', + name: 'standalone:question', + component: () => import(/* webpackChunkName: "standalone" */ 'views/standalone/Question') }, { - path: 'privacy', - name: 'admin:config:privacy', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/privacy') + path: 'kiosk', + name: 'standalone:kiosk', + component: () => import(/* webpackChunkName: "standalone" */ 'views/standalone/kiosk') }, { - path: 'audit-log', - name: 'admin:config:audit-log', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/audit-log') - }, { - path: 'reports', - name: 'admin:config:reports', - component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/reports') + path: 'anonymous', + name: 'standalone:anonymous', + component: () => import(/* webpackChunkName: "standalone" */ 'views/standalone/anonymous') }] - }] -}] + }, + { + path: '/rooms/:roomId/presentation/:mode', + redirect(to) { + return { + path: `/standalone/${to.params.roomId}/${to.params.mode}` + } + } + }, + { + path: `/:worldName`, + component: App, + props: true, + children: [ + { + // we can't alias this because vue-router links seem to explode + // manage view gets linked to room url + path: '', + component: RoomHeader, + children: [{ + path: '', + name: 'home', + component: Room + }] + }, + { + path: 'rooms/:roomId', + component: RoomHeader, + props: true, + children: [{ + path: '', + name: 'room', + component: Room + }, { + path: 'manage', + name: 'room:manage', + component: RoomManager + }] + }, + { + path: 'channels/:channelId', + name: 'channel', + component: Channel, + props: true + }, + { + path: 'schedule', + name: 'schedule', + component: Schedule + }, + { + path: 'schedule/talks/:talkId', + name: 'schedule:talk', + component: Talk, + props: true + }, + { + path: 'sessions', + name: 'schedule:sessions', + component: Session, + props: true + }, + { + path: 'schedule/speakers', + name: 'schedule:speakers', + component: Speakers + }, + { + path: 'schedule/speakers/:speakerId', + name: 'schedule:speaker', + component: Speaker, + props: true + }, + { + path: 'exhibitors/:exhibitorId', + name: 'exhibitor', + component: Exhibitor, + props: true + }, + { + path: 'contact-requests', + name: 'contactRequests', + component: ContactRequests, + props: true + }, + { + path: 'preferences', + name: 'preferences', + component: Preferences + }, + { + path: 'posters/:posterId', + name: 'poster', + component: () => import(/* webpackChunkName: "posters" */ 'views/posters/item'), + props: true + }, + { + path: 'manage-exhibitors', + name: 'exhibitors', + component: () => import(/* webpackChunkName: "exhibitors" */ 'views/exhibitor-manager') + }, + { + path: 'manage-exhibitors/:exhibitorId', + name: 'exhibitors:exhibitor', + component: () => import(/* webpackChunkName: "exhibitors" */ 'views/exhibitor-manager/exhibitor'), + props: true + }, + { + path: 'manage-posters', + name: 'posters', + component: () => import(/* webpackChunkName: "posters" */ 'views/poster-manager') + }, + { + path: 'manage-posters/create', + name: 'posters:create-poster', + component: () => import(/* webpackChunkName: "posters" */ 'views/poster-manager/poster'), + props: { + create: true + } + }, + { + path: 'manage-posters/:posterId', + name: 'posters:poster', + component: () => import(/* webpackChunkName: "posters" */ 'views/poster-manager/poster'), + props: true + }, + { + path: 'admin', + name: 'admin', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin') + }, + { + path: 'admin/users', + name: 'admin:users', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/users') + }, + { + path: 'admin/users/:userId', + name: 'admin:user', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/user'), + props: true + }, + { + path: 'admin/rooms', + name: 'admin:rooms:index', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/rooms/index') + }, + { + path: 'admin/rooms/new/:type?', + name: 'admin:rooms:new', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/rooms/new') + }, + { + path: 'admin/rooms/:roomId', + name: 'admin:rooms:item', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/rooms/item'), + props: true + }, + { + path: 'admin/announcements', + name: 'admin:announcements', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/announcements'), + children: [{ + path: ':announcementId', + name: 'admin:announcements:item', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/announcements/item'), + props: true + }] + }, + { + path: 'admin/kiosks', + name: 'admin:kiosks:index', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/kiosks/index') + }, + { + path: 'admin/kiosks/new', + name: 'admin:kiosks:new', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/kiosks/new') + }, + { + path: 'admin/kiosks/:kioskId', + name: 'admin:kiosks:item', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/kiosks/item'), + props: true + }, + { + path: 'admin/config', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config'), + children: [{ + path: '', + name: 'admin:config', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/main') + }, + { + path: 'schedule', + name: 'admin:config:schedule', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/schedule') + }, + { + path: 'theme', + name: 'admin:config:theme', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/theme') + }, + { + path: 'permissions', + name: 'admin:config:permissions', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/permissions') + }, + { + path: 'token-generator', + name: 'admin:config:token-generator', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/token-generator') + }, + { + path: 'registration', + name: 'admin:config:registration', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/registration') + }, + { + path: 'privacy', + name: 'admin:config:privacy', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/privacy') + }, + { + path: 'audit-log', + name: 'admin:config:audit-log', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/audit-log') + }, + { + path: 'reports', + name: 'admin:config:reports', + component: () => import(/* webpackChunkName: "admin" */ 'views/admin/config/reports') + } + ] + } + ] + } +] const router = new VueRouter({ mode: 'history', From 016791f57e127d414eb756c813336039c6ade8f4 Mon Sep 17 00:00:00 2001 From: lcduong Date: Mon, 7 Oct 2024 19:01:21 +0700 Subject: [PATCH 4/6] fix upload avatar, default theme --- server/venueless/storage/urls.py | 4 ++-- server/venueless/storage/views.py | 4 ++-- webapp/config.js | 4 ++-- webapp/src/theme.js | 35 ++++++++++++++++++++++++------- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/server/venueless/storage/urls.py b/server/venueless/storage/urls.py index e7efd7d1..7fd44223 100644 --- a/server/venueless/storage/urls.py +++ b/server/venueless/storage/urls.py @@ -3,9 +3,9 @@ from . import views urlpatterns = [ - path("upload/", views.UploadView.as_view(), name="upload"), + path("/upload/", views.UploadView.as_view(), name="upload"), path( - "schedule_import/", + "/schedule_import/", views.ScheduleImportView.as_view(), name="schedule_import", ), diff --git a/server/venueless/storage/views.py b/server/venueless/storage/views.py index 857f3ea7..77c33ffe 100644 --- a/server/venueless/storage/views.py +++ b/server/venueless/storage/views.py @@ -34,8 +34,8 @@ def dispatch(self, request, *args, **kwargs): @cached_property def world(self): - world_domain = re.sub(r":\d+$", "", self.request.get_host()) - return get_object_or_404(World, domain=world_domain) + world_id = self.kwargs.get('world_id', None) + return get_object_or_404(World, id=world_id) @cached_property def user(self): diff --git a/webapp/config.js b/webapp/config.js index dcab1a12..de480f7d 100644 --- a/webapp/config.js +++ b/webapp/config.js @@ -12,8 +12,8 @@ if (ENV_DEVELOPMENT || !window.venueless) { api: { base: `${httpProtocol}//${hostname}:8443/api/v1/worlds/${worldName}/`, socket: `${wsProtocol}://${hostname}:8443/ws/world/${worldName}/`, - upload: `${httpProtocol}//${hostname}:8443/storage/upload/`, - scheduleImport: `${httpProtocol}//${hostname}:8443/storage/schedule_import/`, + upload: `${httpProtocol}//${hostname}:8443/storage/${worldName}/upload/`, + scheduleImport: `${httpProtocol}//${hostname}:8443/storage/${worldName}/schedule_import/`, feedback: `${httpProtocol}//${hostname}:8443/_feedback/`, }, defaultLocale: 'en', diff --git a/webapp/src/theme.js b/webapp/src/theme.js index 53d8cabb..0f58179b 100644 --- a/webapp/src/theme.js +++ b/webapp/src/theme.js @@ -151,12 +151,31 @@ export function computeForegroundSidebarColor(colors) { } export async function getThemeConfig() { - const themeUrl = config.api.base + 'theme' - const response = await (await fetch(themeUrl, { - method: 'GET', - headers: { - 'Content-Type': 'application/json' - } - })).json() - return response + const themeUrl = config.api.base + 'theme'; + const response = await fetch(themeUrl, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }); + + let themeConfig; + if (response.ok) { + const data = await response.json(); + themeConfig = { + colors: data.colors || configColors, + logo: Object.assign({}, DEFAULT_LOGO, data.logo), + streamOfflineImage: data.streamOfflineImage, + identicons: Object.assign({}, DEFAULT_IDENTICONS, data.identicons), + }; + } else { + console.error("Failed to fetch theme config, set default:", response.statusText); + themeConfig = { + colors: configColors, + logo: Object.assign({}, DEFAULT_LOGO, config.theme?.logo), + streamOfflineImage: config.theme?.streamOfflineImage, + identicons: Object.assign({}, DEFAULT_IDENTICONS, config.theme?.identicons), + }; + } + return themeConfig; } From 1a53e7284e00f2ad3e069e377ebd243bc91665a5 Mon Sep 17 00:00:00 2001 From: lcduong Date: Wed, 9 Oct 2024 11:51:51 +0700 Subject: [PATCH 5/6] correct link when click to logo --- webapp/src/components/AppBar.vue | 2 +- webapp/src/components/RoomsSidebar.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp/src/components/AppBar.vue b/webapp/src/components/AppBar.vue index b73a8e20..3ddd63a3 100644 --- a/webapp/src/components/AppBar.vue +++ b/webapp/src/components/AppBar.vue @@ -1,7 +1,7 @@