mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fix: shortcut ui, Issue title resizing, comment resizing, kanban scroll fixes (#206)
* fix: help shortcut ui fix * fix: issue title resizing ui fix * fix: issue comment resizing ui fix * feat: circular progress bar added * feat: module card delete added * fix: kanban view scroll fix * chore: shortcut command updated * fix: shortcut ui fix --------- Co-authored-by: Anmol Singh Bhatia <anmolsinghbhatia1001@gmail.com>
This commit is contained in:
parent
7ca1aef2ad
commit
6b89ee2a55
@ -97,32 +97,38 @@ const CommandPalette: React.FC = () => {
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(e: KeyboardEvent) => {
|
||||
if ((e.ctrlKey || e.metaKey) && e.key === "/") {
|
||||
e.preventDefault();
|
||||
setIsPaletteOpen(true);
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.key === "i") {
|
||||
e.preventDefault();
|
||||
setIsIssueModalOpen(true);
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.key === "p") {
|
||||
e.preventDefault();
|
||||
setIsProjectModalOpen(true);
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.key === "b") {
|
||||
e.preventDefault();
|
||||
toggleCollapsed();
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.key === "h") {
|
||||
e.preventDefault();
|
||||
setIsShortcutsModalOpen(true);
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.key === "q") {
|
||||
e.preventDefault();
|
||||
setIsCreateCycleModalOpen(true);
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.key === "m") {
|
||||
e.preventDefault();
|
||||
setIsCreateModuleModalOpen(true);
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.key === "d") {
|
||||
e.preventDefault();
|
||||
setIsBulkDeleteIssuesModalOpen(true);
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.altKey && e.key === "c") {
|
||||
e.preventDefault();
|
||||
if (
|
||||
!(e.target instanceof HTMLTextAreaElement) &&
|
||||
!(e.target instanceof HTMLInputElement) &&
|
||||
!(e.target as Element).classList?.contains("remirror-editor")
|
||||
) {
|
||||
if ((e.ctrlKey || e.metaKey) && e.key === "k") {
|
||||
e.preventDefault();
|
||||
setIsPaletteOpen(true);
|
||||
} else if (e.key === "c") {
|
||||
e.preventDefault();
|
||||
setIsIssueModalOpen(true);
|
||||
} else if (e.key === "p") {
|
||||
e.preventDefault();
|
||||
setIsProjectModalOpen(true);
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.key === "b") {
|
||||
e.preventDefault();
|
||||
toggleCollapsed();
|
||||
} else if (e.key === "h") {
|
||||
e.preventDefault();
|
||||
setIsShortcutsModalOpen(true);
|
||||
} else if (e.key === "q") {
|
||||
e.preventDefault();
|
||||
setIsCreateCycleModalOpen(true);
|
||||
} else if (e.key === "m") {
|
||||
e.preventDefault();
|
||||
setIsCreateModuleModalOpen(true);
|
||||
} else if (e.key === "Delete") {
|
||||
e.preventDefault();
|
||||
setIsBulkDeleteIssuesModalOpen(true);
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.altKey && e.key === "c") {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
if (!router.query.issueId) return;
|
||||
|
||||
|
@ -15,7 +15,7 @@ const shortcuts = [
|
||||
{
|
||||
title: "Navigation",
|
||||
shortcuts: [
|
||||
{ keys: "ctrl,/", description: "To open navigator" },
|
||||
{ keys: "ctrl,cmd,k", description: "To open navigator" },
|
||||
{ keys: "↑", description: "Move up" },
|
||||
{ keys: "↓", description: "Move down" },
|
||||
{ keys: "←", description: "Move left" },
|
||||
@ -27,14 +27,14 @@ const shortcuts = [
|
||||
{
|
||||
title: "Common",
|
||||
shortcuts: [
|
||||
{ keys: "ctrl,p", description: "To create project" },
|
||||
{ keys: "ctrl,i", description: "To create issue" },
|
||||
{ keys: "ctrl,q", description: "To create cycle" },
|
||||
{ keys: "ctrl,m", description: "To create module" },
|
||||
{ keys: "ctrl,d", description: "To bulk delete issues" },
|
||||
{ keys: "ctrl,h", description: "To open shortcuts guide" },
|
||||
{ keys: "p", description: "To create project" },
|
||||
{ keys: "c", description: "To create issue" },
|
||||
{ keys: "q", description: "To create cycle" },
|
||||
{ keys: "m", description: "To create module" },
|
||||
{ keys: "Delete", description: "To bulk delete issues" },
|
||||
{ keys: "h", description: "To open shortcuts guide" },
|
||||
{
|
||||
keys: "ctrl,alt,c",
|
||||
keys: "ctrl,cmd,alt,c",
|
||||
description: "To copy issue url when on issue detail page.",
|
||||
},
|
||||
],
|
||||
|
@ -214,10 +214,7 @@ const BulkDeleteIssuesModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
|
||||
<LayerDiagonalIcon height="56" width="56" />
|
||||
<h3 className="text-gray-500">
|
||||
No issues found. Create a new issue with{" "}
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">
|
||||
Ctrl/Command + I
|
||||
</pre>
|
||||
.
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">C</pre>.
|
||||
</h3>
|
||||
</div>
|
||||
)}
|
||||
|
@ -189,10 +189,7 @@ const ExistingIssuesListModal: React.FC<Props> = ({
|
||||
<LayerDiagonalIcon height="56" width="56" />
|
||||
<h3 className="text-gray-500">
|
||||
No issues found. Create a new issue with{" "}
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">
|
||||
Ctrl/Command + I
|
||||
</pre>
|
||||
.
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">C</pre>.
|
||||
</h3>
|
||||
</div>
|
||||
)}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { FC, useEffect, useState } from "react";
|
||||
import { FC, useEffect, useRef, useState } from "react";
|
||||
import dynamic from "next/dynamic";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
@ -33,10 +33,10 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = ({ issue, handleSubmi
|
||||
// description: issue?.description,
|
||||
// description_html: issue?.description_html,
|
||||
// });
|
||||
|
||||
const [issueName, setIssueName] = useState(issue?.name);
|
||||
const [issueDescription, setIssueDescription] = useState(issue?.description);
|
||||
const [issueDescriptionHTML, setIssueDescriptionHTML] = useState(issue?.description_html);
|
||||
const textareaRef = useRef<HTMLTextAreaElement | null>(null);
|
||||
|
||||
// hooks
|
||||
const formValues = useDebounce(
|
||||
@ -50,24 +50,34 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = ({ issue, handleSubmi
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [handleSubmit, stringFromValues]);
|
||||
|
||||
useEffect(() => {
|
||||
if (textareaRef && textareaRef.current) {
|
||||
textareaRef.current.style.height = "0px";
|
||||
const scrollHeight = textareaRef.current.scrollHeight;
|
||||
textareaRef.current.style.height = scrollHeight + "px";
|
||||
}
|
||||
}, [issueName]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Input
|
||||
<textarea
|
||||
id="name"
|
||||
placeholder="Enter issue name"
|
||||
name="name"
|
||||
autoComplete="off"
|
||||
value={issueName}
|
||||
onChange={(e) => setIssueName(e.target.value)}
|
||||
mode="transparent"
|
||||
className="text-xl font-medium"
|
||||
ref={textareaRef}
|
||||
rows={1}
|
||||
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setIssueName(e.target.value)}
|
||||
required={true}
|
||||
className="no-scrollbar w-full px-3 py-2 outline-none rounded border-none bg-transparent ring-0 transition-all focus:ring-1 focus:ring-theme text-xl font-medium resize-none"
|
||||
/>
|
||||
|
||||
<RemirrorRichTextEditor
|
||||
value={issueDescription}
|
||||
placeholder="Enter Your Text..."
|
||||
onJSONChange={(json) => setIssueDescription(json)}
|
||||
onHTMLChange={(html) => setIssueDescriptionHTML(html)}
|
||||
customClassName="min-h-[150px]"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -126,7 +126,7 @@ const CyclesBoardView: React.FC<Props> = ({
|
||||
return (
|
||||
<>
|
||||
{groupedByIssues ? (
|
||||
<div className="h-screen w-full">
|
||||
<div className="h-[calc(100vh-157px)] lg:h-[calc(100vh-115px)] w-full">
|
||||
<DragDropContext onDragEnd={handleOnDragEnd}>
|
||||
<div className="h-full w-full overflow-hidden">
|
||||
<div className="h-full w-full">
|
||||
|
@ -14,6 +14,9 @@ import cyclesService from "services/cycles.service";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Loader } from "components/ui";
|
||||
//progress-bar
|
||||
import { CircularProgressbar } from "react-circular-progressbar";
|
||||
import "react-circular-progressbar/dist/styles.css";
|
||||
// helpers
|
||||
import { copyTextToClipboard } from "helpers/string.helper";
|
||||
import { groupBy } from "helpers/array.helper";
|
||||
@ -135,7 +138,13 @@ const CycleDetailSidebar: React.FC<Props> = ({ cycle, isOpen, cycleIssues }) =>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 sm:basis-1/2">
|
||||
<div className="grid flex-shrink-0 place-items-center">
|
||||
<span className="h-4 w-4 rounded-full border-2 border-gray-300 border-r-blue-500" />
|
||||
<span className="h-4 w-4">
|
||||
<CircularProgressbar
|
||||
value={groupedIssues.completed.length}
|
||||
maxValue={cycleIssues?.length}
|
||||
strokeWidth={10}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
{groupedIssues.completed.length}/{cycleIssues?.length}
|
||||
</div>
|
||||
|
@ -64,7 +64,7 @@ const CycleStatsView: React.FC<TCycleStatsViewProps> = ({
|
||||
)}
|
||||
<h3 className="text-gray-500">
|
||||
No {type} {type === "current" ? "cycle" : "cycles"} yet. Create with{" "}
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">Ctrl/Command + Q</pre>.
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">Q</pre>.
|
||||
</h3>
|
||||
</div>
|
||||
)}
|
||||
|
@ -200,7 +200,7 @@ const BoardView: React.FC<Props> = ({ issues, handleDeleteIssue, userAuth }) =>
|
||||
}}
|
||||
/>
|
||||
{groupedByIssues ? (
|
||||
<div className="h-screen w-full">
|
||||
<div className="h-[calc(100vh-157px)] lg:h-[calc(100vh-115px)] w-full">
|
||||
<DragDropContext onDragEnd={handleOnDragEnd}>
|
||||
<div className="h-full w-full overflow-hidden">
|
||||
<StrictModeDroppable droppableId="state" type="state" direction="horizontal">
|
||||
|
@ -259,10 +259,7 @@ const SelectBlocked: React.FC<Props> = ({ submitChanges, issuesList, watch }) =>
|
||||
<LayerDiagonalIcon height="56" width="56" />
|
||||
<h3 className="text-gray-500">
|
||||
No issues found. Create a new issue with{" "}
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">
|
||||
Ctrl/Command + I
|
||||
</pre>
|
||||
.
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">C</pre>.
|
||||
</h3>
|
||||
</div>
|
||||
)}
|
||||
|
@ -258,10 +258,7 @@ const SelectBlocker: React.FC<Props> = ({ submitChanges, issuesList, watch }) =>
|
||||
<LayerDiagonalIcon height="56" width="56" />
|
||||
<h3 className="text-gray-500">
|
||||
No issues found. Create a new issue with{" "}
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">
|
||||
Ctrl/Command + I
|
||||
</pre>
|
||||
.
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">C</pre>.
|
||||
</h3>
|
||||
</div>
|
||||
)}
|
||||
|
@ -212,10 +212,7 @@ const IssuesListModal: React.FC<Props> = ({
|
||||
<LayerDiagonalIcon height="56" width="56" />
|
||||
<h3 className="text-gray-500">
|
||||
No issues found. Create a new issue with{" "}
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">
|
||||
Ctrl/Command + I
|
||||
</pre>
|
||||
.
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">C</pre>.
|
||||
</h3>
|
||||
</div>
|
||||
)}
|
||||
|
@ -129,7 +129,7 @@ const ModulesBoardView: React.FC<Props> = ({
|
||||
return (
|
||||
<>
|
||||
{groupedByIssues ? (
|
||||
<div className="h-screen w-full">
|
||||
<div className="h-[calc(100vh-157px)] lg:h-[calc(100vh-115px)] w-full">
|
||||
<DragDropContext onDragEnd={handleOnDragEnd}>
|
||||
<div className="h-full w-full overflow-hidden">
|
||||
<div className="h-full w-full">
|
||||
|
@ -22,6 +22,9 @@ import SelectLead from "components/project/modules/module-detail-sidebar/select-
|
||||
import SelectMembers from "components/project/modules/module-detail-sidebar/select-members";
|
||||
import SelectStatus from "components/project/modules/module-detail-sidebar/select-status";
|
||||
import ModuleLinkModal from "components/project/modules/module-link-modal";
|
||||
//progress-bar
|
||||
import { CircularProgressbar } from "react-circular-progressbar";
|
||||
import "react-circular-progressbar/dist/styles.css";
|
||||
// ui
|
||||
import { Loader } from "components/ui";
|
||||
// icons
|
||||
@ -161,7 +164,13 @@ const ModuleDetailSidebar: React.FC<Props> = ({
|
||||
</div>
|
||||
<div className="flex items-center gap-2 sm:basis-1/2">
|
||||
<div className="grid flex-shrink-0 place-items-center">
|
||||
<span className="h-4 w-4 rounded-full border-2 border-gray-300 border-r-blue-500" />
|
||||
<span className="h-4 w-4">
|
||||
<CircularProgressbar
|
||||
value={groupedIssues.completed.length}
|
||||
maxValue={moduleIssues?.length}
|
||||
strokeWidth={10}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
{groupedIssues.completed.length}/{moduleIssues?.length}
|
||||
</div>
|
||||
|
@ -1,14 +1,15 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { CalendarDaysIcon, TrashIcon } from "@heroicons/react/24/outline";
|
||||
import ConfirmModuleDeletion from "./confirm-module-deletion";
|
||||
// icons
|
||||
import { CalendarDaysIcon } from "@heroicons/react/24/outline";
|
||||
import User from "public/user.png";
|
||||
// helpers
|
||||
import { renderShortNumericDateFormat } from "helpers/date-time.helper";
|
||||
// types
|
||||
import { IModule } from "types";
|
||||
import { IModule, SelectModuleType } from "types";
|
||||
// common
|
||||
import { MODULE_STATUS } from "constants/";
|
||||
|
||||
@ -19,103 +20,131 @@ type Props = {
|
||||
const SingleModuleCard: React.FC<Props> = ({ module }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
const [moduleDeleteModal, setModuleDeleteModal] = useState(false);
|
||||
const [selectedModuleForDelete, setSelectedModuleForDelete] = useState<SelectModuleType>();
|
||||
const handleDeleteModule = () => {
|
||||
if (!module) return;
|
||||
|
||||
setSelectedModuleForDelete({ ...module, actionType: "delete" });
|
||||
setModuleDeleteModal(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<Link href={`/${workspaceSlug}/projects/${module.project}/modules/${module.id}`}>
|
||||
<a className="block cursor-pointer rounded-md border bg-white p-3">
|
||||
{module.name}
|
||||
<div className="mt-4 grid grid-cols-2 gap-2 text-xs md:grid-cols-4">
|
||||
<div className="space-y-2">
|
||||
<h6 className="text-gray-500">LEAD</h6>
|
||||
<div>
|
||||
{module.lead ? (
|
||||
module.lead_detail?.avatar && module.lead_detail.avatar !== "" ? (
|
||||
<div className="h-5 w-5 rounded-full border-2 border-white">
|
||||
<div className="group/card relative select-none p-2">
|
||||
<div className="absolute top-4 right-4 z-50 bg-red-200 opacity-0 group-hover/card:opacity-100">
|
||||
<button
|
||||
type="button"
|
||||
className="grid h-7 w-7 place-items-center bg-white p-1 text-red-500 outline-none duration-300 hover:bg-red-50"
|
||||
onClick={() => handleDeleteModule()}
|
||||
>
|
||||
<TrashIcon className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
<ConfirmModuleDeletion
|
||||
isOpen={
|
||||
moduleDeleteModal &&
|
||||
!!selectedModuleForDelete &&
|
||||
selectedModuleForDelete.actionType === "delete"
|
||||
}
|
||||
setIsOpen={setModuleDeleteModal}
|
||||
data={selectedModuleForDelete}
|
||||
/>
|
||||
<Link href={`/${workspaceSlug}/projects/${module.project}/modules/${module.id}`}>
|
||||
<a className="block cursor-pointer rounded-md border bg-white p-3">
|
||||
{module.name}
|
||||
<div className="mt-4 grid grid-cols-2 gap-2 text-xs md:grid-cols-4">
|
||||
<div className="space-y-2">
|
||||
<h6 className="text-gray-500">LEAD</h6>
|
||||
<div>
|
||||
{module.lead ? (
|
||||
module.lead_detail?.avatar && module.lead_detail.avatar !== "" ? (
|
||||
<div className="h-5 w-5 rounded-full border-2 border-white">
|
||||
<Image
|
||||
src={module.lead_detail.avatar}
|
||||
height="100%"
|
||||
width="100%"
|
||||
className="rounded-full"
|
||||
alt={module.lead_detail.first_name}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid h-5 w-5 place-items-center rounded-full border-2 border-white bg-gray-700 capitalize text-white">
|
||||
{module.lead_detail?.first_name && module.lead_detail.first_name !== ""
|
||||
? module.lead_detail.first_name.charAt(0)
|
||||
: module.lead_detail?.email.charAt(0)}
|
||||
</div>
|
||||
)
|
||||
) : (
|
||||
"N/A"
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h6 className="text-gray-500">MEMBERS</h6>
|
||||
<div className="flex items-center gap-1 text-xs">
|
||||
{module.members && module.members.length > 0 ? (
|
||||
module?.members_detail?.map((member, index: number) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`relative z-[1] h-5 w-5 rounded-full ${
|
||||
index !== 0 ? "-ml-2.5" : ""
|
||||
}`}
|
||||
>
|
||||
{member?.avatar && member.avatar !== "" ? (
|
||||
<div className="h-5 w-5 rounded-full border-2 border-white bg-white">
|
||||
<Image
|
||||
src={member.avatar}
|
||||
height="100%"
|
||||
width="100%"
|
||||
className="rounded-full"
|
||||
alt={member?.first_name}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid h-5 w-5 place-items-center rounded-full border-2 border-white bg-gray-700 capitalize text-white">
|
||||
{member?.first_name && member.first_name !== ""
|
||||
? member.first_name.charAt(0)
|
||||
: member?.email?.charAt(0)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="h-5 w-5 rounded-full border-2 border-white bg-white">
|
||||
<Image
|
||||
src={module.lead_detail.avatar}
|
||||
src={User}
|
||||
height="100%"
|
||||
width="100%"
|
||||
className="rounded-full"
|
||||
alt={module.lead_detail.first_name}
|
||||
alt="No user"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid h-5 w-5 place-items-center rounded-full border-2 border-white bg-gray-700 capitalize text-white">
|
||||
{module.lead_detail?.first_name && module.lead_detail.first_name !== ""
|
||||
? module.lead_detail.first_name.charAt(0)
|
||||
: module.lead_detail?.email.charAt(0)}
|
||||
</div>
|
||||
)
|
||||
) : (
|
||||
"N/A"
|
||||
)}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h6 className="text-gray-500">END DATE</h6>
|
||||
<div className="flex w-min cursor-pointer items-center gap-1 whitespace-nowrap rounded border px-1.5 py-0.5 text-xs shadow-sm">
|
||||
<CalendarDaysIcon className="h-3 w-3" />
|
||||
{renderShortNumericDateFormat(module.target_date ?? "")}
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h6 className="text-gray-500">STATUS</h6>
|
||||
<div className="flex items-center gap-2 capitalize">
|
||||
<span
|
||||
className="h-2 w-2 flex-shrink-0 rounded-full"
|
||||
style={{
|
||||
backgroundColor: MODULE_STATUS.find((s) => s.value === module.status)?.color,
|
||||
}}
|
||||
/>
|
||||
{module.status}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h6 className="text-gray-500">MEMBERS</h6>
|
||||
<div className="flex items-center gap-1 text-xs">
|
||||
{module.members && module.members.length > 0 ? (
|
||||
module?.members_detail?.map((member, index: number) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`relative z-[1] h-5 w-5 rounded-full ${
|
||||
index !== 0 ? "-ml-2.5" : ""
|
||||
}`}
|
||||
>
|
||||
{member?.avatar && member.avatar !== "" ? (
|
||||
<div className="h-5 w-5 rounded-full border-2 border-white bg-white">
|
||||
<Image
|
||||
src={member.avatar}
|
||||
height="100%"
|
||||
width="100%"
|
||||
className="rounded-full"
|
||||
alt={member?.first_name}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid h-5 w-5 place-items-center rounded-full border-2 border-white bg-gray-700 capitalize text-white">
|
||||
{member?.first_name && member.first_name !== ""
|
||||
? member.first_name.charAt(0)
|
||||
: member?.email?.charAt(0)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="h-5 w-5 rounded-full border-2 border-white bg-white">
|
||||
<Image
|
||||
src={User}
|
||||
height="100%"
|
||||
width="100%"
|
||||
className="rounded-full"
|
||||
alt="No user"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h6 className="text-gray-500">END DATE</h6>
|
||||
<div className="flex w-min cursor-pointer items-center gap-1 whitespace-nowrap rounded border px-1.5 py-0.5 text-xs shadow-sm">
|
||||
<CalendarDaysIcon className="h-3 w-3" />
|
||||
{renderShortNumericDateFormat(module.target_date ?? "")}
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h6 className="text-gray-500">STATUS</h6>
|
||||
<div className="flex items-center gap-2 capitalize">
|
||||
<span
|
||||
className="h-2 w-2 flex-shrink-0 rounded-full"
|
||||
style={{
|
||||
backgroundColor: MODULE_STATUS.find((s) => s.value === module.status)?.color,
|
||||
}}
|
||||
/>
|
||||
{module.status}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -47,6 +47,7 @@ export interface IRemirrorRichTextEditor {
|
||||
value?: any;
|
||||
showToolbar?: boolean;
|
||||
editable?: boolean;
|
||||
customClassName?: string;
|
||||
}
|
||||
|
||||
const RemirrorRichTextEditor: FC<IRemirrorRichTextEditor> = (props) => {
|
||||
@ -60,6 +61,7 @@ const RemirrorRichTextEditor: FC<IRemirrorRichTextEditor> = (props) => {
|
||||
value = "",
|
||||
showToolbar = true,
|
||||
editable = true,
|
||||
customClassName,
|
||||
} = props;
|
||||
|
||||
const [imageLoader, setImageLoader] = useState(false);
|
||||
@ -173,7 +175,7 @@ const RemirrorRichTextEditor: FC<IRemirrorRichTextEditor> = (props) => {
|
||||
<Remirror
|
||||
manager={manager}
|
||||
initialContent={state}
|
||||
classNames={["p-4 focus:outline-none"]}
|
||||
classNames={[`p-4 focus:outline-none ${customClassName}`]}
|
||||
editable={editable}
|
||||
onBlur={() => {
|
||||
onBlur(jsonValue, htmlValue);
|
||||
|
@ -132,7 +132,7 @@ export const WorkspaceHelpSection: FC<WorkspaceHelpSectionProps> = (props) => {
|
||||
title="Help"
|
||||
>
|
||||
<QuestionMarkCircleIcon className="h-4 w-4 text-gray-500" />
|
||||
{!sidebarCollapse && <span>Need help?</span>}
|
||||
{!sidebarCollapse && <span>Help ?</span>}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -173,7 +173,7 @@ const Sidebar: React.FC<Props> = ({ toggleSidebar, setToggleSidebar }) => {
|
||||
title="Help"
|
||||
>
|
||||
<QuestionMarkCircleIcon className="h-4 w-4 text-gray-500" />
|
||||
{!sidebarCollapse && <span>Need help?</span>}
|
||||
{!sidebarCollapse && <span>Help ?</span>}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -21,6 +21,7 @@
|
||||
"next-pwa": "^5.6.0",
|
||||
"react": "18.2.0",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-circular-progressbar": "^2.1.0",
|
||||
"react-color": "^2.19.3",
|
||||
"react-dom": "18.2.0",
|
||||
"react-dropzone": "^14.2.3",
|
||||
|
@ -164,8 +164,7 @@ const WorkspacePage: NextPage = () => {
|
||||
<LayerDiagonalIcon height="56" width="56" />
|
||||
<h3 className="text-gray-500">
|
||||
No issues found. Create a new issue with{" "}
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">Ctrl/Command + I</pre>
|
||||
.
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">C</pre>.
|
||||
</h3>
|
||||
</div>
|
||||
)
|
||||
|
@ -163,9 +163,8 @@ const MyIssuesPage: NextPage = () => {
|
||||
title="Create a new issue"
|
||||
description={
|
||||
<span>
|
||||
Use{" "}
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">Ctrl/Command + I</pre>{" "}
|
||||
shortcut to create a new issue
|
||||
Use <pre className="inline rounded bg-gray-100 px-2 py-1">C</pre> shortcut
|
||||
to create a new issue
|
||||
</span>
|
||||
}
|
||||
Icon={PlusIcon}
|
||||
|
@ -178,8 +178,8 @@ const ProjectCycles: NextPage = () => {
|
||||
title="Create a new cycle"
|
||||
description={
|
||||
<span>
|
||||
Use <pre className="inline rounded bg-gray-100 px-2 py-1">Ctrl/Command + Q</pre>{" "}
|
||||
shortcut to create a new cycle
|
||||
Use <pre className="inline rounded bg-gray-100 px-2 py-1">Q</pre> shortcut to
|
||||
create a new cycle
|
||||
</span>
|
||||
}
|
||||
Icon={PlusIcon}
|
||||
|
@ -133,8 +133,8 @@ const ProjectIssues: NextPage<UserAuth> = (props) => {
|
||||
title="Create a new issue"
|
||||
description={
|
||||
<span>
|
||||
Use <pre className="inline rounded bg-gray-100 px-2 py-1">Ctrl/Command + I</pre>{" "}
|
||||
shortcut to create a new issue
|
||||
Use <pre className="inline rounded bg-gray-100 px-2 py-1">C</pre> shortcut to
|
||||
create a new issue
|
||||
</span>
|
||||
}
|
||||
Icon={PlusIcon}
|
||||
|
@ -86,8 +86,8 @@ const ProjectModules: NextPage = () => {
|
||||
title="Create a new module"
|
||||
description={
|
||||
<span>
|
||||
Use <pre className="inline rounded bg-gray-100 px-2 py-1">Ctrl/Command + M</pre>{" "}
|
||||
shortcut to create a new module
|
||||
Use <pre className="inline rounded bg-gray-100 px-2 py-1">M</pre> shortcut to
|
||||
create a new module
|
||||
</span>
|
||||
}
|
||||
Icon={PlusIcon}
|
||||
|
@ -88,9 +88,8 @@ const ProjectsPage: NextPage = () => {
|
||||
title="Create a new project"
|
||||
description={
|
||||
<span>
|
||||
Use{" "}
|
||||
<pre className="inline rounded bg-gray-100 px-2 py-1">Ctrl/Command + P</pre>{" "}
|
||||
shortcut to create a new project
|
||||
Use <pre className="inline rounded bg-gray-100 px-2 py-1">P</pre> shortcut to
|
||||
create a new project
|
||||
</span>
|
||||
}
|
||||
Icon={PlusIcon}
|
||||
|
@ -354,10 +354,6 @@ img.ProseMirror-separator {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.remirror-editor-wrapper .remirror-editor {
|
||||
min-height: 150px;
|
||||
}
|
||||
|
||||
.issue-comments-section .remirror-editor-wrapper .remirror-editor {
|
||||
min-height: 50px;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ importers:
|
||||
postcss: ^8.4.14
|
||||
react: 18.2.0
|
||||
react-beautiful-dnd: ^13.1.1
|
||||
react-circular-progressbar: ^2.1.0
|
||||
react-color: ^2.19.3
|
||||
react-dom: 18.2.0
|
||||
react-dropzone: ^14.2.3
|
||||
@ -63,6 +64,7 @@ importers:
|
||||
next-pwa: 5.6.0_next@12.3.2
|
||||
react: 18.2.0
|
||||
react-beautiful-dnd: 13.1.1_biqbaboplfbrettd7655fr4n2y
|
||||
react-circular-progressbar: 2.1.0_react@18.2.0
|
||||
react-color: 2.19.3_react@18.2.0
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
react-dropzone: 14.2.3_react@18.2.0
|
||||
@ -8326,6 +8328,14 @@ packages:
|
||||
- react-native
|
||||
dev: false
|
||||
|
||||
/react-circular-progressbar/2.1.0_react@18.2.0:
|
||||
resolution: {integrity: sha512-xp4THTrod4aLpGy68FX/k1Q3nzrfHUjUe5v6FsdwXBl3YVMwgeXYQKDrku7n/D6qsJA9CuunarAboC2xCiKs1g==}
|
||||
peerDependencies:
|
||||
react: ^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/react-color/2.19.3_react@18.2.0:
|
||||
resolution: {integrity: sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==}
|
||||
peerDependencies:
|
||||
|
Loading…
Reference in New Issue
Block a user