mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fix: bug fixes (#1000)
* fix: issue sidebar cycle and module dropdown fix * style: my issue page * style: date picker theming * fix: cycle modal * style: date picker * fix: info icon fix * feat: integration banner * feat: project integration banner * fix: module card progress bar fix * style: integration banner * style: workspace sidebar * fix: cycle date checker * fix: calendar page view dropdown
This commit is contained in:
parent
93c105c495
commit
86cb23777e
@ -134,7 +134,7 @@ export const IssuesFilterView: React.FC = () => {
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 translate-y-1"
|
||||
>
|
||||
<Popover.Panel className="absolute right-0 z-20 mt-1 w-screen max-w-xs transform overflow-hidden rounded-lg border border-brand-base bg-brand-surface-1 p-3 shadow-lg">
|
||||
<Popover.Panel className="absolute right-0 z-20 mt-1 w-screen max-w-xs transform rounded-lg border border-brand-base bg-brand-surface-1 p-3 shadow-lg">
|
||||
<div className="relative divide-y-2 divide-brand-base">
|
||||
<div className="space-y-4 pb-3 text-xs">
|
||||
{issueView !== "calendar" && (
|
||||
|
@ -65,7 +65,11 @@ export const CompletedCyclesList: React.FC<CompletedCyclesListProps> = ({
|
||||
completedCycles.completed_cycles.length > 0 ? (
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex items-center gap-2 text-sm text-brand-secondary">
|
||||
<ExclamationIcon height={14} width={14} />
|
||||
<ExclamationIcon
|
||||
height={14}
|
||||
width={14}
|
||||
className="fill-current text-brand-secondary"
|
||||
/>
|
||||
<span>Completed cycles are not editable.</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-9 md:grid-cols-2 lg:grid-cols-3">
|
||||
|
@ -1,21 +1,10 @@
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
import { useEffect } from "react";
|
||||
|
||||
// react-hook-form
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
// services
|
||||
import cyclesService from "services/cycles.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
|
||||
// ui
|
||||
import { DateSelect, Input, PrimaryButton, SecondaryButton, TextArea } from "components/ui";
|
||||
// helpers
|
||||
import {
|
||||
getDateRangeStatus,
|
||||
isDateGreaterThanToday,
|
||||
isDateRangeValid,
|
||||
} from "helpers/date-time.helper";
|
||||
// types
|
||||
import { ICycle } from "types";
|
||||
|
||||
@ -34,13 +23,6 @@ const defaultValues: Partial<ICycle> = {
|
||||
};
|
||||
|
||||
export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, status, data }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const [isDateValid, setIsDateValid] = useState(true);
|
||||
|
||||
const {
|
||||
register,
|
||||
formState: { errors, isSubmitting },
|
||||
@ -60,43 +42,6 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
|
||||
});
|
||||
};
|
||||
|
||||
const cycleStatus =
|
||||
data?.start_date && data?.end_date ? getDateRangeStatus(data?.start_date, data?.end_date) : "";
|
||||
|
||||
const dateChecker = async (payload: any) => {
|
||||
if (isDateGreaterThanToday(payload.end_date)) {
|
||||
await cyclesService
|
||||
.cycleDateCheck(workspaceSlug as string, projectId as string, payload)
|
||||
.then((res) => {
|
||||
if (res.status) {
|
||||
setIsDateValid(true);
|
||||
} else {
|
||||
setIsDateValid(false);
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Error!",
|
||||
message:
|
||||
"You have a cycle already on the given dates, if you want to create your draft cycle you can do that by removing dates",
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
} else {
|
||||
setIsDateValid(false);
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Error!",
|
||||
message: "Unable to create cycle in past date. Please enter a valid date.",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const checkEmptyDate =
|
||||
(watch("start_date") === "" && watch("end_date") === "") ||
|
||||
(!watch("start_date") && !watch("end_date"));
|
||||
|
||||
useEffect(() => {
|
||||
reset({
|
||||
...defaultValues,
|
||||
@ -147,30 +92,7 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
|
||||
control={control}
|
||||
name="start_date"
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<DateSelect
|
||||
label="Start date"
|
||||
value={value}
|
||||
onChange={(val) => {
|
||||
onChange(val);
|
||||
if (val && watch("end_date")) {
|
||||
if (isDateRangeValid(val, `${watch("end_date")}`)) {
|
||||
cycleStatus != "current" &&
|
||||
dateChecker({
|
||||
start_date: val,
|
||||
end_date: watch("end_date"),
|
||||
});
|
||||
} else {
|
||||
setIsDateValid(false);
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Error!",
|
||||
message:
|
||||
"The date you have entered is invalid. Please check and enter a valid date.",
|
||||
});
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<DateSelect label="Start date" value={value} onChange={(val) => onChange(val)} />
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@ -179,30 +101,7 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
|
||||
control={control}
|
||||
name="end_date"
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<DateSelect
|
||||
label="End date"
|
||||
value={value}
|
||||
onChange={(val) => {
|
||||
onChange(val);
|
||||
if (watch("start_date") && val) {
|
||||
if (isDateRangeValid(`${watch("start_date")}`, val)) {
|
||||
cycleStatus != "current" &&
|
||||
dateChecker({
|
||||
start_date: watch("start_date"),
|
||||
end_date: val,
|
||||
});
|
||||
} else {
|
||||
setIsDateValid(false);
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Error!",
|
||||
message:
|
||||
"The date you have entered is invalid. Please check and enter a valid date.",
|
||||
});
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<DateSelect label="End date" value={value} onChange={(val) => onChange(val)} />
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@ -211,18 +110,7 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
|
||||
</div>
|
||||
<div className="-mx-5 mt-5 flex justify-end gap-2 border-t border-brand-base px-5 pt-5">
|
||||
<SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
|
||||
<PrimaryButton
|
||||
type="submit"
|
||||
className={
|
||||
checkEmptyDate
|
||||
? "cursor-pointer"
|
||||
: isDateValid
|
||||
? "cursor-pointer"
|
||||
: "cursor-not-allowed"
|
||||
}
|
||||
disabled={checkEmptyDate ? false : isDateValid ? false : true}
|
||||
loading={isSubmitting}
|
||||
>
|
||||
<PrimaryButton type="submit" loading={isSubmitting}>
|
||||
{status
|
||||
? isSubmitting
|
||||
? "Updating Cycle..."
|
||||
|
@ -13,7 +13,7 @@ import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { CycleForm } from "components/cycles";
|
||||
// helper
|
||||
import { getDateRangeStatus } from "helpers/date-time.helper";
|
||||
import { getDateRangeStatus, isDateGreaterThanToday } from "helpers/date-time.helper";
|
||||
// types
|
||||
import type { ICycle } from "types";
|
||||
// fetch keys
|
||||
@ -128,6 +128,21 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
|
||||
});
|
||||
};
|
||||
|
||||
const dateChecker = async (payload: any) => {
|
||||
try {
|
||||
const res = await cycleService.cycleDateCheck(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
payload
|
||||
);
|
||||
console.log(res);
|
||||
return res.status;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleFormSubmit = async (formData: Partial<ICycle>) => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
@ -135,8 +150,63 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
|
||||
...formData,
|
||||
};
|
||||
|
||||
if (!data) await createCycle(payload);
|
||||
else await updateCycle(data.id, payload);
|
||||
if (payload.start_date && payload.end_date) {
|
||||
if (!isDateGreaterThanToday(payload.end_date)) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Error!",
|
||||
message: "Unable to create cycle in past date. Please enter a valid date.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const isDateValid = await dateChecker({
|
||||
start_date: payload.start_date,
|
||||
end_date: payload.end_date,
|
||||
});
|
||||
|
||||
if (data?.start_date && data?.end_date) {
|
||||
const isDateValidForExistingCycle = await dateChecker({
|
||||
start_date: payload.start_date,
|
||||
end_date: payload.end_date,
|
||||
cycle_id: data.id,
|
||||
});
|
||||
|
||||
if (isDateValidForExistingCycle) {
|
||||
await updateCycle(data.id, payload);
|
||||
return;
|
||||
} else {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Error!",
|
||||
message:
|
||||
"You have a cycle already on the given dates, if you want to create your draft cycle you can do that by removing dates",
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isDateValid) {
|
||||
if (data) {
|
||||
await updateCycle(data.id, payload);
|
||||
} else {
|
||||
await createCycle(payload);
|
||||
}
|
||||
} else {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Error!",
|
||||
message:
|
||||
"You have a cycle already on the given dates, if you want to create your draft cycle you can do that by removing dates",
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (data) {
|
||||
await updateCycle(data.id, payload);
|
||||
} else {
|
||||
await createCycle(payload);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -370,7 +370,11 @@ export const CycleDetailsSidebar: React.FC<Props> = ({
|
||||
</Disclosure.Button>
|
||||
) : (
|
||||
<div className="flex items-center gap-1">
|
||||
<ExclamationIcon height={14} width={14} />
|
||||
<ExclamationIcon
|
||||
height={14}
|
||||
width={14}
|
||||
className="fill-current text-brand-secondary"
|
||||
/>
|
||||
<span className="text-xs italic text-brand-secondary">
|
||||
{cycleStatus === "upcoming"
|
||||
? "Cycle is yet to start."
|
||||
@ -444,7 +448,11 @@ export const CycleDetailsSidebar: React.FC<Props> = ({
|
||||
</Disclosure.Button>
|
||||
) : (
|
||||
<div className="flex items-center gap-1">
|
||||
<ExclamationIcon height={14} width={14} />
|
||||
<ExclamationIcon
|
||||
height={14}
|
||||
width={14}
|
||||
className="fill-current text-brand-secondary"
|
||||
/>
|
||||
<span className="text-xs italic text-brand-secondary">
|
||||
No issues found. Please add issue.
|
||||
</span>
|
||||
|
@ -148,7 +148,11 @@ export const TransferIssuesModal: React.FC<Props> = ({ isOpen, handleClose }) =>
|
||||
))
|
||||
) : (
|
||||
<div className="flex w-full items-center justify-center gap-4 p-5 text-sm">
|
||||
<ExclamationIcon height={14} width={14} />
|
||||
<ExclamationIcon
|
||||
height={14}
|
||||
width={14}
|
||||
className="fill-current text-brand-secondary"
|
||||
/>
|
||||
<span className="text-center text-brand-secondary">
|
||||
You don’t have any current cycle. Please create one to transfer the
|
||||
issues.
|
||||
|
@ -39,7 +39,7 @@ export const TransferIssues: React.FC<Props> = ({ handleClick }) => {
|
||||
return (
|
||||
<div className="-mt-2 mb-4 flex items-center justify-between">
|
||||
<div className="flex items-center gap-2 text-sm text-brand-secondary">
|
||||
<ExclamationIcon height={14} width={14} />
|
||||
<ExclamationIcon height={14} width={14} className="fill-current text-brand-secondary" />
|
||||
<span>Completed cycles are not editable.</span>
|
||||
</div>
|
||||
|
||||
|
@ -7,10 +7,10 @@ export const ExclamationIcon: React.FC<Props> = ({ width, height, className }) =
|
||||
width={width}
|
||||
height={height}
|
||||
className={className}
|
||||
viewBox="0 0 14 15"
|
||||
viewBox="0 0 15 15"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M7.55321 11.042C7.70668 11.042 7.83359 10.9918 7.93394 10.8915C8.03428 10.7911 8.08446 10.6642 8.08446 10.5107V7.30553C8.08446 7.16387 8.03133 7.04286 7.92508 6.94251C7.81883 6.84217 7.69487 6.79199 7.55321 6.79199C7.39973 6.79199 7.27283 6.84217 7.17248 6.94251C7.07213 7.04286 7.02196 7.16977 7.02196 7.32324V10.5285C7.02196 10.6701 7.07508 10.7911 7.18133 10.8915C7.28758 10.9918 7.41154 11.042 7.55321 11.042ZM7.50008 5.48158C7.66536 5.48158 7.80407 5.42845 7.91623 5.3222C8.02838 5.21595 8.08446 5.08019 8.08446 4.91491C8.08446 4.74963 8.02838 4.60796 7.91623 4.48991C7.80407 4.37185 7.66536 4.31283 7.50008 4.31283C7.3348 4.31283 7.19609 4.37185 7.08394 4.48991C6.97178 4.60796 6.91571 4.74963 6.91571 4.91491C6.91571 5.08019 6.97178 5.21595 7.08394 5.3222C7.19609 5.42845 7.3348 5.48158 7.50008 5.48158ZM7.50008 14.5837C6.49661 14.5837 5.56397 14.4036 4.70217 14.0436C3.84036 13.6835 3.09071 13.1847 2.45321 12.5472C1.81571 11.9097 1.31692 11.16 0.956852 10.2982C0.596783 9.43644 0.416748 8.5038 0.416748 7.50033C0.416748 6.50866 0.596783 5.58192 0.956852 4.72012C1.31692 3.85831 1.81571 3.10866 2.45321 2.47116C3.09071 1.83366 3.84036 1.33192 4.70217 0.965951C5.56397 0.599978 6.49661 0.416992 7.50008 0.416992C8.49175 0.416992 9.41848 0.599978 10.2803 0.965951C11.1421 1.33192 11.8917 1.83366 12.5292 2.47116C13.1667 3.10866 13.6685 3.85831 14.0345 4.72012C14.4004 5.58192 14.5834 6.50866 14.5834 7.50033C14.5834 8.5038 14.4004 9.43644 14.0345 10.2982C13.6685 11.16 13.1667 11.9097 12.5292 12.5472C11.8917 13.1847 11.1421 13.6835 10.2803 14.0436C9.41848 14.4036 8.49175 14.5837 7.50008 14.5837ZM7.50008 13.5212C9.15286 13.5212 10.5695 12.9309 11.7501 11.7503C12.9306 10.5698 13.5209 9.1531 13.5209 7.50033C13.5209 5.84755 12.9306 4.43088 11.7501 3.25033C10.5695 2.06977 9.15286 1.47949 7.50008 1.47949C5.8473 1.47949 4.43064 2.06977 3.25008 3.25033C2.06953 4.43088 1.47925 5.84755 1.47925 7.50033C1.47925 9.1531 2.06953 10.5698 3.25008 11.7503C4.43064 12.9309 5.8473 13.5212 7.50008 13.5212Z" fill="#858E96"/>
|
||||
<path d="M7.55321 11.042C7.70668 11.042 7.83359 10.9918 7.93394 10.8915C8.03428 10.7911 8.08446 10.6642 8.08446 10.5107V7.30553C8.08446 7.16387 8.03133 7.04286 7.92508 6.94251C7.81883 6.84217 7.69487 6.79199 7.55321 6.79199C7.39973 6.79199 7.27283 6.84217 7.17248 6.94251C7.07213 7.04286 7.02196 7.16977 7.02196 7.32324V10.5285C7.02196 10.6701 7.07508 10.7911 7.18133 10.8915C7.28758 10.9918 7.41154 11.042 7.55321 11.042ZM7.50008 5.48158C7.66536 5.48158 7.80407 5.42845 7.91623 5.3222C8.02838 5.21595 8.08446 5.08019 8.08446 4.91491C8.08446 4.74963 8.02838 4.60796 7.91623 4.48991C7.80407 4.37185 7.66536 4.31283 7.50008 4.31283C7.3348 4.31283 7.19609 4.37185 7.08394 4.48991C6.97178 4.60796 6.91571 4.74963 6.91571 4.91491C6.91571 5.08019 6.97178 5.21595 7.08394 5.3222C7.19609 5.42845 7.3348 5.48158 7.50008 5.48158ZM7.50008 14.5837C6.49661 14.5837 5.56397 14.4036 4.70217 14.0436C3.84036 13.6835 3.09071 13.1847 2.45321 12.5472C1.81571 11.9097 1.31692 11.16 0.956852 10.2982C0.596783 9.43644 0.416748 8.5038 0.416748 7.50033C0.416748 6.50866 0.596783 5.58192 0.956852 4.72012C1.31692 3.85831 1.81571 3.10866 2.45321 2.47116C3.09071 1.83366 3.84036 1.33192 4.70217 0.965951C5.56397 0.599978 6.49661 0.416992 7.50008 0.416992C8.49175 0.416992 9.41848 0.599978 10.2803 0.965951C11.1421 1.33192 11.8917 1.83366 12.5292 2.47116C13.1667 3.10866 13.6685 3.85831 14.0345 4.72012C14.4004 5.58192 14.5834 6.50866 14.5834 7.50033C14.5834 8.5038 14.4004 9.43644 14.0345 10.2982C13.6685 11.16 13.1667 11.9097 12.5292 12.5472C11.8917 13.1847 11.1421 13.6835 10.2803 14.0436C9.41848 14.4036 8.49175 14.5837 7.50008 14.5837ZM7.50008 13.5212C9.15286 13.5212 10.5695 12.9309 11.7501 11.7503C12.9306 10.5698 13.5209 9.1531 13.5209 7.50033C13.5209 5.84755 12.9306 4.43088 11.7501 3.25033C10.5695 2.06977 9.15286 1.47949 7.50008 1.47949C5.8473 1.47949 4.43064 2.06977 3.25008 3.25033C2.06953 4.43088 1.47925 5.84755 1.47925 7.50033C1.47925 9.1531 2.06953 10.5698 3.25008 11.7503C4.43064 12.9309 5.8473 13.5212 7.50008 13.5212Z" />
|
||||
</svg>
|
||||
);
|
||||
|
@ -231,6 +231,16 @@ export const IssueActivitySection: React.FC = () => {
|
||||
action = `${activityItem.verb} the`;
|
||||
} else if (activityItem.field === "estimate") {
|
||||
action = "updated the";
|
||||
} else if (activityItem.field === "cycles") {
|
||||
action =
|
||||
activityItem.new_value && activityItem.new_value !== ""
|
||||
? "set the cycle to"
|
||||
: "removed the cycle";
|
||||
} else if (activityItem.field === "modules") {
|
||||
action =
|
||||
activityItem.new_value && activityItem.new_value !== ""
|
||||
? "set the module to"
|
||||
: "removed the module";
|
||||
}
|
||||
// for values that are after the action clause
|
||||
let value: any = activityItem.new_value ? activityItem.new_value : activityItem.old_value;
|
||||
@ -282,6 +292,18 @@ export const IssueActivitySection: React.FC = () => {
|
||||
value = "description";
|
||||
} else if (activityItem.field === "attachment") {
|
||||
value = "attachment";
|
||||
} else if (activityItem.field === "cycles") {
|
||||
const cycles =
|
||||
activityItem.new_value && activityItem.new_value !== ""
|
||||
? activityItem.new_value
|
||||
: activityItem.old_value;
|
||||
value = cycles ? addSpaceIfCamelCase(cycles) : "None";
|
||||
} else if (activityItem.field === "modules") {
|
||||
const modules =
|
||||
activityItem.new_value && activityItem.new_value !== ""
|
||||
? activityItem.new_value
|
||||
: activityItem.old_value;
|
||||
value = modules ? addSpaceIfCamelCase(modules) : "None";
|
||||
} else if (activityItem.field === "link") {
|
||||
value = "link";
|
||||
} else if (activityItem.field === "estimate_point") {
|
||||
|
@ -82,7 +82,7 @@ export const IssueAttachments = () => {
|
||||
} uploaded on ${renderLongDateFormat(file.updated_at)}`}
|
||||
>
|
||||
<span>
|
||||
<ExclamationIcon className="h-3 w-3" />
|
||||
<ExclamationIcon className="h-3 w-3 fill-current text-brand-base" />
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
@ -82,7 +82,7 @@ export const MyIssuesListItem: React.FC<Props> = ({ issue, properties, projectId
|
||||
const isNotAllowed = false;
|
||||
|
||||
return (
|
||||
<div className="border-b border-brand-base last:border-b-0 mx-6">
|
||||
<div className="mx-6 border-b border-brand-base last:border-b-0">
|
||||
<div key={issue.id} className="flex items-center justify-between gap-2 py-3">
|
||||
<Link href={`/${workspaceSlug}/projects/${issue?.project_detail?.id}/issues/${issue.id}`}>
|
||||
<a className="group relative flex items-center gap-2">
|
||||
@ -91,13 +91,13 @@ export const MyIssuesListItem: React.FC<Props> = ({ issue, properties, projectId
|
||||
tooltipHeading="Issue ID"
|
||||
tooltipContent={`${issue.project_detail?.identifier}-${issue.sequence_id}`}
|
||||
>
|
||||
<span className="flex-shrink-0 text-xs text-gray-400">
|
||||
<span className="flex-shrink-0 text-xs text-brand-secondary">
|
||||
{issue.project_detail?.identifier}-{issue.sequence_id}
|
||||
</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip position="top-left" tooltipHeading="Title" tooltipContent={issue.name}>
|
||||
<span className="break-all text-sm text-brand-base">
|
||||
<span className="text-[0.825rem] text-brand-base">
|
||||
{truncateText(issue.name, 50)}
|
||||
</span>
|
||||
</Tooltip>
|
||||
@ -127,7 +127,7 @@ export const MyIssuesListItem: React.FC<Props> = ({ issue, properties, projectId
|
||||
/>
|
||||
)}
|
||||
{properties.sub_issue_count && (
|
||||
<div className="flex items-center gap-1 rounded-md border border-brand-base px-3 py-1.5 text-xs shadow-sm">
|
||||
<div className="flex items-center gap-1 rounded-md border border-brand-base px-2 py-1 text-xs text-brand-secondary shadow-sm">
|
||||
{issue?.sub_issues_count} {issue?.sub_issues_count === 1 ? "sub-issue" : "sub-issues"}
|
||||
</div>
|
||||
)}
|
||||
@ -136,10 +136,10 @@ export const MyIssuesListItem: React.FC<Props> = ({ issue, properties, projectId
|
||||
{issue.label_details.map((label) => (
|
||||
<span
|
||||
key={label.id}
|
||||
className="group flex items-center gap-1 rounded-2xl border border-brand-base px-2 py-0.5 text-xs"
|
||||
className="group flex items-center gap-1 rounded-2xl border border-brand-base px-2 py-0.5 text-xs text-brand-secondary"
|
||||
>
|
||||
<span
|
||||
className="h-1.5 w-1.5 flex-shrink-0 rounded-full"
|
||||
className="h-1.5 w-1.5 rounded-full"
|
||||
style={{
|
||||
backgroundColor: label?.color && label.color !== "" ? label.color : "#000",
|
||||
}}
|
||||
@ -171,20 +171,20 @@ export const MyIssuesListItem: React.FC<Props> = ({ issue, properties, projectId
|
||||
</Tooltip>
|
||||
)}
|
||||
{properties.link && (
|
||||
<div className="flex items-center rounded-md shadow-sm px-2.5 py-1 cursor-default text-xs border border-gray-200">
|
||||
<div className="flex cursor-default items-center rounded-md border border-brand-base px-2.5 py-1 text-xs shadow-sm">
|
||||
<Tooltip tooltipHeading="Link" tooltipContent={`${issue.link_count}`}>
|
||||
<div className="flex items-center gap-1 text-gray-500">
|
||||
<LinkIcon className="h-3.5 w-3.5 text-gray-500" />
|
||||
<div className="flex items-center gap-1 text-brand-secondary">
|
||||
<LinkIcon className="h-3.5 w-3.5 text-brand-secondary" />
|
||||
{issue.link_count}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
{properties.attachment_count && (
|
||||
<div className="flex items-center rounded-md shadow-sm px-2.5 py-1 cursor-default text-xs border border-gray-200">
|
||||
<div className="flex cursor-default items-center rounded-md border border-brand-base px-2.5 py-1 text-xs shadow-sm">
|
||||
<Tooltip tooltipHeading="Attachment" tooltipContent={`${issue.attachment_count}`}>
|
||||
<div className="flex items-center gap-1 text-gray-500">
|
||||
<PaperClipIcon className="h-3.5 w-3.5 text-gray-500 -rotate-45" />
|
||||
<div className="flex items-center gap-1 text-brand-secondary">
|
||||
<PaperClipIcon className="h-3.5 w-3.5 -rotate-45 text-brand-secondary" />
|
||||
{issue.attachment_count}
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
@ -78,7 +78,7 @@ export const SidebarCycleSelect: React.FC<Props> = ({
|
||||
</span>
|
||||
</Tooltip>
|
||||
}
|
||||
value={issueCycle?.cycle_detail.id}
|
||||
value={issueCycle ? issueCycle.cycle_detail.id : null}
|
||||
onChange={(value: any) => {
|
||||
!value
|
||||
? removeIssueFromCycle(issueCycle?.id ?? "", issueCycle?.cycle ?? "")
|
||||
|
@ -82,7 +82,7 @@ export const SidebarModuleSelect: React.FC<Props> = ({
|
||||
</span>
|
||||
</Tooltip>
|
||||
}
|
||||
value={issueModule?.module_detail?.id}
|
||||
value={issueModule ? issueModule.module_detail?.id : null}
|
||||
onChange={(value: any) => {
|
||||
!value
|
||||
? removeIssueFromModule(issueModule?.id ?? "", issueModule?.module ?? "")
|
||||
|
@ -416,7 +416,11 @@ export const ModuleDetailsSidebar: React.FC<Props> = ({ issues, module, isOpen,
|
||||
</Disclosure.Button>
|
||||
) : (
|
||||
<div className="flex items-center gap-1">
|
||||
<ExclamationIcon height={14} width={14} />
|
||||
<ExclamationIcon
|
||||
height={14}
|
||||
width={14}
|
||||
className="fill-current text-brand-secondary"
|
||||
/>
|
||||
<span className="text-xs italic text-brand-secondary">
|
||||
Invalid date. Please enter valid date.
|
||||
</span>
|
||||
@ -488,7 +492,11 @@ export const ModuleDetailsSidebar: React.FC<Props> = ({ issues, module, isOpen,
|
||||
</Disclosure.Button>
|
||||
) : (
|
||||
<div className="flex items-center gap-1">
|
||||
<ExclamationIcon height={14} width={14} />
|
||||
<ExclamationIcon
|
||||
height={14}
|
||||
width={14}
|
||||
className="fill-current text-brand-secondary"
|
||||
/>
|
||||
<span className="text-xs italic text-brand-secondary">
|
||||
No issues found. Please add issue.
|
||||
</span>
|
||||
|
@ -44,7 +44,8 @@ export const SingleModuleCard: React.FC<Props> = ({ module, handleEditModule })
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const completionPercentage = (module.completed_issues / module.total_issues) * 100;
|
||||
const completionPercentage =
|
||||
((module.completed_issues + module.cancelled_issues) / module.total_issues) * 100;
|
||||
|
||||
const handleDeleteModule = () => {
|
||||
if (!module) return;
|
||||
|
@ -162,7 +162,7 @@ export const SinglePageDetailedItem: React.FC<TSingleStatProps> = ({
|
||||
} on ${renderLongDateFormat(`${page.created_at}`)}`}
|
||||
>
|
||||
<span>
|
||||
<ExclamationIcon className="h-4 w-4 text-gray-400" />
|
||||
<ExclamationIcon className="h-4 w-4 fill-current text-brand-secondary" />
|
||||
</span>
|
||||
</Tooltip>
|
||||
<CustomMenu verticalEllipsis>
|
||||
|
@ -161,7 +161,7 @@ export const SinglePageListItem: React.FC<TSingleStatProps> = ({
|
||||
} on ${renderLongDateFormat(`${page.created_at}`)}`}
|
||||
>
|
||||
<span>
|
||||
<ExclamationIcon className="h-4 w-4 text-gray-400" />
|
||||
<ExclamationIcon className="h-4 w-4 fill-current text-brand-secondary" />
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
||||
|
@ -172,8 +172,8 @@ export const SingleSidebarProject: React.FC<Props> = ({
|
||||
<a
|
||||
className={`group flex items-center rounded-md p-2 text-xs font-medium outline-none ${
|
||||
router.asPath.includes(item.href)
|
||||
? "bg-brand-base text-brand-secondary"
|
||||
: "text-brand-secondary hover:bg-brand-surface-1 hover:text-brand-secondary focus:bg-brand-base focus:text-brand-secondary"
|
||||
? "bg-brand-surface-2 text-brand-base"
|
||||
: "text-brand-secondary hover:bg-brand-surface-2 hover:text-brand-secondary focus:bg-brand-surface-2 focus:text-brand-secondary"
|
||||
} ${sidebarCollapse ? "justify-center" : ""}`}
|
||||
>
|
||||
<div className="grid place-items-center">
|
||||
|
@ -47,8 +47,8 @@ export const WorkspaceSidebarMenu: React.FC = () => {
|
||||
? router.asPath === link.href
|
||||
: router.asPath.includes(link.href)
|
||||
)
|
||||
? "bg-brand-base text-brand-base"
|
||||
: "text-brand-secondary hover:bg-brand-surface-1 hover:text-brand-secondary focus:bg-brand-base focus:text-brand-secondary"
|
||||
? "bg-brand-surface-2 text-brand-base"
|
||||
: "text-brand-secondary hover:bg-brand-surface-2 hover:text-brand-secondary focus:bg-brand-surface-2 focus:text-brand-secondary"
|
||||
} group flex w-full items-center gap-3 rounded-md p-2 text-sm font-medium outline-none ${
|
||||
sidebarCollapse ? "justify-center" : ""
|
||||
}`}
|
||||
|
@ -52,7 +52,7 @@ const MyIssuesPage: NextPage = () => {
|
||||
<>
|
||||
<Popover.Button
|
||||
className={`group flex items-center gap-2 rounded-md border border-brand-base bg-transparent px-3 py-1.5 text-xs hover:bg-brand-surface-1 hover:text-brand-base focus:outline-none ${
|
||||
open ? "bg-brand-surface-1 text-brand-base" : "text-brand-muted-1"
|
||||
open ? "bg-brand-surface-1 text-brand-base" : "text-brand-secondary"
|
||||
}`}
|
||||
>
|
||||
<span>View</span>
|
||||
@ -69,9 +69,8 @@ const MyIssuesPage: NextPage = () => {
|
||||
leaveTo="opacity-0 translate-y-1"
|
||||
>
|
||||
<Popover.Panel className="absolute right-1/2 z-10 mr-5 mt-1 w-screen max-w-xs translate-x-1/2 transform overflow-hidden rounded-lg bg-brand-base p-3 shadow-lg">
|
||||
<div className="relative flex flex-col gap-1 gap-y-4">
|
||||
<div className="relative flex flex-col gap-1">
|
||||
<h4 className="text-base text-gray-600">Properties</h4>
|
||||
<div className="space-y-2 py-3">
|
||||
<h4 className="text-sm text-brand-secondary">Properties</h4>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{Object.keys(properties).map((key) => {
|
||||
if (key === "estimate") return null;
|
||||
@ -80,10 +79,10 @@ const MyIssuesPage: NextPage = () => {
|
||||
<button
|
||||
key={key}
|
||||
type="button"
|
||||
className={`rounded border border-theme px-2 py-1 text-xs capitalize ${
|
||||
className={`rounded border px-2 py-1 text-xs capitalize ${
|
||||
properties[key as keyof Properties]
|
||||
? "border-theme bg-theme text-white"
|
||||
: ""
|
||||
? "border-brand-accent bg-brand-accent text-white"
|
||||
: "border-brand-base"
|
||||
}`}
|
||||
onClick={() => setProperties(key as keyof Properties)}
|
||||
>
|
||||
@ -93,7 +92,6 @@ const MyIssuesPage: NextPage = () => {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Popover.Panel>
|
||||
</Transition>
|
||||
</>
|
||||
@ -107,7 +105,7 @@ const MyIssuesPage: NextPage = () => {
|
||||
document.dispatchEvent(e);
|
||||
}}
|
||||
>
|
||||
<PlusIcon className="w-4 h-4" />
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
Add Issue
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
|
@ -16,6 +16,7 @@ import { EmptySpace, EmptySpaceItem, Loader } from "components/ui";
|
||||
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
|
||||
// icons
|
||||
import { PlusIcon, PuzzlePieceIcon } from "@heroicons/react/24/outline";
|
||||
import { ExclamationIcon } from "components/icons";
|
||||
// types
|
||||
import { IProject } from "types";
|
||||
import type { NextPage } from "next";
|
||||
@ -56,7 +57,17 @@ const ProjectIntegrations: NextPage = () => {
|
||||
{workspaceIntegrations ? (
|
||||
workspaceIntegrations.length > 0 ? (
|
||||
<section className="space-y-8">
|
||||
<div className="flex flex-col items-start gap-3">
|
||||
<h3 className="text-2xl font-semibold">Integrations</h3>
|
||||
<div className="flex items-center gap-3 rounded-[10px] border border-brand-accent/75 bg-brand-accent/5 p-4 text-sm text-brand-base">
|
||||
<ExclamationIcon height={24} width={24} className="fill-current text-brand-base" />
|
||||
<p className="leading-5">
|
||||
Integrations and importers are only available on the cloud version. We plan to
|
||||
open-source our SDKs in the near future so that the community can request or
|
||||
contribute integrations as needed.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-5">
|
||||
{workspaceIntegrations.map((integration) => (
|
||||
<SingleIntegration
|
||||
|
@ -14,6 +14,8 @@ import { SingleIntegrationCard } from "components/integration";
|
||||
// ui
|
||||
import { Loader } from "components/ui";
|
||||
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
|
||||
// icons
|
||||
import { ExclamationIcon } from "components/icons";
|
||||
// types
|
||||
import type { NextPage } from "next";
|
||||
// fetch-keys
|
||||
@ -45,7 +47,17 @@ const WorkspaceIntegrations: NextPage = () => {
|
||||
}
|
||||
>
|
||||
<section className="space-y-8">
|
||||
<div className="flex flex-col items-start gap-3">
|
||||
<h3 className="text-2xl font-semibold">Integrations</h3>
|
||||
<div className="flex items-center gap-3 rounded-[10px] border border-brand-accent/75 bg-brand-accent/5 p-4 text-sm text-brand-base">
|
||||
<ExclamationIcon height={24} width={24} className="fill-current text-brand-base" />
|
||||
<p className="leading-5">
|
||||
Integrations and importers are only available on the cloud version. We plan to
|
||||
open-source our SDKs in the near future so that the community can request or
|
||||
contribute integrations as needed.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-5">
|
||||
{appIntegrations ? (
|
||||
appIntegrations.map((integration) => (
|
||||
|
@ -8,6 +8,7 @@ import "styles/globals.css";
|
||||
import "styles/editor.css";
|
||||
import "styles/command-pallette.css";
|
||||
import "styles/nprogress.css";
|
||||
import "styles/react-datepicker.css";
|
||||
|
||||
// router
|
||||
import Router from "next/router";
|
||||
|
118
apps/app/styles/react-datepicker.css
Normal file
118
apps/app/styles/react-datepicker.css
Normal file
@ -0,0 +1,118 @@
|
||||
.react-datepicker-wrapper input::placeholder {
|
||||
color: rgba(var(--color-text-secondary));
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.react-datepicker-wrapper input:-ms-input-placeholder {
|
||||
color: rgba(var(--color-text-secondary));
|
||||
}
|
||||
|
||||
.react-datepicker-wrapper .react-datepicker__close-icon::after {
|
||||
background: transparent;
|
||||
color: rgba(var(--color-text-secondary));
|
||||
}
|
||||
|
||||
.react-datepicker-popper {
|
||||
z-index: 30 !important;
|
||||
}
|
||||
|
||||
.react-datepicker-wrapper {
|
||||
position: relative;
|
||||
background-color: rgba(var(--color-bg-base)) !important;
|
||||
}
|
||||
|
||||
.react-datepicker {
|
||||
font-family: "Inter" !important;
|
||||
border: none !important;
|
||||
background-color: rgba(var(--color-bg-base)) !important;
|
||||
}
|
||||
|
||||
.react-datepicker__month-container {
|
||||
width: 300px;
|
||||
background-color: rgba(var(--color-bg-base)) !important;
|
||||
color: rgba(var(--color-text-base)) !important;
|
||||
border-radius: 10px !important;
|
||||
/* border: 1px solid rgba(var(--color-border)) !important; */
|
||||
}
|
||||
|
||||
.react-datepicker__header {
|
||||
border-radius: 10px !important;
|
||||
background-color: rgba(var(--color-bg-base)) !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.react-datepicker__navigation {
|
||||
line-height: 0.78;
|
||||
}
|
||||
|
||||
.react-datepicker__triangle {
|
||||
border-color: rgba(var(--color-bg-base)) transparent transparent transparent !important;
|
||||
}
|
||||
|
||||
.react-datepicker__triangle:before {
|
||||
border-bottom-color: rgba(var(--color-border)) !important;
|
||||
}
|
||||
.react-datepicker__triangle:after {
|
||||
border-bottom-color: rgba(var(--color-bg-base)) !important;
|
||||
}
|
||||
|
||||
.react-datepicker__current-month {
|
||||
font-weight: 500 !important;
|
||||
color: rgba(var(--color-text-base)) !important;
|
||||
}
|
||||
|
||||
.react-datepicker__month {
|
||||
border-collapse: collapse;
|
||||
color: rgba(var(--color-text-base)) !important;
|
||||
}
|
||||
|
||||
.react-datepicker__day-names {
|
||||
margin-top: 10px;
|
||||
margin-left: 14px;
|
||||
width: 280px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.react-datepicker__day-name {
|
||||
color: rgba(var(--color-text-base)) !important;
|
||||
}
|
||||
|
||||
.react-datepicker__week {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.react-datepicker__day {
|
||||
color: rgba(var(--color-text-base)) !important;
|
||||
}
|
||||
|
||||
.react-datepicker__day {
|
||||
border-radius: 50% !important;
|
||||
transition: all 0.15s ease-in-out;
|
||||
}
|
||||
|
||||
.react-datepicker__day:hover {
|
||||
background-color: rgba(var(--color-bg-surface-2)) !important;
|
||||
color: rgba(var(--color-text-base)) !important;
|
||||
}
|
||||
|
||||
.react-datepicker__day--selected {
|
||||
background-color: #216ba5 !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.react-datepicker__day--today {
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.react-datepicker__day--highlighted {
|
||||
background-color: rgba(var(--color-bg-surface-2)) !important;
|
||||
}
|
||||
|
||||
.react-datepicker__day--keyboard-selected {
|
||||
background-color: #216ba5 !important;
|
||||
color: white !important;
|
||||
}
|
Loading…
Reference in New Issue
Block a user