Radish alpha
r
Radicle desktop app
Radicle
Git (anonymous pull)
Log in to clone via SSH
Allow editing issue titles
Rūdolfs Ošiņš committed 1 year ago
commit 6052098c18ff08d6fb42f8cbbdfcf059e354564f
parent 79dbe7875195fe6e9df2b4951f9070acb214f395
3 files changed +105 -10
modified src/components/Border.svelte
@@ -1,5 +1,5 @@
<script lang="ts">
-
  export let variant: "primary" | "secondary" | "ghost" | "float";
+
  export let variant: "primary" | "secondary" | "ghost" | "float" | "danger";
  export let hoverable: boolean = false;
  export let onclick: (() => void) | undefined = undefined;

modified src/components/TextInput.svelte
@@ -10,6 +10,9 @@
  export let autofocus: boolean = false;
  export let autoselect: boolean = false;
  export let disabled: boolean = false;
+
  export let onSubmit: (() => void) | undefined = undefined;
+
  export let onDismiss: (() => void) | undefined = undefined;
+
  export let valid: boolean = true;

  let inputElement: HTMLInputElement | undefined = undefined;
  let focussed = false;
@@ -26,6 +29,17 @@
      inputElement.select();
    }
  });
+

+
  function handleKeydown(event: KeyboardEvent) {
+
    if (event.key === "Enter" && valid && onSubmit) {
+
      onSubmit();
+
    }
+

+
    if (event.key === "Escape" && onDismiss) {
+
      inputElement?.blur();
+
      onDismiss();
+
    }
+
  }
</script>

<style>
@@ -42,6 +56,7 @@
    margin: 0;
    height: 32px;
    padding: 0.25rem 0.75rem;
+
    border: 0;
  }
  input::placeholder {
    font-family: var(--font-family-sans-serif);
@@ -53,7 +68,9 @@
  }
</style>

-
<Border variant={focussed ? "secondary" : "ghost"} styleWidth="100%">
+
<Border
+
  variant={valid ? (focussed ? "secondary" : "ghost") : "danger"}
+
  styleWidth="100%">
  <input
    on:focus={() => {
      focussed = true;
@@ -69,5 +86,6 @@
    bind:value
    autocomplete="off"
    spellcheck="false"
+
    on:keydown|stopPropagation={handleKeydown}
    on:input />
</Border>
modified src/views/repo/Issue.svelte
@@ -32,6 +32,7 @@

  import Layout from "./Layout.svelte";
  import { tick } from "svelte";
+
  import TextInput from "@app/components/TextInput.svelte";

  export let repo: RepoInfo;
  export let issue: Issue;
@@ -39,12 +40,16 @@
  export let config: Config;

  let topLevelReplyOpen = false;
+
  let editingTitle = false;
+
  let updatedTitle: string = issue.title;

-
  // Close the comment textbox when switching between issues. The view doesn't
-
  // get destroyed when we switch between different issues in the sidebar and
-
  // because of that the top-level state gets retained when the issue changes.
+
  // The view doesn't get destroyed when we switch between different issues in
+
  // the sidebar and because of that the top-level state gets retained when the
+
  // issue changes.
  $: if (issue) {
    topLevelReplyOpen = false;
+
    editingTitle = false;
+
    updatedTitle = issue.title;
  }

  $: project = repo.payloads["xyz.radicle.project"]!;
@@ -137,6 +142,32 @@
    }
  }

+
  async function editTitle(id: string, title: string) {
+
    if (issue.title === updatedTitle) {
+
      editingTitle = false;
+
      return;
+
    }
+

+
    try {
+
      await invoke("edit_issue", {
+
        rid: repo.rid,
+
        cobId: issue.id,
+
        action: {
+
          type: "edit",
+
          id,
+
          title,
+
        },
+
        opts: { announce: $announce },
+
      });
+
      editingTitle = false;
+
      issue.title = updatedTitle;
+
    } catch (error) {
+
      if (error instanceof Error) {
+
        console.error("Issue editing failed: ", error);
+
      }
+
    }
+
  }
+

  async function reactOnComment(
    publicKey: string,
    commentId: string,
@@ -173,8 +204,12 @@
    font-weight: var(--font-weight-medium);
    -webkit-user-select: text;
    user-select: text;
-
    margin-bottom: 1rem;
-
    margin-top: 0.35rem;
+
    margin-bottom: 20px;
+
    margin-top: 6px;
+
    display: flex;
+
    align-items: center;
+
    justify-content: space-between;
+
    word-break: break-all;
  }
  .issue-body {
    margin-top: 1rem;
@@ -212,6 +247,12 @@
    margin-left: 1.25rem;
    background-color: var(--color-background-float);
  }
+

+
  .title-icons {
+
    display: flex;
+
    gap: 0.5rem;
+
    margin-left: 1rem;
+
  }
</style>

<Layout>
@@ -283,9 +324,45 @@
  </svelte:fragment>

  <div class="content">
-
    <div class="title">
-
      <InlineTitle content={issue.title} fontSize="medium" />
-
    </div>
+
    {#if editingTitle}
+
      <div class="global-flex" style:margin-bottom="0.5rem">
+
        <TextInput
+
          valid={updatedTitle.trim().length > 0}
+
          bind:value={updatedTitle}
+
          autofocus
+
          onSubmit={() => {
+
            if (updatedTitle.trim().length > 0) {
+
              editTitle(issue.id, updatedTitle);
+
            }
+
          }}
+
          onDismiss={() => {
+
            updatedTitle = issue.title;
+
            editingTitle = !editingTitle;
+
          }} />
+
        <div class="title-icons">
+
          <Icon
+
            name="checkmark"
+
            onclick={() => {
+
              if (updatedTitle.trim().length > 0) {
+
                editTitle(issue.id, updatedTitle);
+
              }
+
            }} />
+
          <Icon
+
            name="cross"
+
            onclick={() => {
+
              updatedTitle = issue.title;
+
              editingTitle = !editingTitle;
+
            }} />
+
        </div>
+
      </div>
+
    {:else}
+
      <div class="title">
+
        <InlineTitle content={issue.title} fontSize="medium" />
+
        <div class="title-icons">
+
          <Icon name="pen" onclick={() => (editingTitle = !editingTitle)} />
+
        </div>
+
      </div>
+
    {/if}

    <IssueMetadata {issue} />