Quellcode durchsuchen

refactor: refactor create team modal to new system

Andrew Bastin vor 4 Jahren
Ursprung
Commit
7ab1bbaf62

+ 56 - 51
packages/hoppscotch-app/components/teams/Add.vue

@@ -1,5 +1,5 @@
 <template>
-  <SmartModal v-if="show" :title="$t('team.new')" @close="hideModal">
+  <SmartModal v-if="show" :title="$t('team.new').toString()" @close="hideModal">
     <template #body>
       <div class="flex flex-col px-2">
         <input
@@ -19,9 +19,12 @@
     </template>
     <template #footer>
       <span>
-        <ButtonPrimary :label="$t('action.save')" @click.native="addNewTeam" />
+        <ButtonPrimary
+          :label="$t('action.save').toString()"
+          @click.native="addNewTeam"
+        />
         <ButtonSecondary
-          :label="$t('action.cancel')"
+          :label="$t('action.cancel').toString()"
           @click.native="hideModal"
         />
       </span>
@@ -29,54 +32,56 @@
   </SmartModal>
 </template>
 
-<script>
-import { defineComponent } from "@nuxtjs/composition-api"
-import * as teamUtils from "~/helpers/teams/utils"
+<script setup lang="ts">
+import { ref, useContext } from "@nuxtjs/composition-api"
+import { pipe } from "fp-ts/function"
+import * as TE from "fp-ts/TaskEither"
+import { createTeam } from "~/helpers/backend/mutations/Team"
+import { TeamNameCodec } from "~/helpers/backend/types/TeamName"
 
-export default defineComponent({
-  props: {
-    show: Boolean,
-  },
-  data() {
-    return {
-      name: null,
-    }
-  },
-  methods: {
-    addNewTeam() {
-      // We save the user input in case of an error
-      const name = this.name
-      // We clear it early to give the UI a snappy feel
-      this.name = ""
-      if (!name) {
-        this.$toast.error(this.$t("empty.team_name"), {
-          icon: "error_outline",
-        })
-        return
-      }
-      if (name !== null && name.replace(/\s/g, "").length < 6) {
-        this.$toast.error(this.$t("team.name_length_insufficient"), {
-          icon: "error_outline",
-        })
-        return
+const {
+  app: { i18n },
+  $toast,
+} = useContext()
+
+const $t = i18n.t.bind(i18n)
+
+defineProps<{
+  show: boolean
+}>()
+
+const emit = defineEmits<{
+  (e: "hide-modal"): void
+}>()
+
+const name = ref<string | null>(null)
+
+const addNewTeam = () =>
+  pipe(
+    TeamNameCodec.decode(name.value), // Perform decode (returns either)
+    TE.fromEither, // Convert either to a task either
+    TE.mapLeft(() => "invalid_name" as const), // Failure above is an invalid_name, give it an identifiable value
+    TE.chainW(createTeam), // Create the team
+    TE.match(
+      (err) => {
+        // err is of type "invalid_name" | GQLError<Err>
+        if (err === "invalid_name") {
+          $toast.error($t("team.name_length_insufficient").toString(), {
+            icon: "error_outline",
+          })
+        } else {
+          // Handle GQL errors (use err obj)
+        }
+      },
+      () => {
+        // Success logic ?
+        hideModal()
       }
-      // Call to the graphql mutation
-      teamUtils
-        .createTeam(this.$apollo, name)
-        .then(() => {
-          this.hideModal()
-        })
-        .catch((e) => {
-          console.error(e)
-          // We restore the initial user input
-          this.name = name
-        })
-      this.hideModal()
-    },
-    hideModal() {
-      this.name = null
-      this.$emit("hide-modal")
-    },
-  },
-})
+    )
+  )()
+
+const hideModal = () => {
+  name.value = null
+  emit("hide-modal")
+}
 </script>

+ 7 - 2
packages/hoppscotch-app/components/teams/Team.vue

@@ -4,7 +4,7 @@
       <div class="p-4">
         <label
           class="cursor-pointer transition hover:text-secondaryDark"
-          @click="team.myRole === 'OWNER' ? $emit('edit-team') : ''"
+          @click="team.myRole === 'OWNER' ? emit('edit-team') : ''"
         >
           {{ team.name || $t("state.nothing_found") }}
         </label>
@@ -36,7 +36,7 @@
           :label="$t('action.edit').toString()"
           @click.native="
             () => {
-              $emit('edit-team')
+              emit('edit-team')
               $refs.options.tippy().hide()
             }
           "
@@ -94,6 +94,11 @@ const props = defineProps<{
   teamID: string
 }>()
 
+const emit = defineEmits<{
+  (e: "edit-team"): void
+  
+}>()
+
 const {
   app: { i18n },
   $toast,

+ 36 - 1
packages/hoppscotch-app/helpers/backend/mutations/Team.ts

@@ -1,12 +1,47 @@
 import gql from "graphql-tag"
+import { pipe } from "fp-ts/function"
+import * as TE from "fp-ts/TaskEither"
 import { runMutation } from "../GQLClient"
+import { TeamName } from "../types/TeamName"
 
 type DeleteTeamErrors =
   | "team/not_required_role"
   | "team/invalid_id"
   | "team/member_not_found"
+  | "ea/not_invite_or_admin"
 
-type ExitTeamErrors = "team/invalid_id" | "team/member_not_found"
+type ExitTeamErrors =
+  | "team/invalid_id"
+  | "team/member_not_found"
+  | "ea/not_invite_or_admin"
+
+type CreateTeamErrors = "team/name_invalid" | "ea/not_invite_or_admin"
+
+export const createTeam = (name: TeamName) =>
+  pipe(
+    runMutation<
+      {
+        createTeam: {
+          id: string
+          name: string
+        }
+      },
+      CreateTeamErrors
+    >(
+      gql`
+        mutation CreateTeam($name: String!) {
+          createTeam(name: $name) {
+            id
+            name
+          }
+        }
+      `,
+      {
+        name,
+      }
+    ),
+    TE.map(({ createTeam }) => createTeam)
+  )
 
 export const deleteTeam = (teamID: string) =>
   runMutation<void, DeleteTeamErrors>(

+ 1 - 1
packages/hoppscotch-app/helpers/backend/types/TeamName.ts

@@ -6,7 +6,7 @@ interface TeamNameBrand {
 
 export const TeamNameCodec = t.brand(
   t.string,
-  (x): x is t.Branded<string, TeamNameBrand> => x.length > 6,
+  (x): x is t.Branded<string, TeamNameBrand> => x.trim().length > 6,
   "TeamName"
 )