From d2cac7f5d21d9c9f1ed4d0feaa2d967a4740367a Mon Sep 17 00:00:00 2001 From: Konstantinos Maninakis Date: Mon, 22 Jan 2024 13:37:43 +0100 Subject: [PATCH] feat(patch-detail): [wip] add revision section with selector and metadata - adds section headings - polishes typography and whitespace - not all revision metadata are shown (e.g. reviews, etc) - patch description and new Activity section use mock data Signed-off-by: Konstantinos Maninakis --- CHANGELOG.md | 5 +- src/types/httpd.ts | 25 +- src/utils/patch.ts | 2 + src/ux/patchesView.ts | 4 +- src/webviews/postcss.config.js | 2 + src/webviews/src/assets/index.css | 14 +- src/webviews/src/components/PatchDetail.vue | 322 +++++++++++++++++- src/webviews/src/components/PatchMetadata.vue | 35 +- .../src/components/PatchStatusBadge.vue | 2 +- src/webviews/src/stores/patchDetailStore.ts | 1 + src/webviews/vite.config.ts | 4 +- 11 files changed, 376 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e925ed8..066d6211 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,10 @@ - can be opened via a new button "View Patch Details" on each item in the list of Patches - panel's title shows the patch description in full if it's short, otherwise truncated to the nearest full word fitting the limit - the following Patch info are shown in the new view - - status + - status (e.g. open, merged, archived, ...) - the status badge's background color is a dynamic color mix of the patch status color and the dynamic editor-foreground inherited from vscode's current theme so as to ensure text contrast reaching at least [WCAAG AA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_WCAG/Perceivable/Color_contrast) level of accessibility at all times while also retaining a relative consistency of the colors across all our UIs - major events like "created", "last updated", "merged" and related info with logic crafting optimal copy for each case (see similar tooltip improvements below) + - checked-out indicator, if the Git branch associated with this Radicle Patch is currently checked out - id (with on-hover button to copy Patch identifier to clipboard) - revision authors - labels @@ -24,6 +25,8 @@ - a "Check Out Default" button that checks out the Git branch marked as default for the Radicle project - shown only if the Patch is checked out - Patch check-out status remains in sync across all views and the actual underlying Git state as the latter changes + - TODO: maninak document all of revision section's features + - TODO: maninak revision description is hidden under an expandable-on-click control (to avoid showing the same content twice) if the selected revision is the first revision - **commands**: add new command to check out the current Radicle project's default Git branch - **patch-list:** show button to "Check Out Default Git Branch" for the currently checked-out Patch on the list - **patch-list:** auto-retry fetching list of Patches from httpd (with geometric backoff) if an error occured diff --git a/src/types/httpd.ts b/src/types/httpd.ts index 0662ed73..6a3fd606 100644 --- a/src/types/httpd.ts +++ b/src/types/httpd.ts @@ -34,7 +34,7 @@ export interface Project { delegates: Did[] patches: { [K in PatchStatus]: number } issues: { open: number; closed: number } - trackings: number + trackings: number // TODO: maninak rename to seeding } export interface Merge { @@ -44,13 +44,15 @@ export interface Merge { timestamp: number } -export type PatchStatus = 'draft' | 'open' | 'archived' | 'merged' - export interface Patch { id: string title: string author: RadicleIdentity - state: { status: PatchStatus } + state: + | { status: 'draft' } + | { status: 'open'; conflicts?: [string, string][] } + | { status: 'archived' } + | { status: 'merged'; revision: string; commit: string } // TODO: maninak utilized new `revision` field target: string labels: string[] merges: Merge[] @@ -58,6 +60,8 @@ export interface Patch { revisions: ArrayMinLength } +export type PatchStatus = Patch['state']['status'] + export function isPatch(x: unknown): x is Patch { const patch = x as Partial | undefined const isPatch = @@ -79,9 +83,18 @@ export interface Revision { id: string author: RadicleIdentity description: string + edits: { + author: RadicleIdentity + body: string + embeds: Embed[] + timestamp: number + }[] + /** + * The value is a commit hash + */ base: string /** - * a.k.a. Object Identifier. The value is the commit hash. + * a.k.a. Object Identifier. The value is a commit hash. */ oid: string refs: string[] @@ -96,7 +109,7 @@ export interface Comment { body: string edits: Edit[] embeds: Embed[] - reactions: [string, string][] + reactions: [string, string][] // TODO: maninak verify updated types timestamp: number replyTo: string | null } diff --git a/src/utils/patch.ts b/src/utils/patch.ts index 42ff01b1..9841448b 100644 --- a/src/utils/patch.ts +++ b/src/utils/patch.ts @@ -1,5 +1,7 @@ import type { Patch, Revision } from '../types' +// TODO: maninak change logic (and rename here and everywhere) to not get the latest revision but the most important one which is `patch.status === merged ? mergedRevision(s) ? latestRevision` + export function getFirstAndLatestRevisions(patch: Patch): { firstRevision: Revision latestRevision: Revision diff --git a/src/ux/patchesView.ts b/src/ux/patchesView.ts index 3e123b75..ec1c70ad 100644 --- a/src/ux/patchesView.ts +++ b/src/ux/patchesView.ts @@ -34,6 +34,8 @@ const checkmark = '✓' let timesPatchListFetchErroredConsecutively = 0 +// TODO: maninak show in item and tooltip if the chosen revision is approved, by whom and when + export interface FilechangeNode { filename: string relativeInRepoUrl: string @@ -474,7 +476,7 @@ function getThemeIconForPatch

(patch: P): ThemeIcon { case 'merged': return new ThemeIcon('git-merge', new ThemeColor('patch.merged')) default: - assertUnreachable(patch.state.status) + assertUnreachable(patch.state) } } diff --git a/src/webviews/postcss.config.js b/src/webviews/postcss.config.js index 2e7af2b7..0fa420c0 100644 --- a/src/webviews/postcss.config.js +++ b/src/webviews/postcss.config.js @@ -1,5 +1,7 @@ export default { plugins: { + 'postcss-import': {}, + 'tailwindcss/nesting': {}, tailwindcss: {}, autoprefixer: {}, }, diff --git a/src/webviews/src/assets/index.css b/src/webviews/src/assets/index.css index 0fa3f567..545f90f7 100644 --- a/src/webviews/src/assets/index.css +++ b/src/webviews/src/assets/index.css @@ -2,12 +2,22 @@ @tailwind components; @tailwind utilities; -:is(code, pre, span, b)[title]:hover { +:where(code, pre, span, b)[title]:hover { @apply underline decoration-dotted cursor-default; text-underline-position: under; } -:is(code, pre) { +:where(code, pre) { @apply m-0; display: initial; } + +:where(details) { + & summary { + @apply w-max cursor-pointer select-none; + } +} + +:where(.parsed-md) :last-child { + @apply mb-0; +} diff --git a/src/webviews/src/components/PatchDetail.vue b/src/webviews/src/components/PatchDetail.vue index f59c4110..6aeed55d 100644 --- a/src/webviews/src/components/PatchDetail.vue +++ b/src/webviews/src/components/PatchDetail.vue @@ -1,20 +1,72 @@ + + diff --git a/src/webviews/src/components/PatchMetadata.vue b/src/webviews/src/components/PatchMetadata.vue index 06bdabac..d2625458 100644 --- a/src/webviews/src/components/PatchMetadata.vue +++ b/src/webviews/src/components/PatchMetadata.vue @@ -9,16 +9,21 @@ provideVSCodeDesignSystem().register(vsCodeButton()) const { patch, authors } = storeToRefs(usePatchDetailStore()) // TODO: maninak add an (orange?) info icon next to authors who's DID is seen for the first time among revisions of patches of this project with text "This is the first time a user with this DID submits a patch revision in this project" -// TODO: maninak list committers with gravatar if available and email as tooltip diff --git a/src/webviews/src/components/PatchStatusBadge.vue b/src/webviews/src/components/PatchStatusBadge.vue index ca3f8a91..9e9e25aa 100644 --- a/src/webviews/src/components/PatchStatusBadge.vue +++ b/src/webviews/src/components/PatchStatusBadge.vue @@ -14,6 +14,6 @@ const status = computed(() => patch.value.state.status) :style="`background: color-mix(in srgb-linear, var(--vscode-patch-${status}), var(--vscode-editor-foreground) 5%);`" > - {{ status }} + {{ status }} diff --git a/src/webviews/src/stores/patchDetailStore.ts b/src/webviews/src/stores/patchDetailStore.ts index 5a7b3bfb..eaac4fd6 100644 --- a/src/webviews/src/stores/patchDetailStore.ts +++ b/src/webviews/src/stores/patchDetailStore.ts @@ -30,6 +30,7 @@ export const usePatchDetailStore = defineStore('patch-detail', () => { ) watchEffect(() => { + // TODO: maninak save and restore scroll position vscode.setState(state.value) }) diff --git a/src/webviews/vite.config.ts b/src/webviews/vite.config.ts index 1ab13eb4..0e513129 100644 --- a/src/webviews/vite.config.ts +++ b/src/webviews/vite.config.ts @@ -6,7 +6,9 @@ import vue from '@vitejs/plugin-vue' // https://vitejs.dev/config/ export default defineConfig({ plugins: [ - vue(), + vue({ + template: {compilerOptions: { isCustomElement: (tag) => tag.includes("vscode-") }}, + }), ], resolve: { alias: {