Skip to content
Snippets Groups Projects
Commit 858b0438 authored by Haakon Tideman Kanter's avatar Haakon Tideman Kanter
Browse files

Merge branch 'community-admin' of...

Merge branch 'community-admin' of https://gitlab.stud.idi.ntnu.no/idatt2106_2022_02/boco-frontend into community-request
parents 333d21e1 5d31ffdc
No related branches found
No related tags found
1 merge request!87Community request
Pipeline #180006 failed
Showing
with 489 additions and 127 deletions
<template>
<div v-if="totalPages() > 0">
<span v-if="showPreviousLink()"
class="cursor-pointer inline-flex items-center p-2 text-sm font-medium text-gray-500 bg-white rounded-lg border border-gray-300 hover:bg-gray-100 hover:text-gray-700"
@click="updatePage(currentPage - 1)">
<span
v-if="showPreviousLink()"
class="cursor-pointer inline-flex items-center p-2 text-sm font-medium text-gray-500 bg-white rounded-lg border border-gray-300 hover:bg-gray-100 hover:text-gray-700"
@click="updatePage(currentPage - 1)"
>
Forrige
</span>
<label class="mx-2">{{ currentPage + 1 }} av {{ totalPages() }}</label>
<span
v-if="showNextLink()"
class="cursor-pointer inline-flex items-center p-2 text-sm font-medium text-gray-500 bg-white rounded-lg border border-gray-300 hover:bg-gray-100 hover:text-gray-700"
@click="updatePage(currentPage + 1)">
v-if="showNextLink()"
class="cursor-pointer inline-flex items-center p-2 text-sm font-medium text-gray-500 bg-white rounded-lg border border-gray-300 hover:bg-gray-100 hover:text-gray-700"
@click="updatePage(currentPage + 1)"
>
Neste
</span>
</div>
......@@ -17,11 +20,11 @@
<script>
export default {
name: 'paginationTemplate',
props: ['items', 'currentPage', 'pageSize'],
name: "paginationTemplate",
props: ["items", "currentPage", "pageSize"],
methods: {
updatePage(pageNumber) {
this.$emit('page:update', pageNumber);
this.$emit("page:update", pageNumber);
},
totalPages() {
return Math.ceil(this.items.length / this.pageSize);
......@@ -30,8 +33,8 @@ export default {
return this.currentPage == 0 ? false : true;
},
showNextLink() {
return this.currentPage == (this.totalPages() - 1) ? false : true;
}
}
}
return this.currentPage == this.totalPages() - 1 ? false : true;
},
},
};
</script>
......@@ -43,18 +43,16 @@ import CommunityAdminService from "@/services/community-admin.service";
export default {
name: "CommunityHamburger",
props: {
communityID: Number,
},
data() {
return {
id: -1,
admin: false,
communityID: -1,
};
},
methods: {
leaveCommunity: async function () {
this.id = await this.$router.currentRoute.value.params.communityID;
this.id = this.$route.params.communityID;
await LeaveCommunity(this.id);
this.$router.push("/");
},
......@@ -64,5 +62,8 @@ export default {
this.$route.params.communityID
);
},
created() {
this.communityID = this.$route.params.communityID;
},
};
</script>
<template>
<div class="flex items-center justify-between mx-4">
<!-- TODO PUT A LOADER HERE -->
<div v-if="loading">LASTER...</div>
<div v-else class="flex items-center justify-between mx-4">
<router-link
:to="'/community/' + community.communityId"
class="flex-1 min-w-0"
......@@ -83,9 +85,10 @@ import CommunityHamburger from "@/components/CommunityComponents/CommunityHambur
import ColoredButton from "@/components/BaseComponents/ColoredButton";
import CommunityService from "@/services/community.service";
import CustomFooterModal from "@/components/BaseComponents/CustomFooterModal";
import { parseCurrentUser } from "@/utils/token-utils";
import {
JoinOpenCommunity,
GetIfUserAlreadyInCommunity,
// GetIfUserAlreadyInCommunity,
} from "@/utils/apiutil";
export default {
......@@ -95,12 +98,18 @@ export default {
ColoredButton,
CustomFooterModal,
},
computed: {
userid() {
return parseCurrentUser().accountId;
},
},
data() {
return {
hamburgerOpen: false,
dialogOpen: false,
member: true,
member: false,
community: {},
loading: true,
};
},
props: {
......@@ -110,6 +119,20 @@ export default {
toggleHamburgerMenu() {
this.hamburgerOpen = !this.hamburgerOpen;
},
async load() {
this.community = await CommunityService.getCommunity(
this.$route.params.communityID
);
let members = await CommunityService.getCommunityMembers(
this.$route.params.communityID
);
for (let mem in members) {
if (mem === this.userid) {
this.member = true;
return;
}
}
},
joinCommunity: async function (id) {
const response = await JoinOpenCommunity(id);
if (response === "Login to join any community") {
......@@ -118,23 +141,13 @@ export default {
window.location.reload();
}
},
getIfUserInCommunity: async function () {
try {
this.member = await GetIfUserAlreadyInCommunity(
this.$router.currentRoute.value.params.communityID
);
} catch (error) {
console.log(error);
}
},
},
beforeMount() {
this.getIfUserInCommunity();
},
async mounted() {
this.community = await CommunityService.getCommunity(
this.$route.params.communityID
);
// beforeMount() {
// this.getIfUserInCommunity();
// },
async created() {
await this.load();
this.loading = false;
},
};
</script>
......@@ -26,35 +26,44 @@
/>
</div>
<div class="absolute inset-x-0 px-5 py-3">
<!-- ItemCards -->
<div class="flex items-center justify-center w-screen">
<!-- Shows items based on pagination -->
<div
class="grid grid-flow-row-dense grid-cols-2 md:grid-cols-4 lg:grid-cols-5 w-full"
v-if="showItems">
<ItemCard v-for="item in visibleItems" :key="item" :item="item" @click="goToItemInfoPage(item.listingID)" />
class="grid grid-flow-row-dense grid-cols-2 md:grid-cols-4 lg:grid-cols-5 w-full"
v-if="showItems"
>
<ItemCard
v-for="item in visibleItems"
:key="item"
:item="item"
@click="goToItemInfoPage(item.listingID)"
/>
</div>
<!-- Shows items based on search field input -->
<div
class="grid grid-flow-row-dense grid-cols-2 md:grid-cols-4 lg:grid-cols-5 w-full place-items-center"
v-if="showSearchedItems">
<ItemCard v-for="item in searchedItems" :key="item" :item="item" @click="goToItemInfoPage(item.listingID)" />
class="grid grid-flow-row-dense grid-cols-2 md:grid-cols-4 lg:grid-cols-5 w-full place-items-center"
v-if="showSearchedItems"
>
<ItemCard
v-for="item in searchedItems"
:key="item"
:item="item"
@click="goToItemInfoPage(item.listingID)"
/>
</div>
</div>
<!-- pagination -->
<div class="flex justify-center" v-if="showItems">
<PaginationTemplate
v-bind:items="items"
v-on:page:update="updatePage"
v-bind:currentPage="currentPage"
v-bind:pageSize="pageSize"
class="mt-10"
v-bind:items="items"
v-on:page:update="updatePage"
v-bind:currentPage="currentPage"
v-bind:pageSize="pageSize"
class="mt-10"
/>
</div>
</div>
......@@ -121,9 +130,8 @@ export default {
};
},
methods: {
getCommunityFromAPI: async function () {
this.communityID = await this.$router.currentRoute.value.params
.communityID;
async getCommunityFromAPI() {
this.communityID = this.$route.params.communityID;
this.community = await GetCommunity(this.communityID);
},
getListingsOfCommunityFromAPI: async function () {
......@@ -144,13 +152,12 @@ export default {
let res = await getItemPictures(itemid);
return res;
},
searchWritten: function (){
searchWritten: function () {
//This method triggers when search input field is changed
if(this.search.length > 0){
if (this.search.length > 0) {
this.showItems = false;
this.showSearchedItems = true;
}
else{
} else {
this.showItems = true;
this.showSearchedItems = false;
}
......@@ -162,11 +169,14 @@ export default {
this.updateVisibleTodos();
},
updateVisibleTodos() {
this.visibleItems = this.items.slice(this.currentPage * this.pageSize, (this.currentPage * this.pageSize) + this.pageSize);
this.visibleItems = this.items.slice(
this.currentPage * this.pageSize,
this.currentPage * this.pageSize + this.pageSize
);
// if we have 0 visible items, go back a page
if (this.visibleItems.length === 0 && this.currentPage > 0) {
this.updatePage(this.currentPage -1);
this.updatePage(this.currentPage - 1);
}
},
},
......
<template>
<ul>
<div v-if="loading">LASTER...</div>
<ul v-else>
<li v-for="member in members" :key="member.userId">
<UserListItemCard :buttons="buttons" :user="member" />
</li>
......@@ -8,7 +9,7 @@
<script>
import UserListItemCard from "@/components/UserProfileComponents/UserListItemCard.vue";
import { GetMembersOfCommunity } from "@/utils/apiutil";
import CommunityService from "@/services/community.service";
export default {
name: "MemberList",
......@@ -21,10 +22,18 @@ export default {
data() {
return {
members: [],
loading: false,
};
},
methods: {
async load() {},
},
async created() {
this.members = await GetMembersOfCommunity(this.$route.params.communityID);
this.loading = true;
this.members = await CommunityService.getCommunityMembers(
this.$route.params.communityID
);
this.loading = false;
},
};
</script>
......@@ -2,7 +2,7 @@ import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import ws from "./services/ws";
// import ws from "./services/ws";
createApp(App).use(router).use(store).mount("#app");
console.log("WS", ws.test);
......@@ -65,7 +65,7 @@ const routes = [
beforeEnter: guardRoute,
},
{
path: "/community/:id/memberlist",
path: "/community/:communityID/memberlist",
name: "memberlist",
component: () => import("../views/CommunityViews/MemberListView.vue"),
beforeEnter: guardRoute,
......
......@@ -4,9 +4,9 @@ import axios from "axios";
const API_URL = process.env.VUE_APP_BASEURL;
class CommunityService {
async getCommunity(communityId) {
async getCommunity(communityID) {
return await axios
.get(API_URL + "community/" + communityId, {
.get(API_URL + "community/" + communityID, {
headers: tokenHeader(),
})
.then((response) => {
......@@ -28,9 +28,9 @@ class CommunityService {
});
}
async getCommunityMembers(communityId) {
async getCommunityMembers(communityID) {
return await axios
.get(API_URL + "community/" + communityId + "/members", {
.get(API_URL + "community/" + communityID + "/members", {
headers: tokenHeader(),
})
.then((response) => {
......
......@@ -23,10 +23,10 @@ class UserService {
}
//TODO
getUserRatingAsOwner() {}
async getUserRatingAsOwner() {}
//TODO
getUserRatingAsRenter() {}
async getUserRatingAsRenter() {}
}
export default new UserService();
......@@ -23,7 +23,7 @@ export function registerUser(registerInfo) {
.post(API_URL + "register", {
email: registerInfo.email,
firstName: registerInfo.firstName,
lastname: registerInfo.lastname,
lastName: registerInfo.lastname,
password: registerInfo.password,
address: registerInfo.address,
})
......
......@@ -2,62 +2,16 @@
exports[`CommunityHeader component renders correctly 1`] = `
<div
class="flex items-center justify-between mx-4"
data-v-app=""
>
<router-link
class="flex-1 min-w-0"
to="/community/1"
<!-- TODO PUT A LOADER HERE -->
<div
adminstatus="true"
community="[object Object]"
>
<h2
class="text-xl md:text-2xl text-gray-600 font-medium w-full sm:truncate"
>
String
</h2>
<div
class="mt-1 flex flex-col sm:flex-row sm:flex-wrap sm:mt-0 sm:space-x-6"
>
<div
class="mt-2 flex items-center text-sm text-gray-500"
>
<svg
aria-hidden="true"
class="flex-shrink-0 mr-1.5 h-5 w-5 text-gray-400"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z"
fill-rule="evenodd"
/>
</svg>
String
</div>
</div>
</router-link>
<div>
<!-- If the user is not a member in the community, this button will show -->
<!--v-if-->
<!-- If the user is member of the community, this hamburger menu will show -->
<div>
<svg
class="w-9 h-9 cursor-pointer"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4 6h16M4 12h16M4 18h16"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
</svg>
<!--v-if-->
<!-- class="absolute" -->
</div>
LASTER...
</div>
</div>
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ItemCard component renders correctly 1`] = `
<div
class="mt-5"
>
<div
class="w-4/5 rounded bg-gray-200 h-full overflow-hidden display:inline-block correct-size"
>
<img
alt="Item image"
class="w-full"
src="String"
/>
<div
class="p-1 m-1"
>
<p
class="text-gray-700 text-xs font-bold"
id="adress"
>
String
</p>
<p
class="font-bold text-sm"
id="title"
>
String
</p>
<p
class="text-gray-700 text-xs"
id="price"
>
0 kr
</p>
</div>
</div>
</div>
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`NewItemForm component renders correctly 1`] = `
<div
class="md:ring-1 ring-gray-300 rounded-xl overflow-hidden mx-auto mb-auto max-w-md w-full p-4"
>
<!-- Component heading -->
<h3
class="text-xl font-medium text-center text-gray-600 dark:text-gray-200 mt-4 mb-8"
>
Opprett ny utleie
</h3>
<!-- Title -->
<div
class="mb-6"
>
<label
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
id="titleLabel"
>
Tittel
</label>
<input
class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light"
id="title"
required=""
type="text"
/>
<!-- error message for title-->
</div>
<!-- Select category -->
<div
class="mb-6"
>
<label
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400"
id="selectCategoryLabel"
>
Kategori
</label>
<select
class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light"
id="categories"
>
<option
class="text-gray-400"
disabled=""
value=""
>
Velg en kategori
</option>
<option
class="text-gray-900 text-sm"
>
Hage
</option>
<option
class="text-gray-900 text-sm"
>
Kjøkken
</option>
<option
class="text-gray-900 text-sm"
>
Musikk
</option>
<option
class="text-gray-900 text-sm"
>
Annet
</option>
</select>
<!-- error message for select box -->
</div>
<!-- Grupper -->
<div
class="mb-6"
>
<label
class="block text-sm font-medium text-gray-900 dark:text-gray-400"
>
Grupper
</label>
<div
class="overflow-auto w-full h-32 mt-2 text-base list-none bg-white rounded divide-y divide-gray-100 dark:bg-gray-700"
>
<ul
aria-labelledby="dropdownDefault"
class="py-1"
>
<li>
</li>
</ul>
</div>
<label
class="text-error text-sm block"
/>
</div>
<!-- price -->
<div
class="mb-6 mt-4"
>
<label
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
id="priceLabel"
>
Pris
</label>
<input
class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light"
id="price"
required=""
type="number"
/>
<!-- error message for price -->
</div>
<!-- Description -->
<div
class="mb-6"
>
<label
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400"
id="descriptionLabel"
>
Beskrivelse
</label>
<textarea
class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light"
id="description"
required=""
rows="4"
/>
<!-- error message for description -->
</div>
<!-- Address -->
<div
class="mb-6"
>
<label
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
id="addressLabel"
>
Adresse
</label>
<input
class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light"
id="adress"
required=""
type="text"
/>
<!-- error message for address-->
</div>
<!-- Images -->
<div>
<label
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400"
id="imageLabel"
>
Bilder
</label>
<input
accept="image/png, image/jpeg"
multiple=""
style="display: none;"
type="file"
/>
<button
class="block text-white bg-primary-medium hover:bg-primary-dark focus:ring-4 focus:outline-none focus:ring-primary-light font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-medium dark:hover:bg-primary-dark dark:focus:ring-primary-light"
>
Velg bilde
</button>
</div>
<!-- Save item button -->
<div
class="float-right"
>
<button
class="block text-white bg-primary-medium hover:bg-primary-dark focus:ring-4 focus:outline-none focus:ring-primary-light font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-medium dark:hover:bg-primary-dark dark:focus:ring-primary-light"
id="saveButton"
>
Lagre
</button>
</div>
</div>
`;
import { shallowMount } from "@vue/test-utils";
import CommunityHamburger from "@/components/CommunityComponents/CommunityHamburger.vue";
import { route, router, $route, $router } from "../../mock-router";
describe("CommunityHamburger elements rendering", () => {
it("renders all li fields", () => {
const wrapper = shallowMount(CommunityHamburger);
let wrapper;
beforeEach(() => {
wrapper = shallowMount(CommunityHamburger, {
//passing prop to component
props: {
adminStatus: true,
community: {
communityId: 1,
name: "String",
description: "String",
visibility: 0,
location: "String",
picture: "String",
},
},
global: {
mocks: {
route,
router,
$route,
$router,
},
},
});
});
it("renders all li fields", () => {
expect(wrapper.find("#newItem").text()).toMatch("Opprett Utleie");
expect(wrapper.find("#getMembers").text()).toMatch("Se Medlemmer");
expect(wrapper.find("#adminGroup").text()).toMatch("Administrer Gruppe");
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`NewPasswordForm component renders correctly 1`] = `
<div
class="md:ring-1 ring-gray-300 rounded-xl overflow-hidden mx-auto mb-auto max-w-md w-full p-4"
>
<h3
class="text-xl font-medium text-center text-gray-600 dark:text-gray-200 mt-4 mb-8"
>
Endre passord
</h3>
<div
class=""
id="firstPasswordField"
>
<label
class="block text-sm text-gray-800 dark:text-gray-200"
for="password"
>
Nytt passord
</label>
<input
class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-blue-300"
type="password"
/>
<!-- error message -->
</div>
<div
class="mt-4"
id="secondPasswordField"
>
<div
class="flex items-center justify-between"
>
<label
class="block text-sm text-gray-800 dark:text-gray-200"
for="rePassword"
>
Gjenta nytt passord
</label>
</div>
<input
class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-blue-300"
type="password"
/>
<!-- error message -->
</div>
<div
class="mt-6"
id="buttonsField"
>
<button
class="block text-white bg-primary-medium hover:bg-primary-dark focus:ring-4 focus:outline-none focus:ring-primary-light font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-medium dark:hover:bg-primary-dark dark:focus:ring-primary-light float-right"
>
Sett ny passord
</button>
</div>
</div>
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ResetPasswordForm component renders correctly 1`] = `
<div
class="md:ring-1 ring-gray-300 rounded-xl overflow-hidden mx-auto mb-auto max-w-md w-full p-4"
>
<h3
class="text-xl font-medium text-center text-gray-600 dark:text-gray-200 mt-4 mb-8"
>
Glemt passordet ditt?
</h3>
<div
class="m-6"
id="emailField"
>
<div
class="mb-6"
>
<label
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
for="email"
>
E-post
</label>
<input
class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-blue-300"
id="email"
placeholder="eksempel@eksempel.no"
required=""
type="email"
/>
<!-- error message -->
</div>
<button
class="block text-white bg-primary-medium hover:bg-primary-dark focus:ring-4 focus:outline-none focus:ring-primary-light font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-medium dark:hover:bg-primary-dark dark:focus:ring-primary-light float-right"
>
Tilbakestill passord
</button>
</div>
</div>
`;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment