mirror of
https://github.com/aykhans/slash-e.git
synced 2025-07-07 13:42:34 +00:00
chore: get shortcut by name and workspace name
This commit is contained in:
@ -7,6 +7,7 @@ import Auth from "./pages/Auth";
|
||||
import Home from "./pages/Home";
|
||||
import WorkspaceDetail from "./pages/WorkspaceDetail";
|
||||
import UserDetail from "./pages/UserDetail";
|
||||
import ShortcutRedirector from "./pages/ShortcutRedirector";
|
||||
|
||||
function App() {
|
||||
const navigate = useNavigate();
|
||||
@ -33,6 +34,7 @@ function App() {
|
||||
<Route path="/auth" element={<Auth />} />
|
||||
<Route path="/user/:userId" element={<UserDetail />} />
|
||||
<Route path="/workspace/:workspaceId" element={<WorkspaceDetail />} />
|
||||
<Route path="/:workspaceName/go/:shortcutName" element={<ShortcutRedirector />} />
|
||||
</Routes>
|
||||
</Only>
|
||||
);
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { shortcutService } from "../services";
|
||||
import copy from "copy-to-clipboard";
|
||||
import { shortcutService, workspaceService } from "../services";
|
||||
import Dropdown from "./common/Dropdown";
|
||||
import showCreateShortcutDialog from "./CreateShortcutDialog";
|
||||
import Icon from "./Icon";
|
||||
@ -11,6 +12,11 @@ interface Props {
|
||||
const ShortcutListView: React.FC<Props> = (props: Props) => {
|
||||
const { workspaceId, shortcutList } = props;
|
||||
|
||||
const handleCopyButtonClick = (shortcut: Shortcut) => {
|
||||
const workspace = workspaceService.getWorkspaceById(workspaceId);
|
||||
copy(`${location.host}/${workspace?.name}/go/${shortcut.name}`);
|
||||
};
|
||||
|
||||
const handleDeleteShortcutButtonClick = (shortcut: Shortcut) => {
|
||||
shortcutService.deleteShortcutById(shortcut.id);
|
||||
};
|
||||
@ -20,33 +26,44 @@ const ShortcutListView: React.FC<Props> = (props: Props) => {
|
||||
{shortcutList.map((shortcut) => {
|
||||
return (
|
||||
<div key={shortcut.id} className="w-full flex flex-row justify-between items-start border px-6 py-4 mb-3 rounded-lg">
|
||||
<div className="flex flex-col justify-start items-start">
|
||||
<span className="text-lg font-medium">{shortcut.name}</span>
|
||||
<a className="text-base text-gray-600 flex flex-row cursor-pointer hover:underline" target="blank" href={shortcut.link}>
|
||||
{shortcut.link} <Icon.ExternalLink className="w-4 h-auto ml-1" />
|
||||
</a>
|
||||
<div className="flex flex-row justify-start items-center mr-4">
|
||||
<span className="font-medium">{shortcut.name}</span>
|
||||
<span className="text-gray-500 ml-4">{shortcut.description}</span>
|
||||
</div>
|
||||
<div className="flex flex-row justify-end items-center">
|
||||
<span
|
||||
className="cursor-pointer mr-4 hover:opacity-80"
|
||||
onClick={() => {
|
||||
handleCopyButtonClick(shortcut);
|
||||
}}
|
||||
>
|
||||
<Icon.Copy className="w-5 h-auto" />
|
||||
</span>
|
||||
<a className="cursor-pointer mr-4 hover:opacity-80" target="blank" href={shortcut.link}>
|
||||
<Icon.ExternalLink className="w-5 h-auto" />
|
||||
</a>
|
||||
<Dropdown
|
||||
actions={
|
||||
<>
|
||||
<span
|
||||
className="w-full px-2 leading-8 cursor-pointer rounded hover:bg-gray-100"
|
||||
onClick={() => showCreateShortcutDialog(workspaceId, shortcut.id)}
|
||||
>
|
||||
Edit
|
||||
</span>
|
||||
<span
|
||||
className="w-full px-2 leading-8 cursor-pointer rounded text-red-600 hover:bg-gray-100"
|
||||
onClick={() => {
|
||||
handleDeleteShortcutButtonClick(shortcut);
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
actionsClassName="!w-24"
|
||||
></Dropdown>
|
||||
</div>
|
||||
<Dropdown
|
||||
actions={
|
||||
<>
|
||||
<span
|
||||
className="w-full px-2 leading-8 cursor-pointer rounded hover:bg-gray-100"
|
||||
onClick={() => showCreateShortcutDialog(workspaceId, shortcut.id)}
|
||||
>
|
||||
Edit
|
||||
</span>
|
||||
<span
|
||||
className="w-full px-2 leading-8 cursor-pointer rounded text-red-600 hover:bg-gray-100"
|
||||
onClick={() => {
|
||||
handleDeleteShortcutButtonClick(shortcut);
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
actionsClassName="!w-24"
|
||||
></Dropdown>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
@ -87,6 +87,10 @@ export function getShortcutList(shortcutFind?: ShortcutFind) {
|
||||
return axios.get<ResponseObject<Shortcut[]>>(`/api/shortcut?${queryList.join("&")}`);
|
||||
}
|
||||
|
||||
export function getShortcutWithNameAndWorkspaceName(workspaceName: string, shortcutName: string) {
|
||||
return axios.get<ResponseObject<Shortcut>>(`/api/workspace/${workspaceName}/shortcut/${shortcutName}`);
|
||||
}
|
||||
|
||||
export function createShortcut(shortcutCreate: ShortcutCreate) {
|
||||
return axios.post<ResponseObject<Shortcut>>("/api/shortcut", shortcutCreate);
|
||||
}
|
||||
|
@ -44,15 +44,3 @@ export function throttle(fn: FunctionType, delay: number) {
|
||||
}, delay);
|
||||
};
|
||||
}
|
||||
|
||||
export async function copyTextToClipboard(text: string) {
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
} catch (error: unknown) {
|
||||
console.warn("Copy to clipboard failed.", error);
|
||||
}
|
||||
} else {
|
||||
console.warn("Copy to clipboard failed, methods not supports.");
|
||||
}
|
||||
}
|
||||
|
43
web/src/pages/ShortcutRedirector.tsx
Normal file
43
web/src/pages/ShortcutRedirector.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import Header from "../components/Header";
|
||||
import { getShortcutWithNameAndWorkspaceName } from "../helpers/api";
|
||||
import useLoading from "../hooks/useLoading";
|
||||
|
||||
interface State {
|
||||
errMessage?: string;
|
||||
}
|
||||
|
||||
const ShortcutRedirector: React.FC = () => {
|
||||
const params = useParams();
|
||||
const [state, setState] = useState<State>();
|
||||
const loadingState = useLoading();
|
||||
|
||||
useEffect(() => {
|
||||
const workspaceName = params.workspaceName || "";
|
||||
const shortcutName = params.shortcutName || "";
|
||||
getShortcutWithNameAndWorkspaceName(workspaceName, shortcutName)
|
||||
.then(({ data: { data: shortcut } }) => {
|
||||
if (shortcut) {
|
||||
window.location.href = shortcut.link;
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
setState({
|
||||
errMessage: err?.message || "Not found",
|
||||
});
|
||||
loadingState.setFinish();
|
||||
});
|
||||
}, []);
|
||||
|
||||
return loadingState.isLoading ? null : (
|
||||
<div className="w-full h-full flex flex-col justify-start items-start">
|
||||
<Header />
|
||||
<div className="w-full pt-24 text-center font-mono text-xl">
|
||||
<p>{state?.errMessage}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ShortcutRedirector;
|
Reference in New Issue
Block a user