ФУНКЦИИ - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: интерактивные карточки и фильтры двусторонней доски внешних контуров

This commit is contained in:
DCCONSTRUCTIONS
2026-04-20 22:57:18 +03:00
parent 6a3adcd245
commit d3b4c0689c
16 changed files with 754 additions and 224 deletions
@@ -303,9 +303,12 @@ export default {
},
filters: {
sort: "Sorting",
contour: "Contour",
requester: "Requester",
unread_only: "Only with updates",
search_placeholder: "Search by request title",
search_contour: "Search by contour",
search_state: "Search by state",
search_priority: "Search by priority",
search_assignee: "Search by assignee",
search_requester: "Search by requester",
@@ -460,9 +460,12 @@ export default {
},
filters: {
sort: "Сортировка",
contour: "Контур",
requester: "Отправитель",
unread_only: "Только с изменениями",
search_placeholder: "Поиск по названию запроса",
search_contour: "Поиск по контуру",
search_state: "Поиск по статусу",
search_priority: "Поиск по приоритету",
search_assignee: "Поиск по исполнителю",
search_requester: "Поиск по отправителю",
@@ -110,6 +110,7 @@ export type TExternalContourBoardFilter = {
assignee_ids?: string[];
created_by_ids?: string[];
requested_by_ids?: string[];
counterparty_project_ids?: string[];
source_project_ids?: string[];
target_project_ids?: string[];
label_ids?: string[];
@@ -143,5 +144,6 @@ export type TExternalContourTargetProject = IProjectLite & {
export type TExternalContourTargetOptions = {
project: TExternalContourTargetProject;
member_ids: string[];
states: Pick<IStateLite, "id" | "name" | "color" | "group">[];
labels: Pick<IIssueLabel, "id" | "name" | "color" | "parent" | "project_id" | "workspace_id" | "sort_order">[];
};
@@ -44,7 +44,7 @@ export function InputSearch(props: IInputSearch) {
return (
<div
className={cn(
"flex items-center gap-1.5 rounded-sm border border-subtle bg-surface-2 px-2",
"nodedc-dropdown-search",
inputContainerClassName
)}
>
@@ -53,7 +53,7 @@ export function InputSearch(props: IInputSearch) {
as="input"
ref={inputRef}
className={cn(
"w-full bg-transparent py-1 text-11 text-secondary placeholder:text-placeholder focus:outline-none",
"w-full bg-transparent py-0 text-12 text-secondary placeholder:text-placeholder focus:outline-none",
inputClassName
)}
value={query}
@@ -46,7 +46,7 @@ export function DropdownOptions(props: IMultiSelectDropdownOptions | ISingleSele
isMobile={isMobile}
/>
)}
<div className={cn("max-h-48 space-y-1 overflow-y-scroll", !disableSearch && "mt-2")}>
<div className={cn("max-h-56 space-y-1 overflow-y-auto", !disableSearch && "mt-2")}>
<>
{options ? (
options.length > 0 ? (
@@ -57,9 +57,9 @@ export function DropdownOptions(props: IMultiSelectDropdownOptions | ISingleSele
disabled={option.disabled}
className={({ active, selected }) =>
cn(
"flex w-full cursor-pointer items-center justify-between gap-2 truncate rounded-sm px-1 py-1.5 select-none",
"nodedc-dropdown-option",
{
"bg-layer-1": active,
"bg-white/6": active,
"text-primary": selected,
"text-secondary": !selected,
},
@@ -7,6 +7,7 @@
import { Combobox } from "@headlessui/react";
import { sortBy } from "lodash-es";
import React, { useMemo, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { usePopper } from "react-popper";
// plane imports
import { useOutsideClickDetector } from "@plane/hooks";
@@ -139,35 +140,34 @@ export function MultiSelectDropdown(props: IMultiSelectDropdown) {
disabled={disabled}
/>
{isOpen && (
<Combobox.Options className="fixed z-10" static>
<div
className={cn(
"my-1 w-48 rounded-sm border-[0.5px] border-strong bg-surface-1 px-2 py-2.5 text-11 shadow-raised-200 focus:outline-none",
optionsContainerClassName
)}
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
>
<DropdownOptions
isOpen={isOpen}
query={query}
setQuery={setQuery}
inputIcon={inputIcon}
inputPlaceholder={inputPlaceholder}
inputClassName={inputClassName}
inputContainerClassName={inputContainerClassName}
disableSearch={disableSearch}
keyExtractor={keyExtractor}
options={sortedOptions}
value={value}
renderItem={renderItem}
loader={loader}
/>
</div>
</Combobox.Options>
)}
{isOpen &&
createPortal(
<Combobox.Options data-prevent-outside-click className="fixed z-30" static>
<div
className={cn("nodedc-dropdown-surface my-1 w-56", optionsContainerClassName)}
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
>
<DropdownOptions
isOpen={isOpen}
query={query}
setQuery={setQuery}
inputIcon={inputIcon}
inputPlaceholder={inputPlaceholder}
inputClassName={inputClassName}
inputContainerClassName={inputContainerClassName}
disableSearch={disableSearch}
keyExtractor={keyExtractor}
options={sortedOptions}
value={value}
renderItem={renderItem}
loader={loader}
/>
</div>
</Combobox.Options>,
document.body
)}
</Combobox>
);
}
@@ -7,6 +7,7 @@
import { Combobox } from "@headlessui/react";
import { sortBy } from "lodash-es";
import React, { useMemo, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { usePopper } from "react-popper";
// plane imports
import { useOutsideClickDetector } from "@plane/hooks";
@@ -138,36 +139,35 @@ export function Dropdown(props: ISingleSelectDropdown) {
disabled={disabled}
/>
{isOpen && (
<Combobox.Options className="fixed z-10" static>
<div
className={cn(
"my-1 w-48 rounded-sm border-[0.5px] border-strong bg-surface-1 px-2 py-2 text-11 shadow-raised-200 focus:outline-none",
optionsContainerClassName
)}
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
>
<DropdownOptions
isOpen={isOpen}
query={query}
setQuery={setQuery}
inputIcon={inputIcon}
inputPlaceholder={inputPlaceholder}
inputClassName={inputClassName}
inputContainerClassName={inputContainerClassName}
disableSearch={disableSearch}
keyExtractor={keyExtractor}
options={sortedOptions}
value={value}
renderItem={renderItem}
loader={loader}
handleClose={handleClose}
/>
</div>
</Combobox.Options>
)}
{isOpen &&
createPortal(
<Combobox.Options data-prevent-outside-click className="fixed z-30" static>
<div
className={cn("nodedc-dropdown-surface my-1 w-56", optionsContainerClassName)}
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
>
<DropdownOptions
isOpen={isOpen}
query={query}
setQuery={setQuery}
inputIcon={inputIcon}
inputPlaceholder={inputPlaceholder}
inputClassName={inputClassName}
inputContainerClassName={inputContainerClassName}
disableSearch={disableSearch}
keyExtractor={keyExtractor}
options={sortedOptions}
value={value}
renderItem={renderItem}
loader={loader}
handleClose={handleClose}
/>
</div>
</Combobox.Options>,
document.body
)}
</Combobox>
);
}