diff --git a/src/api/group.js b/src/api/group.js index da6d7ef4..589fa233 100644 --- a/src/api/group.js +++ b/src/api/group.js @@ -702,6 +702,33 @@ const groupReq = { getGroupCalendar(groupId) { return request(`calendar/${groupId}`, { method: 'GET' + }).then((json) => { + const args = { + json, + params: { + groupId + } + }; + return args; + }); + }, + + /** + * @param {{ + groupId: string, + eventId: string + }} params + * @return { Promise<{json: any, params}> } + */ + getGroupCalendarEvent(params) { + return request(`calendar/${params.groupId}/${params.eventId}`, { + method: 'GET' + }).then((json) => { + const args = { + json, + params + }; + return args; }); }, diff --git a/src/app.scss b/src/app.scss index 1a1a20ff..c09dbc81 100644 --- a/src/app.scss +++ b/src/app.scss @@ -428,6 +428,10 @@ hr.x-vertical-divider { border-radius: 2px; } +.x-friend-item-no-hover:hover { + background: unset !important; +} + .x-friend-item-border:hover { border-top-left-radius: 25px; border-top-right-radius: 5px; diff --git a/src/components/dialogs/GroupDialog/GroupDialog.vue b/src/components/dialogs/GroupDialog/GroupDialog.vue index e3bc3384..db3bb0aa 100644 --- a/src/components/dialogs/GroupDialog/GroupDialog.vue +++ b/src/components/dialogs/GroupDialog/GroupDialog.vue @@ -546,6 +546,44 @@ > +
+
+ {{ t('dialog.group.info.upcoming_events') }} + + - +
+
+
+
+ {{ t('dialog.group.info.past_events') }} + + - +
+
{{ t('dialog.group.info.members') }} @@ -1147,7 +1185,7 @@ View, Warning } from '@element-plus/icons-vue'; - import { nextTick, reactive, ref, watch } from 'vue'; + import { computed, nextTick, reactive, ref, watch } from 'vue'; import { ElMessage, ElMessageBox } from 'element-plus'; import { storeToRefs } from 'pinia'; import { useI18n } from 'vue-i18n'; @@ -1173,6 +1211,7 @@ import { getNextDialogIndex } from '../../../shared/utils/base/ui'; import { groupRequest } from '../../../api'; + import GroupCalendarEventCard from '../../../views/Tools/components/GroupCalendarEventCard.vue'; import GroupPostEditDialog from './GroupPostEditDialog.vue'; import PreviousInstancesGroupDialog from '../PreviousInstancesDialog/PreviousInstancesGroupDialog.vue'; @@ -1235,6 +1274,28 @@ roleId: '' }); + const pastCalenderEvents = computed(() => { + if (!groupDialog.value.calendar) { + return []; + } + const now = Date.now(); + return groupDialog.value.calendar.filter((event) => { + const eventEnd = new Date(event.endsAt).getTime(); + return eventEnd < now; + }); + }); + + const upcomingCalenderEvents = computed(() => { + if (!groupDialog.value.calendar) { + return []; + } + const now = Date.now(); + return groupDialog.value.calendar.filter((event) => { + const eventEnd = new Date(event.endsAt).getTime(); + return eventEnd >= now; + }); + }); + watch( () => groupDialog.value.loading, () => { @@ -1764,4 +1825,31 @@ ...obj }; } + + function updateFollowingCalendarData(event) { + const calendar = groupDialog.value.calendar; + for (let i = 0; i < calendar.length; i++) { + if (calendar[i].id === event.id) { + calendar[i] = { + ...calendar[i], + ...event + }; + break; + } + } + } + diff --git a/src/localization/en.json b/src/localization/en.json index 5f896d9c..b75e6d08 100644 --- a/src/localization/en.json +++ b/src/localization/en.json @@ -315,7 +315,7 @@ }, "prompt": { "title": "Mutual Friend Graph", - "message": "No cached mutual friend graph data was found. Start fetching now?\\nThis may take a while, we will notify you when it is finishes", + "message": "No cached mutual friend graph data was found. Start fetching now? This may take a while, we will notify you when it is finishes", "confirm": "Start Fetch", "cancel": "Maybe Later" }, @@ -1229,7 +1229,9 @@ "role_updated_at": "Updated At:", "role_created_at": "Created At:", "role_permissions": "Permissions:", - "last_visited": "Last Visited" + "last_visited": "Last Visited", + "past_events": "Past Events", + "upcoming_events": "Upcoming Events" }, "posts": { "header": "Posts", diff --git a/src/stores/group.js b/src/stores/group.js index 77773da6..c51de98f 100644 --- a/src/stores/group.js +++ b/src/stores/group.js @@ -45,6 +45,7 @@ export const useGroupStore = defineStore('Group', () => { announcement: {}, posts: [], postsFiltered: [], + calendar: [], members: [], memberSearch: '', memberSearchResults: [], @@ -141,6 +142,7 @@ export const useGroupStore = defineStore('Group', () => { D.galleries = {}; D.members = []; D.memberFilter = groupDialogFilterOptions.everyone; + D.calendar = []; groupRequest .getCachedGroup({ groupId @@ -461,12 +463,45 @@ export const useGroupStore = defineStore('Group', () => { }); } }); + groupRequest.getGroupCalendar(groupId).then((args) => { + if (groupDialog.value.id === args.params.groupId) { + D.calendar = args.json.results; + for (const event of D.calendar) { + applyGroupEvent(event); + // fetch again for isFollowing + groupRequest + .getGroupCalendarEvent({ + groupId, + eventId: event.id + }) + .then((args) => { + Object.assign( + event, + applyGroupEvent(args.json) + ); + }); + } + } + }); } nextTick(() => (D.isGetGroupDialogGroupLoading = false)); return args; }); } + function applyGroupEvent(event) { + return { + userInterest: { + createdAt: null, + isFollowing: false, + updatedAt: null + }, + ...event, + title: replaceBioSymbols(event.title), + description: replaceBioSymbols(event.description) + }; + } + async function updateInGameGroupOrder() { inGameGroupOrder.value = []; try { @@ -1102,6 +1137,7 @@ export const useGroupStore = defineStore('Group', () => { handleGroupRepresented, showModerateGroupDialog, showGroupMemberModerationDialog, - onGroupLeft + onGroupLeft, + applyGroupEvent }; }); diff --git a/src/views/Tools/components/GroupCalendarEventCard.vue b/src/views/Tools/components/GroupCalendarEventCard.vue index 032f29d2..e5ffa690 100644 --- a/src/views/Tools/components/GroupCalendarEventCard.vue +++ b/src/views/Tools/components/GroupCalendarEventCard.vue @@ -77,7 +77,7 @@ import { useGroupStore } from '../../../stores'; const { t } = useI18n(); - const { cachedGroups, showGroupDialog } = useGroupStore(); + const { cachedGroups } = useGroupStore(); const props = defineProps({ event: { @@ -100,7 +100,7 @@ } }); - const emit = defineEmits(['update-following-calendar-data']); + const emit = defineEmits(['update-following-calendar-data', 'click-action']); const showGroupName = computed(() => props.mode === 'timeline'); @@ -182,7 +182,7 @@ const capitalizeFirst = (str) => str?.charAt(0).toUpperCase() + str?.slice(1); const onGroupClick = () => { - showGroupDialog(props.event.ownerId); + emit('click-action'); }; @@ -203,6 +203,10 @@ flex: 0 0 280px; max-width: 280px; } + &.group-dialog-grid-card { + flex: 0 0 320px; + max-width: 320px; + } :deep(.el-card__body) { overflow: visible; } diff --git a/src/views/Tools/dialogs/GroupCalendarDialog.vue b/src/views/Tools/dialogs/GroupCalendarDialog.vue index 0511a51b..7efb9b1d 100644 --- a/src/views/Tools/dialogs/GroupCalendarDialog.vue +++ b/src/views/Tools/dialogs/GroupCalendarDialog.vue @@ -36,7 +36,8 @@ mode="timeline" :is-following="isEventFollowing(value.id)" :card-class="{ 'grouped-card': timeGroup.events.length > 1 }" - @update-following-calendar-data="updateFollowingCalendarData" /> + @update-following-calendar-data="updateFollowingCalendarData" + @click-action="showGroupDialog(value.ownerId)" />
@@ -99,6 +100,7 @@ mode="grid" :is-following="isEventFollowing(event.id)" @update-following-calendar-data="updateFollowingCalendarData" + @click-action="showGroupDialog(event.ownerId)" card-class="grid-card" />
@@ -131,7 +133,7 @@ import GroupCalendarEventCard from '../components/GroupCalendarEventCard.vue'; - const { cachedGroups } = useGroupStore(); + const { cachedGroups, applyGroupEvent, showGroupDialog } = useGroupStore(); const { t } = useI18n(); @@ -341,8 +343,7 @@ try { const response = await groupRequest.getFollowingGroupCalendars(dayjs(selectedDay.value).toISOString()); response.results.forEach((event) => { - event.title = replaceBioSymbols(event.title); - event.description = replaceBioSymbols(event.description); + applyGroupEvent(event); }); followingCalendar.value = response.results; } catch (error) {