Skip to content

Commit

Permalink
Add sessions to sidebar and show filter and export options (#215)
Browse files Browse the repository at this point in the history
* Add sessions to sidebar and show filter and export options

* update translate for sessions
  • Loading branch information
odkhang authored Aug 8, 2024
1 parent 695e4e1 commit e329d2c
Show file tree
Hide file tree
Showing 15 changed files with 545 additions and 2 deletions.
1 change: 1 addition & 0 deletions server/venueless/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
path("worlds/<str:world_id>/", include(world_router.urls)),
path("worlds/<str:world_id>/theme", views.WorldThemeView.as_view()),
path("worlds/<str:world_id>/favourite-talk/", views.UserFavouriteView.as_view()),
path("worlds/<str:world_id>/export-talk", views.ExportView.as_view()),
]
28 changes: 28 additions & 0 deletions server/venueless/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from contextlib import suppress
from urllib.parse import urlparse
import jwt
import requests

from asgiref.sync import async_to_sync
from django.core import exceptions
Expand Down Expand Up @@ -165,6 +166,33 @@ def get_uid_from_token(request, world_id):
return token_decode.get("uid")


class ExportView(APIView):

permission_classes = []

@staticmethod
def get(request, *args, **kwargs):
export_type = request.GET.get('export_type', 'json')
world = get_object_or_404(World, id=kwargs["world_id"])
talk_config = world.config.get("pretalx")
user = User.objects.filter(token_id=request.user)
talk_base_url = talk_config.get('domain') + "/" + talk_config.get('event') + "/schedule/export/"
export_endpoint = 'schedule.' + export_type
talk_url = talk_base_url + export_endpoint
if 'my' in export_type and user:
user_state = user.first().client_state
if user_state and user_state.get('schedule') and user_state.get('schedule').get('favs'):
talk_list = user_state.get('schedule').get('favs')
talk_list_str = ','.join(talk_list)
export_endpoint = 'schedule-my.' + export_type.replace('my','')
talk_url = talk_base_url + export_endpoint + "?talks=" + talk_list_str
header = {
"Content-Type": "application/json"
}
response = requests.get(talk_url, headers=header)
return Response(response.content.decode("utf-8"))


def get_domain(path):
if not path:
return ""
Expand Down
1 change: 1 addition & 0 deletions webapp/src/components/RoomsSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ transition(name="sidebar")
.global-links(role="group", aria-label="pages")
router-link.room(v-if="roomsByType.page.includes(rooms[0])", :to="{name: 'home'}", v-html="$emojify(rooms[0].name)")
router-link.room(:to="{name: 'schedule'}", v-if="!!world.pretalx && (world.pretalx.url || world.pretalx.domain)") {{ $t('RoomsSidebar:schedule:label') }}
router-link.room(:to="{name: 'schedule:sessions'}", v-if="!!world.pretalx && (world.pretalx.url || world.pretalx.domain)") {{ $t('RoomsSidebar:session:label') }}
router-link.room(:to="{name: 'schedule:speakers'}", v-if="!!world.pretalx && (world.pretalx.url || world.pretalx.domain)") {{ $t('RoomsSidebar:speaker:label') }}
router-link.room(v-for="page of roomsByType.page", v-if="page !== rooms[0]", :to="{name: 'room', params: {roomId: page.id}}", v-html="$emojify(page.name)")
.group-title#stages-title(v-if="roomsByType.stage.length || hasPermission('world:rooms.create.stage')")
Expand Down
1 change: 1 addition & 0 deletions webapp/src/locales/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@
"RoomsSidebar:schedule:label": "الجدول",
"RoomsSidebar:speaker:label": "المتحدثين",
"RoomsSidebar:stages-headline:text": "المراحل",
"RoomsSidebar:session:label": "الجلسات",
"RoomsSidebar:users-tooltip:few": "بعض الأشخاص حاليًا داخل هذه الغرفة",
"RoomsSidebar:users-tooltip:many": "العديد من المستخدمين حاليًا داخل هذه الغرفة",
"Roulette:connecting:text": "لقد وجدنا شخصًا! جاري الاتصال …",
Expand Down
1 change: 1 addition & 0 deletions webapp/src/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@
"RoomsSidebar:posters-headline:text": "Plakate",
"RoomsSidebar:posters-manage:label": "Verwalten",
"RoomsSidebar:schedule:label": "Zeitplan",
"RoomsSidebar:session:label": "Sitzungen",
"RoomsSidebar:speaker:label": "Sprecher",
"RoomsSidebar:stages-headline:text": "Bühnen",
"RoomsSidebar:users-tooltip:few": "Einige Leute sind derzeit in diesem Raum",
Expand Down
1 change: 1 addition & 0 deletions webapp/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@
"RoomsSidebar:posters-headline:text": "Posters",
"RoomsSidebar:posters-manage:label": "Manage",
"RoomsSidebar:schedule:label": "Schedule",
"RoomsSidebar:session:label": "Sessions",
"RoomsSidebar:speaker:label": "Speakers",
"RoomsSidebar:stages-headline:text": "Stages",
"RoomsSidebar:users-tooltip:few": "Some people are currently inside this room",
Expand Down
1 change: 1 addition & 0 deletions webapp/src/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@
"RoomsSidebar:posters-headline:text": "Pósters",
"RoomsSidebar:posters-manage:label": "Gestionar",
"RoomsSidebar:schedule:label": "Programa",
"RoomsSidebar:session:label": "Sesiones",
"RoomsSidebar:speaker:label": "Ponentes",
"RoomsSidebar:stages-headline:text": "Escenarios",
"RoomsSidebar:users-tooltip:few": "Pocas personas están en esta sala en este momento",
Expand Down
1 change: 1 addition & 0 deletions webapp/src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@
"RoomsSidebar:posters-headline:text": "Affiches",
"RoomsSidebar:posters-manage:label": "Gérer",
"RoomsSidebar:schedule:label": "Programme",
"RoomsSidebar:session:label": "Séances",
"RoomsSidebar:speaker:label": "Intervenants",
"RoomsSidebar:stages-headline:text": "Scènes",
"RoomsSidebar:users-tooltip:few": "Quelques personnes sont actuellement dans cette salle",
Expand Down
1 change: 1 addition & 0 deletions webapp/src/locales/pt_BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@
"RoomsSidebar:posters-headline:text": "Pôsteres",
"RoomsSidebar:posters-manage:label": "Gerenciar",
"RoomsSidebar:schedule:label": "Programa",
"RoomsSidebar:session:label": "Sessões",
"RoomsSidebar:speaker:label": "Palestrantes",
"RoomsSidebar:stages-headline:text": "Palcos",
"RoomsSidebar:users-tooltip:few": "Algumas pessoas estão nesta sala no momento",
Expand Down
1 change: 1 addition & 0 deletions webapp/src/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@
"RoomsSidebar:posters-headline:text": "Постеры",
"RoomsSidebar:posters-manage:label": "Управление",
"RoomsSidebar:schedule:label": "Расписание",
"RoomsSidebar:session:label": "Сессии",
"RoomsSidebar:speaker:label": "Спикеры",
"RoomsSidebar:stages-headline:text": "Сцены",
"RoomsSidebar:users-tooltip:few": "Несколько человек в данный момент находятся в этой комнате",
Expand Down
1 change: 1 addition & 0 deletions webapp/src/locales/uk.json
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@
"RoomsSidebar:posters-headline:text": "Постери",
"RoomsSidebar:posters-manage:label": "Управління",
"RoomsSidebar:schedule:label": "Розклад",
"RoomsSidebar:session:label": "Сеанси",
"RoomsSidebar:speaker:label": "Доповідачі",
"RoomsSidebar:stages-headline:text": "Сцени",
"RoomsSidebar:users-tooltip:few": "Кілька людей наразі знаходяться в цій кімнаті",
Expand Down
6 changes: 6 additions & 0 deletions webapp/src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import RoomManager from 'views/rooms/manage'
import Channel from 'views/channels/item'
import Schedule from 'views/schedule'
import Talk from 'views/schedule/talks/item'
import Session from 'views/schedule/sessions'
import Speakers from 'views/schedule/speakers'
import Speaker from 'views/schedule/speakers/item'
import Exhibitor from 'views/exhibitors/item'
Expand Down Expand Up @@ -87,6 +88,11 @@ const routes = [{
name: 'schedule:talk',
component: Talk,
props: true
}, {
path: '/sessions',
name: 'schedule:sessions',
component: Session,
props: true
}, {
path: '/schedule/speakers',
name: 'schedule:speakers',
Expand Down
161 changes: 161 additions & 0 deletions webapp/src/views/schedule/export-select.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
<template>
<div class="custom-dropdown" ref="dropdown">

Check warning on line 2 in webapp/src/views/schedule/export-select.vue

View workflow job for this annotation

GitHub Actions / build

'ref' should be on a new line

Check warning on line 2 in webapp/src/views/schedule/export-select.vue

View workflow job for this annotation

GitHub Actions / build

Attribute "ref" should go before "class"
<button @click="isOpen = !isOpen">
{{ selectedOption || 'Add to Calendar' }}
</button>
<div v-if="isOpen" class="dropdown-options">

Check warning on line 6 in webapp/src/views/schedule/export-select.vue

View workflow job for this annotation

GitHub Actions / build

'class' should be on a new line
<div class="dropdown-item"

Check warning on line 7 in webapp/src/views/schedule/export-select.vue

View workflow job for this annotation

GitHub Actions / build

Expected " " character, but found "\t" character

Check warning on line 7 in webapp/src/views/schedule/export-select.vue

View workflow job for this annotation

GitHub Actions / build

'class' should be on a new line
v-for="option in options"

Check warning on line 8 in webapp/src/views/schedule/export-select.vue

View workflow job for this annotation

GitHub Actions / build

Expected " " character, but found "\t" character

Check warning on line 8 in webapp/src/views/schedule/export-select.vue

View workflow job for this annotation

GitHub Actions / build

Attribute "v-for" should go before "class"
:key="option.id"

Check warning on line 9 in webapp/src/views/schedule/export-select.vue

View workflow job for this annotation

GitHub Actions / build

Expected " " character, but found "\t" character

Check warning on line 9 in webapp/src/views/schedule/export-select.vue

View workflow job for this annotation

GitHub Actions / build

Attribute ":key" should go before "class"
@click="selectOption(option)"

Check warning on line 10 in webapp/src/views/schedule/export-select.vue

View workflow job for this annotation

GitHub Actions / build

Expected " " character, but found "\t" character
@mouseover="setHoveredOption(option)"
@mouseleave="clearHoveredOption(option)"
>
<div class="item-text">{{ option.label }}</div>
<img class="default-image" v-if="qrCodes[option.id]" :src="qrCodes[option.id]" alt="QR Code" />
<transition name="fade">
<div v-if="hoveredOption === option" class="qr-popup">
<img :src="qrCodes[option.id]" alt="QR Code" />
</div>
</transition>
</div>
</div>
</div>
</template>

<script>
import QRCode from 'qrcode';
import config from 'config'
export default {
props: ['options'],
mounted() {
document.addEventListener('click', this.outsideClick);
},
beforeDestroy() {
document.removeEventListener('click', this.outsideClick);
},
data() {
return {
isOpen: false,
selectedOption: null,
hoveredOption: null,
qrCodes: {}
};
},
created() {
this.options.forEach(option => {
this.generateQRCode(option);
});
},
methods: {
selectOption(option) {
this.selectedOption = option.label;
this.isOpen = false;
this.$emit('input', option);
},
outsideClick(event) {
const dropdown = this.$refs.dropdown;
if (!dropdown.contains(event.target)) {
this.isOpen = false;
}
},
generateQRCode(option) {
if (!['ics', 'xml', 'myics', 'myxml'].includes(option.id)) {
return;
}
const url = config.api.base + 'export-talk?export_type=' + option.id
QRCode.toDataURL(url, { scale: 1 }, (err, url) => {
if (!err) this.qrCodes[option.id] = url;
});
},
setHoveredOption(option) {
if (['ics', 'xml', 'myics', 'myxml'].includes(option.id)) {
this.hoveredOption = option;
} else {
this.hoveredOption = null;
}
},
clearHoveredOption(option) {
if (this.hoveredOption === option) {
this.hoveredOption = null;
}
},
}
};
</script>

<style>
.custom-dropdown {
position: relative;
display: inline-block;
z-index: 100;
align-content: center;
}
@media screen and (min-width: 480px) {
.custom-dropdown {
margin-right: 100px;
}
}
.custom-dropdown button {
border: none;
height: 32px;
border-radius: 2px;
}
.dropdown-options {
position: absolute;
background-color: #f9f9f9;
min-width: 180px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
.dropdown-options .dropdown-item {
display: flex;
justify-content: space-between;
}
.dropdown-options .dropdown-item .item-text {
align-self: flex-end;
}
.dropdown-options div {
color: black;
padding: 2px 2px;
text-decoration: none;
display: block;
}
.dropdown-options div:hover {
background-color: #f1f1f1;
}
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
.qr-popup {
position: absolute;
right: 100%;
top: 0;
padding: 10px;
background: white;
border: 1px solid #ccc;
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.1);
}
.qr-popup img {
width: 150px; /* Adjust as needed */
height: 150px; /* Adjust as needed */
}
.dropdown-options .dropdown-item .default-image {
width: 20px; /* Adjust as needed */
height: 20px; /* Adjust as needed */
align-self: flex-end;
}
</style>
Loading

0 comments on commit e329d2c

Please sign in to comment.