ФУНКЦИИ - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: интерактивные карточки и фильтры двусторонней доски внешних контуров
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
import type { ReactNode } from "react";
|
||||
import { useRef, useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { usePopper } from "react-popper";
|
||||
import { Combobox } from "@headlessui/react";
|
||||
// plane imports
|
||||
@@ -211,60 +212,62 @@ export const WorkItemStateDropdownBase = observer(function WorkItemStateDropdown
|
||||
button={comboButton}
|
||||
renderByDefault={renderByDefault}
|
||||
>
|
||||
{isOpen && (
|
||||
<Combobox.Options className="fixed z-10" static>
|
||||
<div
|
||||
className="nodedc-glass-modal nodedc-glass-popup-surface my-1 w-52 rounded-[1.25rem] border-0 px-3 py-3 text-12 shadow-none outline-none"
|
||||
ref={setPopperElement}
|
||||
style={styles.popper}
|
||||
{...attributes.popper}
|
||||
>
|
||||
<div className="flex items-center gap-1.5 rounded-[0.95rem] border-0 bg-white/5 px-3 py-2 outline-none">
|
||||
<SearchIcon className="h-3.5 w-3.5 text-placeholder" strokeWidth={1.5} />
|
||||
<Combobox.Input
|
||||
as="input"
|
||||
ref={inputRef}
|
||||
className="w-full bg-transparent py-0 text-12 text-secondary placeholder:text-placeholder outline-none focus:outline-none"
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
placeholder={t("common.search.label")}
|
||||
displayValue={(assigned: any) => assigned?.name}
|
||||
onKeyDown={searchInputKeyDown}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-2 max-h-56 space-y-1 overflow-y-auto">
|
||||
{filteredOptions ? (
|
||||
filteredOptions.length > 0 ? (
|
||||
filteredOptions.map((option) => (
|
||||
<Combobox.Option
|
||||
key={option.value}
|
||||
value={option.value}
|
||||
className={({ active, selected }) =>
|
||||
cn(
|
||||
`flex w-full cursor-pointer items-center justify-between gap-2 truncate rounded-[0.9rem] px-2 py-2 select-none outline-none ${
|
||||
active ? "bg-white/6" : ""
|
||||
} ${selected ? "text-primary" : "text-secondary"}`
|
||||
)
|
||||
}
|
||||
>
|
||||
{({ selected }) => (
|
||||
<>
|
||||
<span className="flex-grow truncate">{option.content}</span>
|
||||
{selected && <CheckIcon className="h-3.5 w-3.5 flex-shrink-0" />}
|
||||
</>
|
||||
)}
|
||||
</Combobox.Option>
|
||||
))
|
||||
{isOpen &&
|
||||
createPortal(
|
||||
<Combobox.Options data-prevent-outside-click className="fixed z-30" static>
|
||||
<div
|
||||
className="nodedc-glass-modal nodedc-glass-popup-surface my-1 w-52 rounded-[1.25rem] border-0 px-3 py-3 text-12 shadow-none outline-none"
|
||||
ref={setPopperElement}
|
||||
style={styles.popper}
|
||||
{...attributes.popper}
|
||||
>
|
||||
<div className="flex items-center gap-1.5 rounded-[0.95rem] border-0 bg-white/5 px-3 py-2 outline-none">
|
||||
<SearchIcon className="h-3.5 w-3.5 text-placeholder" strokeWidth={1.5} />
|
||||
<Combobox.Input
|
||||
as="input"
|
||||
ref={inputRef}
|
||||
className="w-full bg-transparent py-0 text-12 text-secondary placeholder:text-placeholder outline-none focus:outline-none"
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
placeholder={t("common.search.label")}
|
||||
displayValue={(assigned: any) => assigned?.name}
|
||||
onKeyDown={searchInputKeyDown}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-2 max-h-56 space-y-1 overflow-y-auto">
|
||||
{filteredOptions ? (
|
||||
filteredOptions.length > 0 ? (
|
||||
filteredOptions.map((option) => (
|
||||
<Combobox.Option
|
||||
key={option.value}
|
||||
value={option.value}
|
||||
className={({ active, selected }) =>
|
||||
cn(
|
||||
`flex w-full cursor-pointer items-center justify-between gap-2 truncate rounded-[0.9rem] px-2 py-2 select-none outline-none ${
|
||||
active ? "bg-white/6" : ""
|
||||
} ${selected ? "text-primary" : "text-secondary"}`
|
||||
)
|
||||
}
|
||||
>
|
||||
{({ selected }) => (
|
||||
<>
|
||||
<span className="flex-grow truncate">{option.content}</span>
|
||||
{selected && <CheckIcon className="h-3.5 w-3.5 flex-shrink-0" />}
|
||||
</>
|
||||
)}
|
||||
</Combobox.Option>
|
||||
))
|
||||
) : (
|
||||
<p className="px-1.5 py-1 text-placeholder italic">{t("no_matching_results")}</p>
|
||||
)
|
||||
) : (
|
||||
<p className="px-1.5 py-1 text-placeholder italic">{t("no_matching_results")}</p>
|
||||
)
|
||||
) : (
|
||||
<p className="px-1.5 py-1 text-placeholder italic">{t("loading")}</p>
|
||||
)}
|
||||
<p className="px-1.5 py-1 text-placeholder italic">{t("loading")}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Combobox.Options>
|
||||
)}
|
||||
</Combobox.Options>,
|
||||
document.body
|
||||
)}
|
||||
</ComboDropDown>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -71,7 +71,7 @@ export class ExternalContourService extends APIService {
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
requestId: string,
|
||||
data: Pick<Partial<TIssue>, "name" | "description_html">
|
||||
data: Pick<Partial<TIssue>, "name" | "description_html" | "priority" | "target_date" | "assignee_ids" | "label_ids" | "state_id">
|
||||
): Promise<TExternalContourRequest> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/external-contours/${requestId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
|
||||
@@ -38,7 +38,7 @@ export interface IProjectExternalContoursStore {
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
requestId: string,
|
||||
data: Pick<Partial<TIssue>, "name" | "description_html">
|
||||
data: Pick<Partial<TIssue>, "name" | "description_html" | "priority" | "target_date" | "assignee_ids" | "label_ids" | "state_id">
|
||||
) => Promise<TExternalContourRequest | undefined>;
|
||||
decideRequest: (
|
||||
workspaceSlug: string,
|
||||
@@ -251,7 +251,7 @@ export class ProjectExternalContoursStore implements IProjectExternalContoursSto
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
requestId: string,
|
||||
data: Pick<Partial<TIssue>, "name" | "description_html">
|
||||
data: Pick<Partial<TIssue>, "name" | "description_html" | "priority" | "target_date" | "assignee_ids" | "label_ids" | "state_id">
|
||||
) => {
|
||||
this.loader = "mutation-loading";
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user