mirror of
https://github.com/vrc-get/vrc-get.git
synced 2026-06-21 09:58:08 +00:00
Merge 7de392596b into 9a1044df51
This commit is contained in:
commit
fea57e8ee6
6 changed files with 215 additions and 6 deletions
|
|
@ -37,6 +37,7 @@ import {
|
|||
import { openSingleDialog } from "@/lib/dialog";
|
||||
import { tc } from "@/lib/i18n";
|
||||
import { toastThrownError } from "@/lib/toast";
|
||||
import { openProjectDetails } from "@/app/_main/projects/manage/-edit-project-details";
|
||||
|
||||
export function ProjectGridItem({
|
||||
project,
|
||||
|
|
@ -88,6 +89,21 @@ export function ProjectGridItem({
|
|||
>
|
||||
{tc("projects:menuitem:open directory")}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={async () => {
|
||||
try {
|
||||
await openProjectDetails({
|
||||
existingMemo: project.memo,
|
||||
existingTags: project.tags
|
||||
})
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
toastThrownError(e);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{tc("projects:menuitem:project details")}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={async () => {
|
||||
try {
|
||||
|
|
@ -123,12 +139,24 @@ export function ProjectGridItem({
|
|||
<TooltipTriggerIfValid
|
||||
className={"text-left select-text cursor-auto w-full"}
|
||||
>
|
||||
<p className="font-normal whitespace-pre overflow-ellipsis overflow-hidden">
|
||||
<p className="font-normal whitespace-pre overflow-ellipsis overflow-hidden w-100">
|
||||
{project.name}
|
||||
</p>
|
||||
<p className="font-normal opacity-50 text-sm whitespace-pre overflow-ellipsis overflow-hidden compact:hidden">
|
||||
{project.path}
|
||||
Path: {project.path}
|
||||
</p>
|
||||
{!project.memo ? undefined : (
|
||||
<p className="font-normal opacity-50 text-sm whitespace-pre overflow-ellipsis overflow-hidden compact:hidden">
|
||||
Memo: {project.memo}
|
||||
</p>
|
||||
)}
|
||||
{Array.isArray(project.tags) && project.tags.length != 0 && (
|
||||
<div className="flex overflow-x-auto gap-2 mt-1">
|
||||
{project.tags.map(tag => (
|
||||
<Button variant={"info"} size={"sm"}>{tag}</Button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</TooltipTriggerIfValid>
|
||||
<TooltipContent>{project.path}</TooltipContent>
|
||||
</Tooltip>
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import { router } from "@/lib/main";
|
|||
import { queryClient } from "@/lib/query-client";
|
||||
import { toastError, toastSuccess, toastThrownError } from "@/lib/toast";
|
||||
import { compareUnityVersionString } from "@/lib/version";
|
||||
import { openProjectDetails } from "./manage/-edit-project-details";
|
||||
|
||||
export const ProjectDisplayType: Record<
|
||||
TauriProjectType,
|
||||
|
|
@ -135,8 +136,20 @@ export function ProjectRow({
|
|||
>
|
||||
<p className="font-normal whitespace-pre">{project.name}</p>
|
||||
<p className="font-normal opacity-50 text-sm whitespace-pre compact:hidden">
|
||||
{project.path}
|
||||
Path: {project.path}
|
||||
</p>
|
||||
{!project.memo ? undefined : (
|
||||
<p className="font-normal opacity-50 text-sm whitespace-pre overflow-ellipsis overflow-hidden compact:hidden">
|
||||
Memo: {project.memo}
|
||||
</p>
|
||||
)}
|
||||
{Array.isArray(project.tags) && project.tags.length != 0 && (
|
||||
<div className="flex overflow-x-auto gap-2 mt-1">
|
||||
{project.tags.map(tag => (
|
||||
<Button variant={"info"} size={"sm"}>{tag}</Button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</TooltipTriggerIfValid>
|
||||
<TooltipContent>{project.path}</TooltipContent>
|
||||
</Tooltip>
|
||||
|
|
@ -251,6 +264,21 @@ export function ProjectRow({
|
|||
>
|
||||
{tc("projects:menuitem:open directory")}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={async () => {
|
||||
try {
|
||||
await openProjectDetails({
|
||||
existingMemo: project.memo,
|
||||
existingTags: project.tags
|
||||
})
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
toastThrownError(e);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{tc("projects:menuitem:project details")}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={onCopyProject}
|
||||
disabled={removed || !(is_valid ?? true)}
|
||||
|
|
|
|||
|
|
@ -205,9 +205,15 @@ export function sortSearchProjects(
|
|||
search: string,
|
||||
sorting: Sorting,
|
||||
): TauriProject[] {
|
||||
const searched = projects.filter((project) =>
|
||||
project.name.toLowerCase().includes(search?.toLowerCase() ?? ""),
|
||||
);
|
||||
const searched = projects.filter((project) => {
|
||||
const searchString = search?.toLowerCase() ?? ""
|
||||
|
||||
return (
|
||||
project.name.toLowerCase().includes(searchString) ||
|
||||
project.memo.toLowerCase().includes(searchString) ||
|
||||
project.tags?.map(tag => tag.toLowerCase()).find(tag => tag.includes(searchString))
|
||||
)
|
||||
});
|
||||
|
||||
searched.sort((a, b) => b.last_modified - a.last_modified);
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,38 @@ const environmentProjects = queryOptions({
|
|||
|
||||
function Page() {
|
||||
const result = useQuery(environmentProjects);
|
||||
|
||||
//TODO remove temporary Mock
|
||||
if(!result.error){
|
||||
result.data = result.data?.map(project => {
|
||||
const id = crypto.randomUUID()
|
||||
project.name = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx "+id
|
||||
project.path = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy "+id
|
||||
|
||||
if (Math.random() > 0.5) {
|
||||
project.memo = ""
|
||||
project.tags = []
|
||||
return project
|
||||
}
|
||||
|
||||
project.memo = "Super memo with much details n°"+id
|
||||
if(project.tags == null){
|
||||
project.tags = []
|
||||
project.tags.push("Spokeek")
|
||||
if (Math.random() > 0.3) project.tags.push("Number "+Math.ceil(Math.random()*1000))
|
||||
if (Math.random() > 0.3) project.tags.push("Emoji 🔥")
|
||||
if (Math.random() > 0.3) project.tags.push("Chinese 本前开但因只从想")
|
||||
if (Math.random() > 0.3) project.tags.push("Cursed ḑ̸̨͈̬̲̜̟̤͉̪̪̞̖̏̄̀̓̈́́͐̈́̓̆̎͜z̷͙̣̘̰̻̲͔̻͕͕͖̙͎̿̾͒͒͌̀̍͒̔̏̿̏̚͘a̸̡̡̧̨͓͈͖͎̹̰͕̲͍̾̀͂͆̽̅͗̒̑̍͘̚̚͜d̵̨̧̡̰̻͖̯̱͖͖̰̘́̽͂͆̀̍͗̾̂̐͐̑̏â̷̲̈́͊̌͛̉̇̇ͅd̵̜̠̳͎̙̝͚̓̅̋̆͐͘͜͠͝͝")
|
||||
|
||||
if (Math.random() > 0.5)
|
||||
project.tags.push("Random 0.5")
|
||||
if (Math.random() > 0.7)
|
||||
project.tags.push("Super Random 0.7")
|
||||
}
|
||||
return project
|
||||
})
|
||||
}
|
||||
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
const viewModeQuery = useQuery({
|
||||
|
|
|
|||
111
vrc-get-gui/app/_main/projects/manage/-edit-project-details.tsx
Normal file
111
vrc-get-gui/app/_main/projects/manage/-edit-project-details.tsx
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
import { type DialogContext, showDialog } from "@/lib/dialog";
|
||||
import { DialogFooter, DialogTitle } from "@/components/ui/dialog";
|
||||
import { tc } from "@/lib/i18n";
|
||||
import { NavigateFn } from "@tanstack/react-router";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useState } from "react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { toastError } from "@/lib/toast";
|
||||
|
||||
export async function openProjectDetails({
|
||||
existingTags,
|
||||
existingMemo
|
||||
}: {
|
||||
existingTags: string[],
|
||||
existingMemo: string
|
||||
}, navigate?: NavigateFn) {
|
||||
using dialog = showDialog();
|
||||
await dialog.ask(openProjectDetailsDialog, { existingTags, existingMemo });
|
||||
}
|
||||
|
||||
function saveProjectDetails({
|
||||
newMemo,
|
||||
newTags
|
||||
}:
|
||||
{
|
||||
newMemo: string,
|
||||
newTags: string[]
|
||||
}) {
|
||||
console.log({
|
||||
newMemo,
|
||||
newTags
|
||||
})
|
||||
toastError("Feature is still being developped")
|
||||
}
|
||||
|
||||
function openProjectDetailsDialog({
|
||||
dialog,
|
||||
existingTags,
|
||||
existingMemo
|
||||
}: {
|
||||
dialog: DialogContext<string | null>,
|
||||
existingTags: string[],
|
||||
existingMemo: string
|
||||
}) {
|
||||
const [modified, setModified] = useState(false)
|
||||
|
||||
const [newMemo, setNewMemo] = useState(existingMemo)
|
||||
const [newTags, setNewTags] = useState(existingTags.map(((tag, index) => ({ index, value: tag }))))
|
||||
|
||||
function resetFields() {
|
||||
setNewMemo(existingMemo)
|
||||
setNewTags(existingTags.map(((tag, index) => ({ index, value: tag }))))
|
||||
setModified(false)
|
||||
}
|
||||
|
||||
return (<>
|
||||
<DialogTitle>{tc("projects:menuitem:project details")}</DialogTitle>
|
||||
<section>
|
||||
<h3 className="mb-1">
|
||||
Memo
|
||||
</h3>
|
||||
<Input className="w-full min-h-5" value={newMemo} placeholder={newMemo} onChange={(changeEvent => {
|
||||
setModified(true)
|
||||
setNewMemo(changeEvent.target.value)
|
||||
})} />
|
||||
</section>
|
||||
<section className="mb-2">
|
||||
<h3 className="mb-1">
|
||||
Tags
|
||||
</h3>
|
||||
<ul>
|
||||
{newTags.map((newTag) => (<li>
|
||||
<Input
|
||||
key={newTag.index}
|
||||
className="w-full mb-1"
|
||||
value={newTag.value}
|
||||
placeholder={newTag.value}
|
||||
onChange={(updateEvent) => {
|
||||
setModified(true)
|
||||
setNewTags(newTags.map(tag => {
|
||||
if (tag.index === newTag.index)
|
||||
tag.value = updateEvent.target.value
|
||||
return tag
|
||||
}))
|
||||
}}
|
||||
/>
|
||||
</li>))}
|
||||
</ul>
|
||||
</section>
|
||||
<DialogFooter className={"gap-2"}>
|
||||
<Button disabled={!modified} onClick={resetFields}>
|
||||
{tc("general:button:reset")}
|
||||
</Button>
|
||||
<Button onClick={() => dialog.close(null)}>
|
||||
{tc("general:button:cancel")}
|
||||
</Button>
|
||||
{/* button save not working */}
|
||||
<Button
|
||||
disabled={!modified}
|
||||
onClick={() => {
|
||||
saveProjectDetails({
|
||||
newMemo,
|
||||
newTags: newTags.map(tag => tag.value)
|
||||
})
|
||||
}}
|
||||
>
|
||||
{tc("project details:buttons:confirm")}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</>)
|
||||
}
|
||||
|
|
@ -565,5 +565,9 @@
|
|||
"logs:message": "Message",
|
||||
"logs:manage:select logs level": "Logs Level Filter",
|
||||
"logs:manage:auto scroll": "Toggle Auto Scroll",
|
||||
|
||||
// Project details
|
||||
"projects:menuitem:project details": "Edit project details",
|
||||
"project details:buttons:confirm": "Update details"
|
||||
},
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue