Skip to content
Snippets Groups Projects
Profile.vue 26.4 KiB
Newer Older
moon's avatar
moon committed
<template>
moon's avatar
moon committed
  <div
    id="page-content-wrapper"
    class="flex flex-wrap justify-center"
  >
    <base-toaster
      :open="toasterIsOpen"
      @close="hideDialog"
    >
      <div class="flex justify-between space-x-4 items-center">
        <font-awesome-icon
          class="ml-3"
          icon="fa-solid fa-thumbs-up "
          size="lg"
        />
        <h4>{{toasterMessage}}</h4>
moon's avatar
moon committed
        <button
          class="btn btn-outline"
          @click="hideDialog"
        >
          <font-awesome-icon
            icon="fa-regular fa-circle-xmark"
            size="2x"
          />
    <div class="w-5/6">
moon's avatar
moon committed
      <fetch-profile
        v-if="userData !== null"
        :key="updatedKey"
      >
raghosh's avatar
raghosh committed
        <template slot-scope="{ response, loading, error: profile_error }">
moon's avatar
moon committed
          <slot
            :response="response"
            :loading="loading"
            :error="profile_error"
          >
moon's avatar
moon committed
            <div v-if="loading">
              <base-spinner />
            </div>
            <div v-else-if="!loading && profile_error">
              <p class="text-red-500 text-2xl">
                {{ response }}
              </p>
            </div>
            <div v-else>
              <!--            {{response}}-->
moon's avatar
moon committed
              <h2 class="round font-bold">
                User Profile
              </h2>
moon's avatar
moon committed
              <div class="panel panel-default">
                <div class="panel-body">
                  <div class="container-fluid col-md-12">
                    <div class="row">
moon's avatar
moon committed
                      <div class="text col-sm-3">
                        User ID
                      </div>
moon's avatar
moon committed
                      <div class="col-sm-9">
                        <div class="flex justify-between">
                          <b>{{ response.username }}</b>
                          <div class="relative">
                            <button
                              class="
raghosh's avatar
raghosh committed
                                text-white
                                bg-blue-500
                                hover:bg-blue-700
                                focus:ring-2 focus:ring-blue-300
                                rounded-lg
                                items-center
                                px-5
                                py-3
                                text-center
                                font-bold
                                mr-2
                                font-bold
                              "
moon's avatar
moon committed
                              @click="isOpen = !isOpen"
                            >
                              Edit
                              <font-awesome-icon
                                class="ml-2"
                                icon="fa-solid fa-user-pen"
                              />
                            </button>
                            <button
                              v-if="isOpen"
                              tabindex="-1"
                              class="fixed inset-0 cursor-default h-full w-full"
moon's avatar
moon committed
                              @click="isOpen = false"
                            />
moon's avatar
moon committed
                            <div
                              v-if="isOpen"
                              class="
raghosh's avatar
raghosh committed
                                absolute
raghosh's avatar
raghosh committed
                                z-50
raghosh's avatar
raghosh committed
                                right-0
raghosh's avatar
raghosh committed
                                rounded-lg
                                shadow-lg
                                border border-gray-200
                                divide-y divide-white-base
raghosh's avatar
raghosh committed
                              "
moon's avatar
moon committed
                            >
                              <!-- Active: "bg-gray-100 text-gray-900", Not Active: "text-gray-700" -->
                              <a
                                class="
raghosh's avatar
raghosh committed
                                  py-4
                                  rounded-lg
                                  text-2xl text-white-base
                                  hover:text-pink-base hover:no-underline
raghosh's avatar
raghosh committed
                                "
moon's avatar
moon committed
                                @click="openScientificDisciplineEdit"
moon's avatar
moon committed
                              >Scientific Discipline</a>
moon's avatar
moon committed
                              <a
                                class="
raghosh's avatar
raghosh committed
                                  py-4
                                  rounded-lg
                                  text-2xl text-white-base
                                  hover:text-pink-base hover:no-underline
raghosh's avatar
raghosh committed
                                "
moon's avatar
moon committed
                                @click="openProfileLinkEdit"
moon's avatar
moon committed
                              >Profile Link</a>
moon's avatar
moon committed
                              <a
raghosh's avatar
raghosh committed
                                class="
raghosh's avatar
raghosh committed
                                  py-4
                                  rounded-lg
                                  text-2xl text-white-base
                                  hover:text-pink-base hover:no-underline
raghosh's avatar
raghosh committed
                                "
moon's avatar
moon committed
                                @click="openChangePassword"
moon's avatar
moon committed
                              >Password</a>
moon's avatar
moon committed
                            </div>
moon's avatar
moon committed
                    <div class="row">
moon's avatar
moon committed
                      <div class="text col-sm-3">
                        Full Name
                      </div>
moon's avatar
moon committed
                      <div class="col-sm-9">
                        <b>{{ response.full_name }}</b>
moon's avatar
moon committed
                    <div class="row">
moon's avatar
moon committed
                      <div class="text col-sm-3">
                        Email
                      </div>
moon's avatar
moon committed
                      <div class="col-sm-9">
                        {{ response.email }}
moon's avatar
moon committed
                    <div class="row">
moon's avatar
moon committed
                      <div class="text col-sm-3">
                        Role
                      </div>
moon's avatar
moon committed
                      <div class="col-sm-9">
                        {{ setRole(response.role.name) }}
                      </div>
moon's avatar
moon committed
                    </div>
moon's avatar
moon committed
                    <div class="row">
moon's avatar
moon committed
                      <div class="text col-sm-3">
                        Current role
                      </div>
moon's avatar
moon committed
                      <div class="col-sm-9">
                        <div>
raghosh's avatar
raghosh committed
                          {{ response.current_role.replace(/_/g, " ") }}
moon's avatar
moon committed
                        </div>
                      </div>
moon's avatar
moon committed
                    <div class="row">
moon's avatar
moon committed
                      <div class="text col-sm-3">
                        Scientific Discipline
                      </div>
moon's avatar
moon committed
                      <div class="col-sm-9">
                        <div>
raghosh's avatar
raghosh committed
                          {{ response.scientific_discipline.join(", ") }}
moon's avatar
moon committed
                        </div>
                      </div>
moon's avatar
moon committed
                    </div>
moon's avatar
moon committed
                    <div class="row">
moon's avatar
moon committed
                      <div class="text col-sm-3">
                        Motivation
                      </div>
moon's avatar
moon committed
                      <div class="col-sm-9">
                        <p>
                          {{ response.motivation_text }}
                        </p>
moon's avatar
moon committed
                    <div class="row">
moon's avatar
moon committed
                      <div class="text col-sm-3">
                        Affiliation
                      </div>
moon's avatar
moon committed
                      <div class="col-sm-9">
                        <div>
                          {{ response.current_affiliation }}
                        </div>
                      </div>
moon's avatar
moon committed
                    </div>
moon's avatar
moon committed
                    <div class="row">
moon's avatar
moon committed
                      <div class="text col-sm-3">
                        Profile Link
                      </div>
moon's avatar
moon committed
                      <div class="col-sm-9">
moon's avatar
moon committed
                        <a
                          :href="response.profile_link"
                          target="_blank"
                        >
moon's avatar
moon committed
                          {{ response.profile_link }}
                        </a>
                      </div>
moon's avatar
moon committed
                    <div class="row">
moon's avatar
moon committed
                      <div class="text col-sm-3">
                        Joined
                      </div>
moon's avatar
moon committed
                      <div class="col-sm-9">
                        {{ response.createdAt }}
                      </div>
moon's avatar
moon committed
                    </div>
moon's avatar
moon committed
                    <div class="row">
moon's avatar
moon committed
                      <div class="text col-sm-3">
                        Updated
                      </div>
moon's avatar
moon committed
                      <div class="col-sm-9">
                        {{ response.updatedAt }}
                      </div>
moon's avatar
moon committed
              <div
                v-if="editMode"
                class="panel panel-default"
              >
moon's avatar
moon committed
                <div class="panel-body">
                  <div class="container-fluid col-md-12">
                    <div v-if="showEditScientificDis">
                      <h3 class="mb-6 border-b">
                        Update Scientific Discipline
                      </h3>
                      <div class="row">
                        <div class="text col-sm-3 p-4">
                          Scientific Discipline
moon's avatar
moon committed
                        <div class="col-sm-9 p-4">
                          <div
                            v-for="options in scientificDisciplineOptions"
                            :key="options.id"
                          >
                            <input
                              :id="options.id"
                              v-model="selected"
                              type="checkbox"
                              class="h-6 w-6"
                              :name="options"
                              :value="options.discipline"
moon's avatar
moon committed
                            >
                            <label
                              class="mx-3"
                              :for="options.id"
                            >{{
moon's avatar
moon committed
                              options.discipline
                            }}</label>
                          </div>
moon's avatar
moon committed
                          <p
                            v-if="profile_error && scientificErrMsg"
                            class="text-red-500 font-bold mt-2"
                          >
                            {{ scientificErrMsg }}
                          </p>
                        </div>
moon's avatar
moon committed
                    </div>
moon's avatar
moon committed
                    <div v-if="showEditProfileLink">
moon's avatar
moon committed
                      <h3 class="mb-6 border-b">
                        Change Profile Link
                      </h3>
moon's avatar
moon committed
                      <div class="row">
moon's avatar
moon committed
                        <div class="text col-sm-3 p-4">
                          Profile Link
                        </div>
moon's avatar
moon committed
                        <div class="col-sm-9 p-4">
                          <input
                            id="inline-profile-link"
                            v-model.trim="profile_link"
                            class="
raghosh's avatar
raghosh committed
                              bg-white
                              w-1/3
                              py-4
                              px-4
                              rounded-lg
                              text-gray-700
                              bg-transparent
                              border border-gray-500
                              hover:border-gray-700
                            "
moon's avatar
moon committed
                            type="text"
                            placeholder="Enter profile link."
moon's avatar
moon committed
                          >
moon's avatar
moon committed
                          <p
                            v-if="profile_error && profileLinkErrMsg"
                            class="text-red-500 font-bold mt-2"
                          >
                            {{ profileLinkErrMsg }}
                          </p>
                        </div>
moon's avatar
moon committed
                    </div>
moon's avatar
moon committed
                    <div v-if="showChangePassword">
moon's avatar
moon committed
                      <h3 class="mb-6 border-b">
                        Change Password
                      </h3>
moon's avatar
moon committed
                      <div class="row">
moon's avatar
moon committed
                        <div class="text col-sm-3 p-4">
                          Current password
                        </div>
moon's avatar
moon committed
                        <div class="col-sm-9 p-4">
                          <input
                            id="current-password"
                            v-model.trim="currentPassword"
                            class="
raghosh's avatar
raghosh committed
                              bg-white
                              w-1/3
                              py-4
                              px-4
                              rounded-lg
                              text-gray-700
                              bg-transparent
                              border border-gray-500
                              hover:border-gray-700
                            "
moon's avatar
moon committed
                            type="password"
moon's avatar
moon committed
                          >
moon's avatar
moon committed
                        </div>
moon's avatar
moon committed
                      </div>
moon's avatar
moon committed
                      <div class="row">
moon's avatar
moon committed
                        <div class="text col-sm-3 p-4">
                          New Password
                        </div>
moon's avatar
moon committed
                        <div class="col-sm-9 p-4">
                          <input
                            id="inline-password"
                            v-model.trim="newPassword"
                            class="
raghosh's avatar
raghosh committed
                              bg-white
                              w-1/3
                              py-4
                              px-4
                              rounded-lg
                              text-gray-700
                              bg-transparent
                              border border-gray-500
                              hover:border-gray-700
                            "
moon's avatar
moon committed
                            type="password"
moon's avatar
moon committed
                          >
moon's avatar
moon committed
                        </div>
moon's avatar
moon committed
                      </div>
moon's avatar
moon committed
                      <div class="row">
                        <div class="text col-sm-3 p-4">
                          Confirm New Password
                        </div>
                        <div class="col-sm-9 p-4">
                          <input
                            id="confirm-password"
                            v-model.trim="confirmPassword"
                            class="
raghosh's avatar
raghosh committed
                              bg-white
                              w-1/3
                              py-4
                              px-4
                              rounded-lg
                              text-gray-700
                              bg-transparent
                              border border-gray-500
                              hover:border-gray-700
                            "
moon's avatar
moon committed
                            type="password"
moon's avatar
moon committed
                          >
moon's avatar
moon committed
                          <p
                            v-if="profile_error && passwordErrMsg"
                            class="text-red-500 font-bold mt-2"
                          >
                            {{ passwordErrMsg }}
                          </p>
                        </div>
moon's avatar
moon committed
                    </div>
moon's avatar
moon committed
                    <div class="flex space-x-4 mt-2">
                      <button
                        class="
raghosh's avatar
raghosh committed
                          bg-blue-500
                          text-xl
                          font-bold
                          rounded-lg
                          px-5
                          py-4
                          text-white
                          hover:bg-blue-700
                        "
moon's avatar
moon committed
                        @click="update(response)"
                      >
                        Update Profile
                      </button>
                      <button
                        class="
raghosh's avatar
raghosh committed
                          bg-gray-500
                          text-xl
                          font-bold
                          rounded-lg
                          px-5
                          py-4
                          text-white
                          hover:bg-gray-700
                        "
moon's avatar
moon committed
                        @click="close"
                      >
                        Cancel
                      </button>
                    </div>
moon's avatar
moon committed
                <p
                  v-if="profile_error && errorMsg"
                  class="text-red-500 font-bold mt-2"
                >
                  {{ errorMsg }}
                </p>
moon's avatar
moon committed
              </div>
raghosh's avatar
raghosh committed
              <!-- <button v-if="userData !== null && (getRole === 'Contributor' || getRole === 'Maintainer')"
                    class="btn btn-primary" @click="$router.push('/updateitem/new')">
              Create new Update Item
moon's avatar
moon committed
            </div>
          </slot>
        </template>
      </fetch-profile>
      <fetch-users v-if="getRole === 'Administrator'" :key="'users-' + updatedUsersKey">
moon's avatar
moon committed
        <template slot-scope="{ response, loading }">
moon's avatar
moon committed
          <slot
            :response="response"
            :loading="loading"
          >
moon's avatar
moon committed
            <div v-if="loading || response === null" />
            <div v-else>
moon's avatar
moon committed
              <h4 class="round">
                User List
              </h4>
              <user-table
                id="usersTable"
                :data="response"
moon's avatar
moon committed
              />
moon's avatar
moon committed
            </div>
          </slot>
        </template>
      </fetch-users>
moon's avatar
moon committed
  </div>
</template>

<script>
moon's avatar
moon committed
import FetchProfile from '@/components/CMS/fetchProfile';
import FetchUpdateItems from '@/components/CMS/fetchUpdateItems';
import FetchUsers from '@/components/CMS/fetchUsers';
import UserTable from '../components/UserTable.vue';
import BaseSpinner from '../components/UI/BaseSpinner.vue';
import BaseToaster from '../components/UI/BaseToaster.vue';
moon's avatar
moon committed
const _ = require('lodash');
let host = require('@/components/js/const').apiHost;
moon's avatar
moon committed

export default {
moon's avatar
moon committed
  name: 'ProfilePage',
moon's avatar
moon committed
  components: {
    FetchProfile,
    UserTable,
    FetchUsers,
    BaseSpinner,
    BaseToaster,
moon's avatar
moon committed
  },
  props: {
moon's avatar
moon committed
  },
  data() {
    return {
moon's avatar
moon committed
      user: '',
      motivation_text: '',
      current_role: '',
moon's avatar
moon committed
      current_affiliation: '',
      profile_link: '',
      currentPassword: '',
      newPassword: '',
      confirmPassword: '',
      isDev: process.env.NODE_ENV === 'development',
      toasterMessage: 'Profile update successful!',
      error: false,
      scientificDisciplineOptions: [
moon's avatar
moon committed
        { id: '1', discipline: 'Physics' },
        { id: '2', discipline: 'Chemistry' },
        { id: '3', discipline: 'Biology' },
        { id: '4', discipline: 'Computer Science' },
        { id: '5', discipline: 'Mathematics' },
      ],
      selected: [],
      isOpen: false,
      showEditScientificDis: false,
      showEditProfileLink: false,
      showChangePassword: false,
moon's avatar
moon committed
      scientificErrMsg: '',
      profileLinkErrMsg: '',
      passwordErrMsg: '',
      errorMsg: '',
      updatedKey: 0,
moon's avatar
moon committed
  },
  computed: {
moon's avatar
moon committed
      return this.$store.getters['User/jwt'];
    userData: function () {
moon's avatar
moon committed
      return this.$store.getters['User/userData'];
moon's avatar
moon committed
      return this.$store.getters['User/userRole'];
moon's avatar
moon committed
  mounted: function () {
    const vm = this;

    if (vm.userData === null) {
moon's avatar
moon committed
      this.$router.push('/login');
moon's avatar
moon committed
    } else {
      vm.user = vm.userData.id;
      vm.current_role = vm.userData.current_role;
      vm.scientific_discipline = vm.userData.scientific_discipline;
      if (vm.scientific_discipline === null) {
        vm.scientific_discipline = [];
      }
    }
  },
moon's avatar
moon committed
  methods: {
    close() {
      this.editMode = false;
      this.showEditScientificDis = false;
      this.showEditProfileLink = false;
      this.showChangePassword = false;
      this.error = false;
moon's avatar
moon committed
      this.scientificErrMsg = '';
      this.profileLinkErrMsg = '';
      this.passwordErrMsg = '';
moon's avatar
moon committed
      this.profile_link = '';
      this.password = '';
    },
    openScientificDisciplineEdit() {
      this.editMode = true;
      this.showEditScientificDis = true;
      this.showEditProfileLink = false;
      this.showChangePassword = false;
    },
    openProfileLinkEdit() {
      this.editMode = true;
      this.showEditScientificDis = false;
      this.showEditProfileLink = true;
      this.showChangePassword = false;
    },
    openChangePassword() {
      this.editMode = true;
      this.showEditScientificDis = false;
      this.showEditProfileLink = false;
      this.showChangePassword = true;
    },
    showDialog() {
      this.toasterMessage = 'Profile update successful!';
      this.toasterIsOpen = true;
    },
    hideDialog() {
      this.toasterIsOpen = false;
    },
    setRole(roleName) {
      //console.log("role name is,", roleName);
moon's avatar
moon committed
      window.localStorage.setItem('roleName', roleName);
      vm.$store.dispatch('User/setUserRole', roleName);
      // console.log("user data", e);
moon's avatar
moon committed
        host = require('@/components/js/const').devApiHost;
      vm.user = e.id;
      let dat;
      if (this.showEditScientificDis) {
        if (this.selected.length === 0) {
          this.error = true;
moon's avatar
moon committed
          this.scientificErrMsg = 'Please select at least one discipline.';
          return;
        }
        dat = {
          id: vm.user,
          scientific_discipline: vm.selected,
        };
      } else if (this.showEditProfileLink) {
        if (!this.profile_link) {
          this.error = true;
moon's avatar
moon committed
          this.profileLinkErrMsg = 'Please enter your profile link.';
          return;
        }
        dat = {
          id: vm.user,
          profile_link: vm.profile_link,
        };
      } else if (this.showChangePassword) {
moon's avatar
moon committed
        if (!this.currentPassword) {
          this.error = true;
moon's avatar
moon committed
          this.passwordErrMsg = 'Please enter the current password.';
moon's avatar
moon committed
          return;
        }
        if (!this.newPassword) {
moon's avatar
moon committed
          this.passwordErrMsg = 'Please enter new password.';
moon's avatar
moon committed
        if (!this.confirmPassword) {
          this.error = true;
moon's avatar
moon committed
          this.passwordErrMsg = 'Please enter new password again.';
moon's avatar
moon committed
          return;
        }

moon's avatar
moon committed
          identifier: vm.user,
          password: vm.currentPassword,
          newPassword: vm.newPassword,
          confirmPassword: vm.confirmPassword,
moon's avatar
moon committed
      this.scientificErrMsg = '';
      this.profileLinkErrMsg = '';
      this.passwordErrMsg = '';
      // let dat = {
      //   id: vm.user,
      //   profile_link: vm.profile_link,
      //   scientific_discipline: vm.selected,
      //   password: vm.password,
      // };
      // console.log(dat);
moon's avatar
moon committed
        let res;
        if (this.showChangePassword) {
          res = await this.axios.post(`${host}/api/password`, dat, {
            headers: {
              Authorization: `Bearer ${jwt}`,
            },
          });
          // console.log(res.data);
          const newJwt = res.data.jwt;
moon's avatar
moon committed
          window.localStorage.setItem('jwt', newJwt);
          this.$store.dispatch('User/setJwt', newJwt);
moon's avatar
moon committed
        } else {
          res = await this.axios.put(`${host}/api/users/${vm.user}`, dat, {
            headers: {
              Authorization: `Bearer ${jwt}`,
            },
          });
        }
        // console.log(res.data);
        this.toasterMessage = 'Profile update successful!';
        this.editMode = false;
        this.isOpen = false;
        setTimeout(() => {
raghosh's avatar
raghosh committed
          this.toasterIsOpen = false;
        }, 2000);
moon's avatar
moon committed
        this.profile_link = '';
        this.password = '';
        this.updatedKey += 1;
        // console.log(error.response.data.error.message)
        // console.log(error.response)
        this.error = true;
        this.errorMsg = error;
    async approve(e) {
      const vm = this

      try {
        vm.user = e.id;

        if (vm.isDev) {
          host = require('@/components/js/const').devApiHost;
        }

        let jwt = vm.jwt;
        if (jwt === null) {
          vm.loaded = false;
          return;
        }

        const dat = {
          id: vm.user,
          role: 3,  // Make the user contributor
        };

        let res = await this.axios.put(`${host}/api/users/${vm.user}`, dat, {
          headers: {
            Authorization: `Bearer ${jwt}`,
          },
        });

        jwt = require('@/components/js/const').wikiApikey;

        const query = `mutation User {
            users {
              create (email: "${e.email}",
                name: "${e.full_name}",
                passwordRaw: "welcome2cdcode",
                providerKey: "local",
                groups: 3,
                mustChangePassword: true,
                sendWelcomeEmail: true) {
              responseResult {
                succeeded,
                errorCode,
                slug,
                message
              },
              user {
                email,
                name
                }
              }
            }
          }`

        res = await this.axios.post(`https://wiki.cd-code.org/graphql`, { query }, {
          headers: {
            Authorization: `Bearer ${jwt}`,
          },
        });

        vm.error = false;
        vm.toasterMessage = 'Approved and a welcome email sent!';
        vm.toasterIsOpen = true;
        setTimeout(() => {
          vm.toasterIsOpen = false;
        }, 2000);

        vm.updatedUsersKey += 1;
      } catch (error) {
        this.error = true;
        this.errorMsg = error;
      }
    }
moon's avatar
moon committed
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
@import url("~@/assets/bootstrap.css");
moon's avatar
moon committed

.main {
  margin: 1.5rem;
}

h3 {
  margin: 40px 0 0;
}

  color: #ef0087 !important;
moon's avatar
moon committed

.panel {
  font-size: 1.2rem;
}

ul.a {
  list-style-type: disc;
  list-style-position: inside;
}
</style>