Skip to content

Commit

Permalink
Show draft projects on users home page (#872)
Browse files Browse the repository at this point in the history
* created myDraftProjects query & used it in load function

* show draft projects on users page

* disable data preloading for draft projects

* modified to query all the data in one request

* Add CSS design to draft projects

* Add icon to draft projects

* Fix bug with showing project list and table

* Improve mobile grid view

* address review comment

* Update draft icon

---------

Co-authored-by: Tim Haasdyk <[email protected]>
  • Loading branch information
psh0078 and myieye authored Jun 13, 2024
1 parent 037fb46 commit 0637c0e
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 39 deletions.
8 changes: 8 additions & 0 deletions backend/LexBoxApi/GraphQL/LexQueries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ public IQueryable<Project> Projects(LexBoxDbContext context, bool withDeleted =
}
}

[UseProjection]
[UseSorting]
public IQueryable<DraftProject> MyDraftProjects(LoggedInContext loggedInContext, LexBoxDbContext context)
{
var userId = loggedInContext.User.Id;
return context.DraftProjects.Where(p => p.ProjectManagerId == userId);
}

[UseProjection]
[UseFiltering]
[UseSorting]
Expand Down
3 changes: 2 additions & 1 deletion frontend/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ type ProjectUsers {

type Query {
myProjects(orderBy: [ProjectSortInput!]): [Project!]!
myDraftProjects(orderBy: [DraftProjectSortInput!]): [DraftProject!]!
projects(withDeleted: Boolean! = false where: ProjectFilterInput orderBy: [ProjectSortInput!]): [Project!]! @authorize(policy: "AdminRequiredPolicy")
draftProjects(where: DraftProjectFilterInput orderBy: [DraftProjectSortInput!]): [DraftProject!]! @authorize(policy: "AdminRequiredPolicy")
projectById(projectId: UUID!): Project
Expand Down Expand Up @@ -889,4 +890,4 @@ scalar UUID

scalar timestamptz @specifiedBy(url: "https:\/\/www.graphql-scalars.com\/date-time")

scalar uuid
scalar uuid
88 changes: 59 additions & 29 deletions frontend/src/lib/components/ProjectList.svelte
Original file line number Diff line number Diff line change
@@ -1,42 +1,64 @@
<script lang="ts">
import t from '$lib/i18n';
import Icon from '$lib/icons/Icon.svelte';
import { Badge } from './Badges';
import { getProjectTypeIcon } from './ProjectType';
import type { ProjectItem } from './Projects';
import type { ProjectItemWithDraftStatus } from './Projects';
export let projects: ProjectItem[];
export let projects: ProjectItemWithDraftStatus[];
</script>

<div class="grid grid-cols-2 sm:grid-cols-3 auto-rows-fr gap-2 md:gap-4">
<div class="grid grid-cols-1 xs:grid-cols-2 sm:grid-cols-3 auto-rows-fr gap-2 md:gap-4 max-xs:justify-items-center">
{#each projects as project}
<a class="card aspect-square bg-base-200 shadow-base-300 group overflow-hidden" href={`/project/${project.code}`}>
<div class="bg" style="background-image: url('{getProjectTypeIcon(project.type)}')" />
<div class="card-body z-[1]">
<h2 class="card-title overflow-hidden text-ellipsis" title={project.name}>
<span class="text-primary inline-flex gap-2 items-center">
{project.name}
</span>
</h2>

<p>{project.code}</p>

<p>
<span class="i-mdi-account text-xl mb-[-4px]" /> {project.userCount}
</p>

<p class="flex items-end">
{#if project.lastCommit}
{$t('projectlist.last_change', {
lastChange: new Date(project.lastCommit),
{#if project.isDraft}
<div class="draft card aspect-square bg-base-200 overflow-hidden">
<div class="bg" style="background-image: url('{getProjectTypeIcon(project.type)}')" />
<div class="card-body z-[1] max-sm:p-6">
<h2 class="card-title overflow-hidden text-ellipsis" title={project.name}>
<span class="text-primary inline-flex gap-2 items-center">
{project.name}
<Icon icon="i-mdi-script" color="text-warning"/>
</span>
</h2>
<p>{project.code}</p>
<Badge variant="badge-warning" outline>
<Icon icon="i-mdi-progress-clock" />
{$t('project.awaiting_approval')}
</Badge>
<p class="flex items-end">
{$t('projectlist.requested', {
requested: new Date(project.createdDate),
})}
{:else}
<Badge variant="badge-info" outline>
{$t('projectlist.no_changes')}
</Badge>
{/if}
</p>
</p>
</div>
</div>
</a>
{:else}
<a class="card aspect-square bg-base-200 shadow-base-300 overflow-hidden" href={`/project/${project.code}`}>
<div class="bg" style="background-image: url('{getProjectTypeIcon(project.type)}')" />
<div class="card-body z-[1] max-sm:p-6">
<h2 class="card-title overflow-hidden text-ellipsis" title={project.name}>
<span class="text-primary inline-flex gap-2 items-center">
{project.name}
</span>
</h2>
<p>{project.code}</p>
<p>
<span class="i-mdi-account text-xl mb-[-4px]" /> {project.userCount}
</p>
<p class="flex items-end">
{#if project.lastCommit}
{$t('projectlist.last_change', {
lastChange: new Date(project.lastCommit),
})}
{:else}
<Badge variant="badge-info" outline>
{$t('projectlist.no_changes')}
</Badge>
{/if}
</p>
</div>
</a>
{/if}
{/each}
</div>

Expand All @@ -50,6 +72,9 @@
hover:border-neutral
hover:shadow-xl;
max-height: 50vh;
max-width: 100%;
.bg {
@apply absolute
w-full
Expand All @@ -73,4 +98,9 @@
@apply opacity-100;
}
}
.draft.card {
pointer-events: none;
box-shadow: none;
}
</style>
2 changes: 2 additions & 0 deletions frontend/src/lib/components/Projects/ProjectTable.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@
</span>
{:else if !project.isDraft}
{$date(project.lastCommit)}
{:else}
{$t('project.awaiting_approval')}
{/if}
</td>
{/if}
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/lib/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ the [Linguistics Institute at Payap University](https://li.payap.ac.th/) in Chia
"project_now_not_confidential": "Project is now not confidential.",
}
},
"awaiting_approval": "Awaiting approval"
},
"project_page": {
"project": "Project",
Expand Down Expand Up @@ -399,7 +400,8 @@ If you don't see a dialog or already closed it, click the button below:",
"projectlist": {
"last_change": "Last Change: {lastChange, date, short} {lastChange, time, short}",
"no_changes": "New",
"shared_with": "Shared with {memberCount, plural, one {no one} other {# people} }"
"shared_with": "Shared with {memberCount, plural, one {no one} other {# people} }",
"requested": "Requested: {requested, date, short} {requested, time, short}",
},
"register": {
"title": "Register",
Expand Down
25 changes: 17 additions & 8 deletions frontend/src/routes/(authenticated)/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { HeaderPage } from '$lib/layout';
import { getSearchParams, queryParam } from '$lib/util/query-params';
import type { ProjectType } from '$lib/gql/types';
import { ProjectFilter, filterProjects, type ProjectFilters, type ProjectItem } from '$lib/components/Projects';
import { ProjectFilter, filterProjects, type ProjectFilters, type ProjectItemWithDraftStatus } from '$lib/components/Projects';
import ProjectTable from '$lib/components/Projects/ProjectTable.svelte';
import { Button } from '$lib/forms';
import { limit } from '$lib/components/Paging';
Expand All @@ -15,6 +15,7 @@
export let data: PageData;
$: projects = data.projects;
$: draftProjects = data.draftProjects;
type Filters = Pick<ProjectFilters, 'projectSearch' | 'projectType'>;
Expand All @@ -23,9 +24,22 @@
projectType: queryParam.string<ProjectType | undefined>(undefined),
});
let allProjects: ProjectItemWithDraftStatus[] = [];
let filteredProjects: ProjectItemWithDraftStatus[] = [];
let limitResults = true;
$: allProjects = [
...$draftProjects.map(p => ({
...p, isDraft: true as const,
createUrl: ''
})),
...$projects.map(p => ({ ...p, isDraft: false as const })),
];
$: filteredProjects = filterProjects(allProjects, $filters);
$: shownProjects = limitResults ? limit(filteredProjects) : filteredProjects;
let initializedMode = false;
let mode: ViewMode;
$: defaultMode = $projects.length < 10 ? ViewMode.Grid : ViewMode.Table;
$: defaultMode = allProjects.length < 10 ? ViewMode.Grid : ViewMode.Table;
$: {
if (!initializedMode) {
Expand All @@ -43,11 +57,6 @@
mode = selectedMode;
Cookies.set(STORAGE_VIEW_MODE_KEY, mode, { expires: 365 * 10 });
}
let filteredProjects: ProjectItem[] = [];
let limitResults = true;
$: filteredProjects = filterProjects($projects, $filters);
$: shownProjects = limitResults ? limit(filteredProjects) : filteredProjects;
</script>

<HeaderPage wide title={$t('user_dashboard.title')}>
Expand Down Expand Up @@ -84,7 +93,7 @@
{/if}
</svelte:fragment>

{#if !$projects.length}
{#if !allProjects.length}
<div class="text-lg text-secondary flex gap-4 items-center justify-center">
<span class="i-mdi-creation-outline text-xl shrink-0" />
{#if !data.user.emailVerified && !data.user.createdByAdmin}
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/routes/(authenticated)/+page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,28 @@ export async function load(event: PageLoadEvent) {
type
isConfidential
}
myDraftProjects(orderBy: [
{code: ASC }
]) {
code
createdDate
id
name
type
description
retentionPolicy
isConfidential
projectManagerId
}
}
`), {});

const projectViewMode = getViewMode(event);

return {
projects: results.myProjects,
draftProjects: results.myDraftProjects,
projectViewMode,
}
}
6 changes: 6 additions & 0 deletions frontend/tailwind.config.cjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const { iconsPlugin, getIconCollections } = require('@egoist/tailwindcss-icons');
const defaultTheme = require('tailwindcss/defaultTheme');

/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{svelte,ts}'],
Expand Down Expand Up @@ -32,6 +34,10 @@ module.exports = {
logs: false,
},
theme: {
screens: {
'xs': '400px',
...defaultTheme.screens,
},
extend: {
screens: {
'max-xs': { 'max': '400px' },
Expand Down

0 comments on commit 0637c0e

Please sign in to comment.