diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e757a909259f83ab7a49cbed5dac6b15ab115061..8dd0ebc17218f6c8273da344f9dec0ce864912a8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,6 +3,7 @@ image: node:16 stages: # - setup - test + - deploy #variables: # npm_config_cache: "$CI_PROJECT_DIR/.npm" @@ -37,6 +38,21 @@ test: - npm run lint - npm run test:unit +deploy-backend: + image: ubuntu:latest + stage: deploy + script: + - chmod og= $ID_RSA + - apt update + - apt install --assume-yes rsync + - apt install --assume-yes openssh-client + - ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVERUSER@$SERVERIP "sudo /bin/systemctl restart cleanfront.service" + - rsync --archive --rsync-path=/usr/bin/rsync --delete --exclude='.git' --exclude='node_modules' -e "ssh -i $ID_RSA -o StrictHostKeyChecking=no -l $SERVERUSER -p 22" . $SERVERIP:./app/frontend + - ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVERUSER@$SERVERIP "cd app/frontend;npm install" + - ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVERUSER@$SERVERIP "sudo /bin/systemctl restart frontend.service" + only: + - main + #unit_test: # stage: test # script: diff --git a/src/components/BaseComponents/PaginationTemplate.vue b/src/components/BaseComponents/PaginationTemplate.vue new file mode 100644 index 0000000000000000000000000000000000000000..0d96ee5d7fcea9955cf6c9a85546b7c4033b21b3 --- /dev/null +++ b/src/components/BaseComponents/PaginationTemplate.vue @@ -0,0 +1,37 @@ +<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)"> + 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)"> + Neste + </span> + </div> +</template> + +<script> +export default { + name: 'paginationTemplate', + props: ['items', 'currentPage', 'pageSize'], + methods: { + updatePage(pageNumber) { + this.$emit('page:update', pageNumber); + }, + totalPages() { + return Math.ceil(this.items.length / this.pageSize); + }, + showPreviousLink() { + return this.currentPage == 0 ? false : true; + }, + showNextLink() { + return this.currentPage == (this.totalPages() - 1) ? false : true; + } + } +} +</script> diff --git a/src/components/CommunityComponents/CommunityHome.vue b/src/components/CommunityComponents/CommunityHome.vue index 99e3e48a02cfe8ae489140457f9d8ee61f4ba37d..35542263915a810f46645b220d8d076783e4eeae 100644 --- a/src/components/CommunityComponents/CommunityHome.vue +++ b/src/components/CommunityComponents/CommunityHome.vue @@ -1,5 +1,5 @@ <template> - <section class="w-full px-5 py-4 mx-auto rounded-md"> + <section class="w-full px-5 py-4 mx-auto rounded-md "> <CommunityHeader :admin-status="false" :community="community" @@ -26,19 +26,39 @@ class="w-full py-3 pl-10 pr-4 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-primary-medium dark:focus:border-primary-medium focus:outline-none focus:ring" placeholder="Search" v-model="search" + @change="searchWritten" /> </div> - <!-- Item cards --> - <div class="absolute inset-x-0 px-6 py-3"> - <div - class="grid grid-flow-row-dense grid-cols-2 md:grid-cols-4 lg:grid-cols-5 w-full place-items-center" - > - <ItemCard - v-for="item in searchedItems" - :key="item" - :item="item" - @click="goToItemInfoPage(item.listingID)" + + <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)" /> + </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)" /> + </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" /> </div> </div> @@ -46,8 +66,10 @@ </template> <script> -import CommunityHeader from "@/components/CommunityComponents/CommunityHeader.vue"; import ItemCard from "@/components/ItemComponents/ItemCard"; +import CommunityHeader from "@/components/CommunityComponents/CommunityHeader"; +import PaginationTemplate from "@/components/BaseComponents/PaginationTemplate"; + import { GetCommunity, GetListingsInCommunity, @@ -59,6 +81,7 @@ export default { components: { CommunityHeader, ItemCard, + PaginationTemplate, }, computed: { @@ -93,6 +116,14 @@ export default { search: "", communityID: -1, community: {}, + + showItems: true, + showSearchedItems: false, + + //Variables connected to pagination + currentPage: 0, + pageSize: 12, + visibleItems: [], }; }, methods: { @@ -107,7 +138,6 @@ export default { this.items = await GetListingsInCommunity(this.communityID); for (var i = 0; i < this.items.length; i++) { let images = await getItemPictures(this.items[i].listingID); - console.log(images); if (images.length > 0) { this.items[i].img = images[0].picture; } @@ -120,10 +150,36 @@ export default { let res = await getItemPictures(itemid); return res; }, + searchWritten: function (){ + //This method triggers when search input field is changed + if(this.search.length > 0){ + this.showItems = false; + this.showSearchedItems = true; + } + else{ + this.showItems = true; + this.showSearchedItems = false; + } + }, + + //Pagination + updatePage(pageNumber) { + this.currentPage = pageNumber; + this.updateVisibleTodos(); + }, + updateVisibleTodos() { + 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); + } + }, }, - beforeMount() { - this.getCommunityFromAPI(); //To get the id of the community before mounting the view - this.getListingsOfCommunityFromAPI(); + async beforeMount() { + await this.getCommunityFromAPI(); //To get the id of the community before mounting the view + await this.getListingsOfCommunityFromAPI(); + this.updateVisibleTodos(); }, }; </script> diff --git a/src/components/FormComponents/NewPasswordForm.vue b/src/components/FormComponents/NewPasswordForm.vue index d13c08349360250ff4f0cf96b5f3faab00d7a841..f9a9c779db23ef5d16e6871d1edac10fd7b7e55b 100644 --- a/src/components/FormComponents/NewPasswordForm.vue +++ b/src/components/FormComponents/NewPasswordForm.vue @@ -134,12 +134,19 @@ export default { return; } - const newPasswordInfo = { - token: this.token, - newPassword: this.password, - }; + const newPassword = this.user.password; - const newPasswordResponse = doNewPassword(newPasswordInfo); + const newPasswordResponse = await doNewPassword(newPassword); + + if (newPasswordResponse != null) { + console.log("New password set"); + this.$store.commit("saveToken", newPasswordResponse); + await this.$router.push("/"); + } else { + console.log("Couldn't set new password"); + } + + /* if (newPasswordResponse.newPasswordSet === true) { console.log("New password set"); @@ -149,6 +156,8 @@ export default { } else { console.log("Something went wrong"); } + + */ }, validate() { this.$refs.form.validate(); diff --git a/src/utils/apiutil.js b/src/utils/apiutil.js index a49864af94949186bb90b327a95ad74cc4dc9d37..1397849ea208d2760f3b8ac372ba1d6820892d73 100644 --- a/src/utils/apiutil.js +++ b/src/utils/apiutil.js @@ -84,15 +84,22 @@ export function getAverageRating(userid) { console.error(error); }); } -export function doNewPassword() { - //m - //add newPasswordInfo to input - const auth = { newPasswordSet: false }; - //return axios - //.post(API_URL + "newPassword", newPasswordInfo) - //.then((response) => {auth.newPasswordSet = true;return auth;}) - //.catch((error) => {console.log(error);return auth;}); - return auth; //remove after axios is added +export async function doNewPassword(password) { + let res = await axios({ + method: "put", + url: API_URL + "user/profile/password", + headers: tokenHeader(), + data: { + password: password, + }, + }) + .then((response) => { + return response; + }) + .catch((error) => { + console.log(error); + }); + return res.data; } export function postNewItem(itemInfo) {