Skip to content

Commit

Permalink
BC-7823 - implement rooms page (#3370)
Browse files Browse the repository at this point in the history
  • Loading branch information
uidp authored Aug 29, 2024
1 parent 5ab97ff commit cd28aa1
Show file tree
Hide file tree
Showing 17 changed files with 2,992 additions and 168 deletions.
1 change: 1 addition & 0 deletions config/webpack/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ module.exports = {
"@feature-render-html": getDir("src/modules/feature/render-html"),
"@feature-news-form": getDir("src/modules/feature/news-form"),
"@feature-media-shelf": getDir("src/modules/feature/media-shelf"),
"@feature-room": getDir("src/modules/feature/room"),
"@ui-alert": getDir("src/modules/ui/alert"),
"@ui-board": getDir("src/modules/ui/board"),
"@ui-chip": getDir("src/modules/ui/chip"),
Expand Down
2,903 changes: 2,752 additions & 151 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 1 addition & 9 deletions src/layouts/LoggedIn.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
createTestingVuetify,
} from "@@/tests/test-utils/setup";
import { mount } from "@vue/test-utils";
import { h, nextTick } from "vue";
import { h } from "vue";
import { VApp } from "vuetify/lib/components/index.mjs";
import NewLoggedIn from "./LoggedIn.layout.vue";

Expand Down Expand Up @@ -86,8 +86,6 @@ const defineWindowWidth = (width: number) => {
describe("newLoggedIn", () => {
it("should render correctly", async () => {
const { wrapper } = setup();
await nextTick();
await nextTick();

expect(wrapper.exists()).toBe(true);
});
Expand All @@ -96,8 +94,6 @@ describe("newLoggedIn", () => {
defineWindowWidth(1564);
const sidebarExpanded = true;
const { wrapper } = setup();
await nextTick();
await nextTick();
const sidebar = wrapper.find("nav");

if (!sidebarExpanded)
Expand All @@ -108,8 +104,6 @@ describe("newLoggedIn", () => {
defineWindowWidth(564);
const sidebarExpanded = true;
const { wrapper } = setup();
await nextTick();
await nextTick();
const sidebar = wrapper.find("nav");

if (!sidebarExpanded)
Expand All @@ -121,8 +115,6 @@ describe("newLoggedIn", () => {
const sidebarExpanded = true;
const { wrapper } = setup();

await nextTick();

const sidebar = wrapper.find("nav");

if (!sidebarExpanded) expect(sidebar.attributes("tabindex")).toBe("-1");
Expand Down
2 changes: 2 additions & 0 deletions src/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1609,6 +1609,8 @@ export default {
"pages.room.modal.course.export.version1.1":
"Common Cartridge Version 1.1 (z.B. kompatibel mit Moodle)",
"pages.room.modal.course.export.version1.3": "Common Cartridge Version 1.3",
"pages.rooms.active.title": "Aktuelle Räume",
"pages.rooms.active.emptyState": "Aktuell gibt es hier noch keine Räume.",
"pages.taskCard.addElement": "Element hinzufügen",
"pages.taskCard.deleteElement.text":
"Bist du dir sicher, dass du das Element löschen möchtest?",
Expand Down
2 changes: 2 additions & 0 deletions src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1580,6 +1580,8 @@ export default {
"pages.room.modal.course.export.version1.1":
"Common Cartridge Version 1.1 (e.g. compatible with Moodle)",
"pages.room.modal.course.export.version1.3": "Common Cartridge Version 1.3",
"pages.rooms.active.title": "Current rooms",
"pages.rooms.active.emptyState": "Currently there are no rooms here.",
"pages.taskCard.addElement": "Add element",
"pages.taskCard.deleteElement.text":
"Are you sure, you want to remove this element?",
Expand Down
2 changes: 2 additions & 0 deletions src/locales/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1625,6 +1625,8 @@ export default {
"pages.room.modal.course.export.version1.1":
"Common Cartridge versión 1.1 (p. ej. compatible con Moodle)",
"pages.room.modal.course.export.version1.3": "Common Cartridge versión 1.3",
"pages.rooms.active.title": "Habitaciones actuales",
"pages.rooms.active.emptyState": "Actualmente no hay habitaciones aquí.",
"pages.taskCard.addElement": "Añadir artículo",
"pages.taskCard.deleteElement.text":
"¿Estás seguro de que deseas eliminar este elemento?",
Expand Down
2 changes: 2 additions & 0 deletions src/locales/uk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1603,6 +1603,8 @@ export default {
"pages.room.modal.course.export.version1.1":
"Загальний картридж версії 1.1 (наприклад, сумісні з Moodle)",
"pages.room.modal.course.export.version1.3": "Загальний картридж версії 1.3",
"pages.rooms.active.title": "Актуальні номери",
"pages.rooms.active.emptyState": "Зараз тут немає кімнат",
"pages.taskCard.addElement": "Додати елемент",
"pages.taskCard.deleteElement.text":
"Ви впевнені, що хочете видалити цей елемент?",
Expand Down
75 changes: 75 additions & 0 deletions src/modules/feature/room/RoomGrid.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<template>
<template v-if="isLoading">
<VContainer class="loader">
<VSkeletonLoader
ref="skeleton-loader"
type="date-picker-days"
class="mt-6"
/>
</VContainer>
</template>
<template v-else-if="isEmpty">
<VCustomEmptyState
ref="rooms-empty-state"
image="rooms-empty-state"
:title="t('pages.rooms.active.emptyState')"
class="mt-16"
/>
</template>
<template v-else>
<div class="room-tile-grid">
<RoomTile
v-for="room in rooms"
:key="room.id"
:room="room"
class="room-tile"
/>
</div>
</template>
</template>

<script setup lang="ts">
import { useRoomsState } from "./data/Rooms.state";
import { onMounted } from "vue";
import RoomTile from "./RoomTile.vue";
import VCustomEmptyState from "@/components/molecules/vCustomEmptyState.vue";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { rooms, isLoading, isEmpty, fetchRooms } = useRoomsState();
onMounted(() => {
fetchRooms();
});
</script>

<style lang="scss">
@import "@/styles/settings.scss";
.room-tile-grid {
@media #{map-get($display-breakpoints, "sm-and-up")} {
display: flex;
flex-wrap: wrap;
}
margin-left: -20px;
margin-right: -20px;
}
.room-tile {
padding-left: 20px;
padding-right: 20px;
margin-bottom: 20px;
@media #{map-get($display-breakpoints, "sm-and-up")} {
flex: 0 0 50%;
}
@media #{map-get($display-breakpoints, "md-and-up")} {
flex: 0 0 33.3333%;
}
@media #{map-get($display-breakpoints, "lg-and-up")} {
flex: 0 0 25%;
}
}
</style>
76 changes: 76 additions & 0 deletions src/modules/feature/room/RoomTile.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<template>
<div>
<RouterLink :to="roomPath" class="room-link">
<div
class="room-icon"
:aria-label="iconAriaLabel"
:style="{ 'background-color': iconColor }"
>
<span class="text-h3 text-white" data-testid="room-short-title">
{{ room.shortTitle }}
</span>
</div>
<div class="room-title mb-2 mt-2">{{ room.title }}</div>
</RouterLink>
</div>
</template>
<script setup lang="ts">
import { Room } from "@/types/room/Room";
import { computed, PropType } from "vue";
import { useI18n } from "vue-i18n";
const props = defineProps({
room: {
type: Object as PropType<Room>,
required: true,
},
});
const { t } = useI18n();
const roomPath = computed(() => `/rooms/${props.room.id}`);
const iconColor = computed(() => props.room.displayColor);
const iconAriaLabel = computed(() => {
return `${t("common.labels.room")} ${props.room.title}`;
});
</script>

<style lang="scss" scoped>
@import "@/utils/multiline-ellipsis.scss";
a.room-link {
display: block;
text-decoration: none;
text-align: center;
color: rgba(var(--v-theme-primary));
}
.room-icon {
width: 5em;
height: 5em;
border-radius: 8px;
user-select: none;
// taken from VAvatar.sass
flex: none;
align-items: center;
display: inline-flex;
justify-content: center;
line-height: normal;
overflow: hidden;
position: relative;
text-align: center;
transition: 0.2s cubic-bezier(0.4, 0, 0.2, 1);
transition-property: width, height;
vertical-align: middle;
}
.room-title {
@include excerpt(
$font-size: calc(var(--space-base-vuetify) * 4),
$line-height: var(--line-height-lg),
$lines-to-show: 3
);
}
</style>
22 changes: 22 additions & 0 deletions src/modules/feature/room/data/Rooms.state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Room } from "@/types/room/Room";
import { delay } from "@/utils/helpers";
import { computed, ref } from "vue";
import { roomsData } from "./rooms-mock-data";

export const useRoomsState = () => {
const rooms = ref<Room[]>([]);
const isLoading = ref(true);

const fetchRooms = async () => {
await delay(1000);
// TODO call API + do sorting there
rooms.value = roomsData.sort((r1, r2) => (r1.title > r2.title ? 1 : -1));
isLoading.value = false;
};

const isEmpty = computed(() => {
return rooms.value.length === 0;
});

return { rooms, isLoading, isEmpty, fetchRooms };
};
41 changes: 41 additions & 0 deletions src/modules/feature/room/data/rooms-mock-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Room } from "@/types/room/Room";

// TODO replace with API call
export const roomsData: Room[] = [
{
id: "0000dcfbfb5c7a3f00bf21cd",
title: "Maschinelles Lernen in der Cloud",
shortTitle: "Ma",
displayColor: "#54616e",
},
{
id: "0000dcfbfb5c7a3f00bf21ce",
title: "Hybrid Cloud und Multi-Cloud-Strategien",
shortTitle: "Hy",
displayColor: "rgb(239, 108, 0)",
},
{
id: "0000dcfbfb5c7a3f00bf21cf",
title: "Serverless Computing",
shortTitle: "Se",
displayColor: "rgb(48, 79, 254)",
},
{
id: "0000dcfbfb5c7a3f00bf21da",
title: "Prototyping an App with Quasar",
shortTitle: "Pr",
displayColor: "#54616e",
},
{
id: "0000dcfbfb5c7a3f00bf21db",
title: "State Management with Pinia",
shortTitle: "St",
displayColor: "#54616e",
},
{
id: "0000dcfbfb5c7a3f00bf21db",
title: "Accessibility, Interactivity And Why Testing Still Matters",
shortTitle: "Ac",
displayColor: "#54616e",
},
];
3 changes: 3 additions & 0 deletions src/modules/feature/room/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import RoomGrid from "./RoomGrid.vue";

export { RoomGrid };
11 changes: 6 additions & 5 deletions src/modules/page/room/Rooms.page.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<template>
<DefaultWireframe max-width="short">
<template #header>
<h1 class="text-h3 py-2 mb-4">Rooms [TODO translation]</h1>
</template>

<template>
<p>Content [TODO component]</p>
<h1 class="text-h3 py-2 mb-4">{{ t("pages.rooms.active.title") }}</h1>
</template>
<RoomGrid />
</DefaultWireframe>
</template>
<script setup lang="ts">
import DefaultWireframe from "@/components/templates/DefaultWireframe.vue";
import { RoomGrid } from "@feature-room";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
</script>
2 changes: 0 additions & 2 deletions src/modules/ui/layout/sidebar/Sidebar.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ describe("@ui-layout/Sidebar", () => {
describe("when user does not have needed permission", () => {
it("should filter items correctly", async () => {
const { wrapper } = setup([]);
await nextTick();
await nextTick();

expect(wrapper.find("[data-testid='Teams']").exists()).toBe(false);
});
Expand Down
1 change: 0 additions & 1 deletion src/modules/ui/layout/topbar/Topbar.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ describe("@ui-layout/Topbar", () => {
},
});

await nextTick();
await nextTick();
const topbar = wrapper.findComponent({ name: "Topbar" });
return { wrapper, topbar };
Expand Down
6 changes: 6 additions & 0 deletions src/types/room/Room.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export type Room = {
id: string;
title: string;
shortTitle: string;
displayColor: string;
};
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"@feature-news-form": ["src/modules/feature/news-form"],
"@feature-media-shelf": ["src/modules/feature/media-shelf"],
"@feature-board-deleted-element": ["src/modules/feature/board-deleted-element"],
"@feature-room": ["src/modules/feature/room"],
"@ui-alert": ["src/modules/ui/alert"],
"@ui-board": ["src/modules/ui/board"],
"@ui-chip": ["src/modules/ui/chip"],
Expand Down

0 comments on commit cd28aa1

Please sign in to comment.