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

Page home & explore for community #973

Merged
merged 2 commits into from
Oct 11, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions spx-gui/src/apis/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,9 @@ export type FileCollection = {
[path: string]: UniversalUrl
}

/** Get time string for spx-backend APIs */
export function timeStringify(time: number) {
return new Date(time).toISOString()
}

export const client = new Client()
54 changes: 53 additions & 1 deletion spx-gui/src/apis/project.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import dayjs from 'dayjs'
import type { FileCollection, ByPage, PaginationParams } from './common'
import { client, IsPublic, ownerAll } from './common'
import { client, IsPublic, ownerAll, timeStringify } from './common'
import { ApiException, ApiExceptionCode } from './common/exception'

export { IsPublic, ownerAll }
Expand Down Expand Up @@ -105,6 +106,14 @@ export type ListProjectParams = PaginationParams & {
owner?: string
/** Filter projects by name pattern */
keyword?: string
/** Filter projects that were created after this timestamp */
createdAfter?: string
/** Filter projects that gained new likes after this timestamp */
likesReceivedAfter?: string
/** Filter projects that were remixed after this timestamp */
remixesReceivedAfter?: string
/** If filter projects created by followees of logged-in user */
fromFollowees?: boolean
/** Field by which to order the results */
orderBy?: 'cTime' | 'uTime' | 'likeCount' | 'remixCount' | 'recentLikeCount' | 'recentRemixCount'
/** Order in which to sort the results */
Expand All @@ -125,6 +134,49 @@ export async function getProject(owner: string, name: string) {
return __adaptProjectData(await client.get(`/project/${encode(owner, name)}`))
}

export enum ExploreOrder {
MostLikes = 'likes',
MostRemixes = 'remix',
FollowingCreated = 'following'
}

export type ExploreParams = {
order: ExploreOrder
count: number
}

/** Get project list for explore purpose */
export async function exploreProjects({ order, count }: ExploreParams) {
// count within the last month
const countAfter = timeStringify(dayjs().subtract(1, 'month').valueOf())
const p: ListProjectParams = {
isPublic: IsPublic.public,
owner: ownerAll,
pageSize: count,
pageIndex: 1
}
switch (order) {
case ExploreOrder.MostLikes:
p.likesReceivedAfter = countAfter
p.orderBy = 'recentLikeCount'
p.sortOrder = 'desc'
break
case ExploreOrder.MostRemixes:
p.remixesReceivedAfter = countAfter
p.orderBy = 'recentRemixCount'
p.sortOrder = 'desc'
break
case ExploreOrder.FollowingCreated:
p.fromFollowees = true
p.createdAfter = countAfter
p.orderBy = 'cTime'
p.sortOrder = 'desc'
break
}
const listResult = await listProject(p)
return listResult.data
}

/**
* Check if given project liked by current logged-in user.
* If not logged in, `false` will be returned.
Expand Down
47 changes: 47 additions & 0 deletions spx-gui/src/components/community/CommunityHeader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!-- Simple header component for pages like search & explore -->

<template>
<section class="header">
<CenteredWrapper class="header-content">
<h1 class="title">
<slot></slot>
</h1>
<label class="options">
<slot name="options"></slot>
</label>
</CenteredWrapper>
</section>
</template>

<script setup lang="ts">
import CenteredWrapper from '@/components/community/CenteredWrapper.vue'
</script>

<style lang="scss" scoped>
@import '@/utils/utils';

.header {
flex: 0 0 auto;
background-color: var(--ui-color-grey-100);
}

.header-content {
height: 64px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;

.title {
flex: 1 1 0;
@include text-ellipsis;
line-height: 26px;
font-size: 16px;
color: var(--ui-color-title);
}

.options {
flex: 0 0 auto;
}
}
</style>
4 changes: 3 additions & 1 deletion spx-gui/src/components/community/CommunityNavbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
<NavbarWrapper centered>
<template #left>
<NavbarDropdown>
<template #trigger> Create(TODO) </template>
<template #trigger>
<UIIcon type="plus" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

突然发现设计稿上的“+”(右图)看起来好像圆润些🌝

Screenshot 2024-10-11 at 14 37 27 Screenshot 2024-10-11 at 14 38 00

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

细啊..应该是清清换了个 plus 的 icon,我在后边的 PR 里边更新下吧

</template>
<UIMenu>
<NavbarNewProjectItem />
<NavbarOpenProjectItem />
Expand Down
80 changes: 80 additions & 0 deletions spx-gui/src/components/community/ProjectsSection.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!-- Project list as a section -->

<template>
<section>
<header class="header">
<h2 class="title">
<slot name="title"></slot>
</h2>
<RouterLink class="link" :to="linkTo">
<slot name="link"></slot>
<UIIcon class="link-icon" type="arrowRightSmall" />
</RouterLink>
</header>
<ul class="projects">
<UILoading v-if="queryRet.isLoading.value" :mask="false" />
<!-- TODO: simpler UIError & UIEmpty here -->
<UIError v-else-if="queryRet.error.value != null" :retry="queryRet.refetch">
{{ $t(queryRet.error.value.userMessage) }}
</UIError>
<UIEmpty
v-else-if="queryRet.data.value != null && queryRet.data.value.length === 0"
size="large"
/>
<template v-else-if="queryRet.data.value != null">
<slot></slot>
</template>
</ul>
</section>
</template>

<script setup lang="ts">
import type { QueryRet } from '@/utils/exception'
import { UIIcon, UILoading, UIError, UIEmpty } from '@/components/ui'

defineProps<{
linkTo: string
queryRet: QueryRet<unknown[]>
}>()
</script>

<style lang="scss" scoped>
.header {
height: 56px;
display: flex;
justify-content: space-between;
align-items: center;

.title {
line-height: 28px;
font-size: 20px;
color: var(--ui-color-title);
}

.link {
display: flex;
color: var(--ui-color-primary-main);
text-decoration: none;
}

.link-icon {
margin-left: 8px;
width: 20px;
height: 20px;
}
}

.projects {
padding: 20px 0;
margin-bottom: 12px;

// same height as `ProjectItem`, to prevent layout shift
min-height: 260px;
position: relative;

display: flex;
overflow: hidden;
align-items: center;
gap: 20px;
}
</style>
10 changes: 7 additions & 3 deletions spx-gui/src/components/navbar/NavbarProfile.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div v-if="!userStore.userInfo" class="sign-in">
<UIButton :disabled="!isOnline" @click="userStore.signInWithRedirection()">{{
<UIButton type="secondary" :disabled="!isOnline" @click="userStore.signInWithRedirection()">{{
$t({ en: 'Sign in', zh: '登录' })
}}</UIButton>
</div>
Expand Down Expand Up @@ -37,14 +37,18 @@ const { isOnline } = useNetwork()
<style lang="scss" scoped>
.sign-in,
.avatar {
margin: 0 8px;
height: 100%;
display: flex;
align-items: center;
}

.sign-in {
white-space: nowrap;
}

.avatar {
margin-right: 8px;
padding: 0 24px;
padding: 0 16px;

&:hover {
background-color: var(--ui-color-primary-600);
Expand Down
1 change: 1 addition & 0 deletions spx-gui/src/components/navbar/NavbarWrapper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ withDefaults(
.right {
flex-basis: 30%;
display: flex;
gap: 8px;
}

.center {
Expand Down
20 changes: 14 additions & 6 deletions spx-gui/src/components/project/item/ProjectItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -128,18 +128,16 @@ const handleRemove = useMessageHandle(
</script>

<style lang="scss" scoped>
@mixin text-ellipsis {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
@import '@/utils/utils';

.project-item {
width: 240px;
flex: 0 0 auto;
overflow: hidden;
border-radius: var(--ui-border-radius-2);
border: 1px solid var(--ui-color-grey-400);
background-color: var(--ui-color-grey-100);
transition: 0.1s;
}

.link {
Expand All @@ -159,6 +157,8 @@ const handleRemove = useMessageHandle(
}

.options {
opacity: 0;
visibility: hidden;
position: absolute;
top: 8px;
right: 8px;
Expand All @@ -171,7 +171,7 @@ const handleRemove = useMessageHandle(
color: var(--ui-color-grey-800);
background-color: var(--ui-color-grey-100);
cursor: pointer;
transition: 0.3s;
transition: 0.1s;

&:hover {
color: var(--ui-color-grey-100);
Expand All @@ -191,6 +191,14 @@ const handleRemove = useMessageHandle(
}
}

.project-item:hover {
box-shadow: 0px 4px 12px 0px rgba(36, 41, 47, 0.08);
.options {
visibility: visible;
opacity: 1;
}
}

.info {
padding: var(--ui-gap-middle);

Expand Down
1 change: 1 addition & 0 deletions spx-gui/src/components/ui/empty/UIEmpty.vue
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ const slots = useSlots()
}

.size-large {
width: 100%;
flex-direction: column;
gap: 12px;

Expand Down
4 changes: 2 additions & 2 deletions spx-gui/src/components/ui/error/UIError.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="ui-error">
<img :src="defaultErrorImg" />
<h5 class="error">
<h5 class="message">
<slot></slot>
</h5>
<button v-if="retry != null" class="retry" @click="retry">{{ retryText }}</button>
Expand Down Expand Up @@ -32,7 +32,7 @@ const retryText = computed(() => config.error?.retryText ?? 'Retry')
justify-content: center;
}

.error {
.message {
margin-top: 12px;
font-size: 16px;
line-height: 26px;
Expand Down
4 changes: 3 additions & 1 deletion spx-gui/src/components/ui/icons/UIIcon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import volumeOff from './volume-off.svg?raw'
import statePublic from './state-public.svg?raw'
import statePrivate from './state-private.svg?raw'
import heart from './heart.svg?raw'
import arrowRightSmall from './arrow-right-small.svg?raw'

const typeIconMap = {
file,
Expand Down Expand Up @@ -70,7 +71,8 @@ const typeIconMap = {
volumeOff,
statePublic,
statePrivate,
heart
heart,
arrowRightSmall
}

export type Type = keyof typeof typeIconMap
Expand Down
3 changes: 3 additions & 0 deletions spx-gui/src/components/ui/icons/arrow-right-small.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading