Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Svelte: Implement and instantiate FilePopover #62498

Merged
merged 5 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
63 changes: 63 additions & 0 deletions client/web-sveltekit/src/lib/repo/filePopover/FilePopover.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
query FileOrDirPopoverQuery($repoName: String!, $revision: String!, $filePath: String!) {
repository(name: $repoName) {
commit(rev: $revision) {
path(path: $filePath) {
...on GitBlob {
...FilePopoverFragment
}
...on GitTree {
...DirPopoverFragment
}
}
}
}
}

fragment FilePopoverFragment on GitBlob {
__typename
path
languages
byteSize
totalLines
history(first: 1) {
nodes {
commit {
...FilePopoverLastCommitFragment
}
}
}
...FileIcon_GitBlob
}

fragment DirPopoverFragment on GitTree {
__typename
path
# TODO(camdencheek): fix this to use a count, which currently does not exist in our API.
# This currently does not scale well with very large directories.
files {
name
}
directories {
name
}
jasonhawkharris marked this conversation as resolved.
Show resolved Hide resolved
history(first: 1) {
nodes {
commit {
...FilePopoverLastCommitFragment
}
}
}
}

fragment FilePopoverLastCommitFragment on GitCommit {
abbreviatedOID
oid
subject
canonicalURL
author {
date
person {
...Avatar_Person
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<script lang="ts" context="module">
import { Story } from '@storybook/addon-svelte-csf'

import type { FilePopoverFragment, DirPopoverFragment, FilePopoverLastCommitFragment } from './FilePopover.gql'
import FilePopover from './FilePopover.svelte'

export const meta = {
component: FilePopover,
}

const lastCommit: FilePopoverLastCommitFragment = {
abbreviatedOID: '1234567',
oid: '1234567890123456789012345678901234567890',
subject: 'Test subject',
canonicalURL: 'https://sourcegraph.com/about',
author: {
date: '2021-01-01T00:00:00Z',
person: {
__typename: 'Person',
name: 'camdencheek',
avatarURL: 'https://github.com/camdencheek.png',
displayName: 'Camden Cheek',
},
},
}

const fileEntry: FilePopoverFragment = {
__typename: 'GitBlob',
name: 'results.go',
path: 'internal/search/results/results.go',
languages: ['Go'],
byteSize: 325,
totalLines: 12,
history: {
nodes: [
{
commit: lastCommit,
},
],
},
}

const dirEntry: DirPopoverFragment = {
__typename: 'GitTree',
path: 'internal/search/results',
files: [{ name: 'results.go' }, { name: 'results_test.go' }],
directories: [{ name: 'testdata' }],
history: {
nodes: [{ commit: lastCommit }],
},
}
</script>

<Story name="Default">
<FilePopover repoName={'github.com/sourcegraph/sourcegraph'} entry={fileEntry} />

<FilePopover repoName={'github.com/sourcegraph/sourcegraph'} entry={dirEntry} />
</Story>
188 changes: 188 additions & 0 deletions client/web-sveltekit/src/lib/repo/filePopover/FilePopover.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
<script lang="ts" context="module">
import { type DirPopoverFragment, type FilePopoverFragment, FileOrDirPopoverQuery } from './FilePopover.gql'

export interface FilePopoverInputs {
repoName: string
revision: string
filePath: string
}

export async function fetchPopoverData(args: FilePopoverInputs): Promise<DirPopoverFragment | FilePopoverFragment> {
const client = getGraphQLClient()
const result = await client.query(FileOrDirPopoverQuery, args)
if (result.error) {
throw new Error('could not fetch file or dir popover', result.error)
}
const fragment = result.data?.repository?.commit?.path
if (!fragment) {
throw new Error('entry does not exist')
}
return fragment
}
</script>

<script lang="ts">
import { mdiFolder } from '@mdi/js'

import Avatar from '$lib/Avatar.svelte'
import { pluralize } from '$lib/common'
import { getGraphQLClient } from '$lib/graphql'
import Icon from '$lib/Icon.svelte'
import { displayRepoName } from '$lib/shared'
import Timestamp from '$lib/Timestamp.svelte'
import { formatBytes } from '$lib/utils'
import Badge from '$lib/wildcard/Badge.svelte'

import FileIcon from '../FileIcon.svelte'

import NodeLine from './NodeLine.svelte'

export let repoName: string
export let entry: FilePopoverFragment | DirPopoverFragment

function splitPath(filePath: string): [string, string] {
let parts = filePath.split('/')
return [parts.slice(0, parts.length - 1).join('/'), parts[parts.length - 1]]
}

$: [dirName, baseName] = splitPath(entry.path)
$: lastCommit = entry.history.nodes[0].commit
</script>

<div class="root section muted">
<div class="repo-and-path section mono">
<small>
{displayRepoName(repoName).replaceAll('/', ' / ')}
·
{dirName ? `${dirName.replaceAll('/', ' / ')}` : '/'}
</small>
</div>

<div class="lang-and-file section">
{#if entry.__typename === 'GitBlob'}
<FileIcon file={entry} inline={false} --icon-size="1.5rem" />
<div class="file mono">
<div>{baseName}</div>
<small>
{entry.languages[0] ? `${entry.languages[0]} ·` : ''}
{entry.totalLines}
{pluralize('Line', entry.totalLines)} ·
{formatBytes(entry.byteSize)}
</small>
</div>
{:else if entry.__typename === 'GitTree'}
<Icon svgPath={mdiFolder} --icon-fill-color="var(--primary)" --icon-size="1.5rem" />
<div class="file mono">
<div class="title">{baseName}</div>
<small>
Subdirectories {entry.directories.length}
· Files {entry.files.length}
</small>
</div>
{/if}
</div>

<div class="last-changed section">Last Changed @</div>

<div class="commit">
<div class="node-line"><NodeLine /></div>
<div class="commit-info">
<Badge variant="link">
<a href={lastCommit.canonicalURL} target="_blank">
{lastCommit.abbreviatedOID}
</a>
</Badge>
<div class="body">{lastCommit.subject}</div>
<div class="author">
<Avatar avatar={lastCommit.author.person} --avatar-size="1.0rem" />
{lastCommit.author.person.displayName}
·
<Timestamp date={lastCommit.author.date} />
</div>
</div>
</div>
</div>

<style lang="scss">
.root {
width: 400px;
background: var(--body-bg);

.section {
padding: 0.5rem 1rem;
}

.repo-and-path {
border-bottom: 1px solid var(--border-color);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

.lang-and-file {
display: flex;
align-items: center;
gap: 1rem;

.file {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 0.25rem;

div {
color: var(--text-body);
}
}
}

.last-changed {
background-color: var(--secondary-4);
border-bottom: 1px solid var(--border-color);
}

.commit {
display: flex;
align-items: stretch;
justify-content: flex-start;

.node-line {
flex: 0 0 40px;
}

.commit-info {
flex: 1;

display: flex;
flex-direction: column;
align-items: flex-start;
gap: 0.25rem;
padding: 0.5rem 0.5rem 0.5rem 0;

.author {
display: flex;
justify-content: flex-start;
align-items: center;
gap: 0.25rem;
font-size: var(--font-size-tiny);
}
}
}
}

.mono {
font-family: var(--monospace-font-family);
}

.title {
color: var(--text-title);
}

.muted {
color: var(--text-muted);
}

.body {
color: var(--text-body);
}
</style>
29 changes: 29 additions & 0 deletions client/web-sveltekit/src/lib/repo/filePopover/NodeLine.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<div class="line">
<div class="connector" />
<div class="circle" />
<div class="connector" />
</div>

<style lang="scss">
$circle-size: 8px;

.line {
display: flex;
flex-direction: column;
align-items: center;
height: 100%;

.connector {
border-left: 1px solid var(--border-color);
flex-grow: 1;
}

.circle {
height: $circle-size;
width: $circle-size;
border-radius: 50%;
border: 2px solid var(--border-color);
flex-grow: 0;
}
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@
}

$: if (!!lastCommitQuery) {
// Reset commit history when the query observable changes. Without
// this we are showing the commit history of the previously selected
// file/folder until the new commit history is loaded.
// Reset last commit when the query observable changes. Without
// this we are showing the last commit of the previously selected
// file/folder until the last commit is loaded.
lastCommit = null
}

Expand Down