Procházet zdrojové kódy

fix query param toggling and add input fields for adding them

biblius před 1 týdnem
rodič
revize
05780022bb
2 změnil soubory, kde provedl 154 přidání a 92 odebrání
  1. 153 91
      src/lib/components/WorkspaceEntry.svelte
  2. 1 1
      src/lib/state.svelte.ts

+ 153 - 91
src/lib/components/WorkspaceEntry.svelte

@@ -36,6 +36,7 @@
   import AuthParams from "./AuthParams.svelte";
   import Response from "./Response.svelte";
   import Checkbox from "./ui/checkbox/checkbox.svelte";
+  import { tick } from "svelte";
 
   let isSending = $derived.by(isRequestSending);
 
@@ -63,8 +64,15 @@
     }
   });
 
+  // Used for inputs in the URL bar
   let updateUrlTimeout: number | undefined = $state();
 
+  // Used for inputs in the query params
+  let addQueryTimeout: number | undefined = $state();
+
+  let addQueryParamKeyInput: string | undefined = $state();
+  let addQueryParamValInput: string | undefined = $state();
+
   async function handleRequest() {
     if (isRequestSending()) {
       try {
@@ -87,7 +95,7 @@
     }
   }
 
-  async function handleUrlUpdate(update: UrlUpdate) {
+  function handleUrlUpdate(update: UrlUpdate) {
     if (updateUrlTimeout != undefined) {
       clearTimeout(updateUrlTimeout);
     }
@@ -114,6 +122,41 @@
       }
     }, 200);
   }
+
+  function handleAddQueryParam() {
+    if (addQueryTimeout != undefined) {
+      clearTimeout(addQueryTimeout);
+    }
+    addQueryTimeout = setTimeout(async () => {
+      const key = addQueryParamKeyInput ? addQueryParamKeyInput : "";
+      const val = addQueryParamValInput ? addQueryParamValInput : "";
+
+      if (_state.entry.query.length === 0) {
+        _state.entry.url += `?${key}=${val}`;
+      } else {
+        _state.entry.url += `&${key}=${val}`;
+      }
+
+      await updateUrl({
+        type: "URL",
+        url: _state.entry.url,
+      });
+
+      await tick(); // wait for DOM update
+
+      addQueryParamValInput = "";
+      addQueryParamKeyInput = "";
+
+      // Added param will always be last
+      const param = _state.entry.query[_state.entry.query.length - 1];
+
+      if (key) {
+        document.getElementById(`${param.id}_query_key`)?.focus();
+      } else {
+        document.getElementById(`${param.id}_query_val`)?.focus();
+      }
+    }, 200);
+  }
 </script>
 
 {#snippet authParams(
@@ -301,13 +344,54 @@
           <div class="flex-1 overflow-auto p-2">
             <!-- ================= PARAMETERS ================= -->
 
-            <!-- ================= PATH ================= -->
+            <!-- ================= HEADERS ================= -->
+
+            <div>
+              <h3
+                class="mb-2 pb-1 pointer-events-none text-xs font-medium border-b border-secondary text-muted-foreground"
+              >
+                Headers
+              </h3>
+              <div
+                class="grid grid-cols-[2%_1fr_1fr_2%] items-center justify-center gap-2 text-sm"
+              >
+                {#each _state.entry.headers as header (header.id)}
+                  <Input
+                    class="col-start-2"
+                    bind:value={header.name}
+                    placeholder="Name"
+                    oninput={() =>
+                      updateHeader(header.id, header.name, header.value)}
+                  />
+
+                  <Input
+                    class="col-start-3"
+                    bind:value={header.value}
+                    placeholder="Value"
+                    oninput={() =>
+                      updateHeader(header.id, header.name, header.value)}
+                  />
+
+                  <Trash
+                    class="col-start-4 h-4 w-4 cursor-pointer text-muted-foreground hover:text-destructive"
+                    onclick={() => deleteHeader(header.id)}
+                  />
+                {/each}
+
+                <PlusIcon
+                  class="border p-1 rounded-2xl mx-auto col-span-3 cursor-pointer"
+                  onclick={() => insertHeader()}
+                />
+              </div>
+            </div>
 
             <Tabs.Content value="params" class="space-y-4">
+              <!-- ================= PATH ================= -->
+
               {#if _state.entry?.path?.length > 0}
                 <div>
                   <h3
-                    class="mb-2 pointer-events-none text-xs font-medium border-b border-secondary text-muted-foreground"
+                    class="mb-2 pb-1 pointer-events-none text-xs font-medium border-b border-secondary text-muted-foreground"
                   >
                     Path
                   </h3>
@@ -340,65 +424,79 @@
 
               <!-- ================= QUERY ================= -->
 
-              {#if _state.entry?.query?.length > 0}
-                <div>
-                  <h3
-                    class="mb-2 pointer-events-none text-xs font-medium border-b border-secondary text-muted-foreground"
-                  >
-                    Query
-                  </h3>
-                  <div
-                    class="grid grid-cols-[2%_1fr_1fr_2%] items-center justify-center gap-2 text-sm"
-                  >
-                    {#each _state.entry.query as param}
-                      <div class="flex justify-center">
-                        <Checkbox
-                          checked={param.position != null}
-                          onCheckedChange={() => updateQueryParamEnabled(param)}
-                        />
-                      </div>
-                      <Input
-                        class={param.position == null
-                          ? `text-muted-foreground opacity-75`
-                          : ""}
-                        bind:value={param.key}
-                        placeholder="key"
-                        oninput={() =>
-                          handleUrlUpdate({
-                            type: "Query",
-                            url: _state.entry.url,
-                            param,
-                          })}
+              <div>
+                <h3
+                  class="mb-2 pb-1 pointer-events-none text-xs font-medium border-b border-secondary text-muted-foreground"
+                >
+                  Query
+                </h3>
+                <div
+                  class="grid grid-cols-[2%_1fr_1fr_2%] items-center justify-center gap-2 text-sm"
+                >
+                  {#each _state.entry.query as param (param.id)}
+                    <div class="flex justify-center">
+                      <Checkbox
+                        checked={param.position != null}
+                        onCheckedChange={() => updateQueryParamEnabled(param)}
                       />
-                      <Input
-                        class={param.position == null
-                          ? `text-muted-foreground opacity-75`
-                          : ""}
-                        bind:value={param.value}
-                        placeholder="value"
-                        oninput={() =>
-                          handleUrlUpdate({
-                            type: "Query",
-                            url: _state.entry.url,
-                            param,
-                          })}
+                    </div>
+                    <Input
+                      id={`${param.id}_query_key`}
+                      class={param.position == null
+                        ? `text-muted-foreground opacity-75`
+                        : ""}
+                      bind:value={param.key}
+                      placeholder="key"
+                      oninput={() =>
+                        handleUrlUpdate({
+                          type: "Query",
+                          url: _state.entry.url,
+                          param,
+                        })}
+                    />
+                    <Input
+                      id={`${param.id}_query_val`}
+                      class={param.position == null
+                        ? `text-muted-foreground opacity-75`
+                        : ""}
+                      bind:value={param.value}
+                      placeholder="value"
+                      oninput={() =>
+                        handleUrlUpdate({
+                          type: "Query",
+                          url: _state.entry.url,
+                          param,
+                        })}
+                    />
+                    <div class="flex justify-center">
+                      <Trash
+                        class="h-4 w-4 cursor-pointer text-muted-foreground hover:text-destructive"
+                        onclick={() => deleteQueryParam(param)}
                       />
-                      <div class="flex justify-center">
-                        <Trash
-                          class="h-4 w-4 cursor-pointer text-muted-foreground hover:text-destructive"
-                          onclick={() => deleteQueryParam(param)}
-                        />
-                      </div>
-                    {/each}
-                  </div>
+                    </div>
+                  {/each}
+                  <!-- ================= ADD QUERY PARAM ================= -->
+
+                  <Input
+                    class="col-start-2"
+                    bind:value={addQueryParamKeyInput}
+                    placeholder="Key"
+                    oninput={() => handleAddQueryParam()}
+                  />
+                  <Input
+                    class="col-start-3"
+                    bind:value={addQueryParamValInput}
+                    placeholder="Value"
+                    oninput={() => handleAddQueryParam()}
+                  />
                 </div>
-              {/if}
+              </div>
 
               <!-- ================= BODY ================= -->
 
-              <div class="space-y-4">
+              <div>
                 <h3
-                  class="mb-2 pointer-events-none text-xs font-medium border-b border-secondary text-muted-foreground"
+                  class="mb-2 pb-1 pointer-events-none text-xs font-medium border-b border-secondary text-muted-foreground"
                 >
                   Body
                 </h3>
@@ -447,42 +545,6 @@
               </div>
             </Tabs.Content>
 
-            <!-- ================= HEADERS ================= -->
-
-            <Tabs.Content value="headers">
-              <div
-                class="w-10/12 mx-auto grid grid-cols-[auto_1fr] gap-2 items-center"
-              >
-                {#each _state.entry.headers as header}
-                  <div class="contents">
-                    <Input
-                      bind:value={header.name}
-                      placeholder="Name"
-                      oninput={() =>
-                        updateHeader(header.id, header.name, header.value)}
-                    />
-
-                    <Input
-                      bind:value={header.value}
-                      placeholder="Value"
-                      oninput={() =>
-                        updateHeader(header.id, header.name, header.value)}
-                    />
-
-                    <Trash
-                      class="h-4 w-4 cursor-pointer text-muted-foreground hover:text-destructive"
-                      onclick={() => deleteHeader(header.id)}
-                    />
-                  </div>
-                {/each}
-
-                <PlusIcon
-                  class="border p-1 rounded-2xl mx-auto col-span-3 cursor-pointer"
-                  onclick={() => insertHeader()}
-                />
-              </div>
-            </Tabs.Content>
-
             <!-- ================= AUTH ================= -->
 
             <Tabs.Content value="auth" class="space-y-4">

+ 1 - 1
src/lib/state.svelte.ts

@@ -640,7 +640,7 @@ export async function updateQueryParamEnabled(param: QueryParam) {
   // Param was removed, offset all positions
   if (newQp.position == null) {
     for (const q of state.entry.query) {
-      if (q.position < param.position!!) {
+      if (q.position == null || q.position < param.position!!) {
         continue;
       }
       // +1 for the &, +1 for the =