от src избавился
This commit is contained in:
@@ -25,7 +25,7 @@ jobs:
|
|||||||
run: dotnet restore backend/Tnsu.ApprovalRoute.sln
|
run: dotnet restore backend/Tnsu.ApprovalRoute.sln
|
||||||
|
|
||||||
- name: Publish (local)
|
- name: Publish (local)
|
||||||
run: dotnet publish backend/src/Tnsu.ApprovalRoute.Api/Tnsu.ApprovalRoute.Api.csproj -c Release -o "$LOCAL_PUBLISH"
|
run: dotnet publish backend/Tnsu.ApprovalRoute.Api/Tnsu.ApprovalRoute.Api.csproj -c Release -o "$LOCAL_PUBLISH"
|
||||||
|
|
||||||
- name: Install cifs-utils
|
- name: Install cifs-utils
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -22,11 +22,10 @@ backend/
|
|||||||
Directory.Build.props # общие настройки таргета (net10.0, nullable, etc.)
|
Directory.Build.props # общие настройки таргета (net10.0, nullable, etc.)
|
||||||
Directory.Packages.props # централизованные версии пакетов
|
Directory.Packages.props # централизованные версии пакетов
|
||||||
Tnsu.ApprovalRoute.sln
|
Tnsu.ApprovalRoute.sln
|
||||||
src/
|
Tnsu.ApprovalRoute.Domain/ # сущности и enum'ы домена
|
||||||
Tnsu.ApprovalRoute.Domain/ # сущности и enum'ы домена
|
Tnsu.ApprovalRoute.Application/ # сервисы, DTO, валидаторы
|
||||||
Tnsu.ApprovalRoute.Application/ # сервисы, DTO, валидаторы
|
Tnsu.ApprovalRoute.Infrastructure/ # EF Core DbContext, миграции, клиент tnsu-portal
|
||||||
Tnsu.ApprovalRoute.Infrastructure/ # EF Core DbContext, миграции, клиент tnsu-portal
|
Tnsu.ApprovalRoute.Api/ # ASP.NET Core Controllers, Program.cs, авторизация
|
||||||
Tnsu.ApprovalRoute.Api/ # ASP.NET Core Controllers, Program.cs, авторизация
|
|
||||||
tests/
|
tests/
|
||||||
Tnsu.ApprovalRoute.IntegrationTests/
|
Tnsu.ApprovalRoute.IntegrationTests/
|
||||||
frontend/
|
frontend/
|
||||||
@@ -61,7 +60,7 @@ npm run build # heft test + package-solution --production
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd backend
|
cd backend
|
||||||
dotnet run --project src/Tnsu.ApprovalRoute.Api
|
dotnet run --project Tnsu.ApprovalRoute.Api
|
||||||
```
|
```
|
||||||
|
|
||||||
Требуется PostgreSQL (строка подключения — `ConnectionStrings:Postgres` в `appsettings.json`).
|
Требуется PostgreSQL (строка подключения — `ConnectionStrings:Postgres` в `appsettings.json`).
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
COPY Directory.Build.props Directory.Packages.props ./
|
||||||
|
COPY Tnsu.ApprovalRoute.Domain/Tnsu.ApprovalRoute.Domain.csproj Tnsu.ApprovalRoute.Domain/
|
||||||
|
COPY Tnsu.ApprovalRoute.Application/Tnsu.ApprovalRoute.Application.csproj Tnsu.ApprovalRoute.Application/
|
||||||
|
COPY Tnsu.ApprovalRoute.Infrastructure/Tnsu.ApprovalRoute.Infrastructure.csproj Tnsu.ApprovalRoute.Infrastructure/
|
||||||
|
COPY Tnsu.ApprovalRoute.Api/Tnsu.ApprovalRoute.Api.csproj Tnsu.ApprovalRoute.Api/
|
||||||
|
RUN dotnet restore Tnsu.ApprovalRoute.Api/Tnsu.ApprovalRoute.Api.csproj
|
||||||
|
COPY Tnsu.ApprovalRoute.Domain/ Tnsu.ApprovalRoute.Domain/
|
||||||
|
COPY Tnsu.ApprovalRoute.Application/ Tnsu.ApprovalRoute.Application/
|
||||||
|
COPY Tnsu.ApprovalRoute.Infrastructure/ Tnsu.ApprovalRoute.Infrastructure/
|
||||||
|
COPY Tnsu.ApprovalRoute.Api/ Tnsu.ApprovalRoute.Api/
|
||||||
|
RUN dotnet publish Tnsu.ApprovalRoute.Api/Tnsu.ApprovalRoute.Api.csproj -c Release -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final
|
||||||
|
WORKDIR /app
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*
|
||||||
|
COPY --from=build /app/publish .
|
||||||
|
ENV ASPNETCORE_URLS=http://+:8080
|
||||||
|
EXPOSE 8080
|
||||||
|
ENTRYPOINT ["dotnet", "Tnsu.ApprovalRoute.Api.dll"]
|
||||||
@@ -3,15 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.0.31903.59
|
VisualStudioVersion = 17.0.31903.59
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tnsu.ApprovalRoute.Domain", "Tnsu.ApprovalRoute.Domain\Tnsu.ApprovalRoute.Domain.csproj", "{67C6FECB-26BF-4A7E-AC40-574F4D88EEAC}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tnsu.ApprovalRoute.Domain", "src\Tnsu.ApprovalRoute.Domain\Tnsu.ApprovalRoute.Domain.csproj", "{67C6FECB-26BF-4A7E-AC40-574F4D88EEAC}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tnsu.ApprovalRoute.Application", "Tnsu.ApprovalRoute.Application\Tnsu.ApprovalRoute.Application.csproj", "{2EEA333B-16C7-460E-BD07-AB1F32D6A9A9}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tnsu.ApprovalRoute.Application", "src\Tnsu.ApprovalRoute.Application\Tnsu.ApprovalRoute.Application.csproj", "{2EEA333B-16C7-460E-BD07-AB1F32D6A9A9}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tnsu.ApprovalRoute.Infrastructure", "Tnsu.ApprovalRoute.Infrastructure\Tnsu.ApprovalRoute.Infrastructure.csproj", "{46EF4247-8B98-4CC9-A981-186C8D24163C}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tnsu.ApprovalRoute.Infrastructure", "src\Tnsu.ApprovalRoute.Infrastructure\Tnsu.ApprovalRoute.Infrastructure.csproj", "{46EF4247-8B98-4CC9-A981-186C8D24163C}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tnsu.ApprovalRoute.Api", "Tnsu.ApprovalRoute.Api\Tnsu.ApprovalRoute.Api.csproj", "{4697B342-BE47-435B-B854-75F9277AD769}"
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tnsu.ApprovalRoute.Api", "src\Tnsu.ApprovalRoute.Api\Tnsu.ApprovalRoute.Api.csproj", "{4697B342-BE47-435B-B854-75F9277AD769}"
|
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}"
|
||||||
EndProject
|
EndProject
|
||||||
@@ -92,10 +90,6 @@ Global
|
|||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{67C6FECB-26BF-4A7E-AC40-574F4D88EEAC} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
|
||||||
{2EEA333B-16C7-460E-BD07-AB1F32D6A9A9} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
|
||||||
{46EF4247-8B98-4CC9-A981-186C8D24163C} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
|
||||||
{4697B342-BE47-435B-B854-75F9277AD769} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
|
||||||
{F5E2BA0E-7978-414C-98D4-D3C91C162FDE} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
{F5E2BA0E-7978-414C-98D4-D3C91C162FDE} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"ExpandedNodes": [
|
|
||||||
"",
|
|
||||||
"\\Tnsu.ApprovalRoute.Api",
|
|
||||||
"\\Tnsu.ApprovalRoute.Application"
|
|
||||||
],
|
|
||||||
"SelectedNode": "\\Tnsu.ApprovalRoute.Application",
|
|
||||||
"PreviewInSolutionExplorer": false
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -1,37 +0,0 @@
|
|||||||
{
|
|
||||||
"Version": 1,
|
|
||||||
"WorkspaceRootPath": "C:\\Users\\trishina.mariya\\Documents\\Projects\\tnsu-approval-route\\backend\\src\\",
|
|
||||||
"Documents": [
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\trishina.mariya\\Documents\\Projects\\tnsu-approval-route\\backend\\src\\Tnsu.ApprovalRoute.Api\\appsettings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}",
|
|
||||||
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:Tnsu.ApprovalRoute.Api\\appsettings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"DocumentGroupContainers": [
|
|
||||||
{
|
|
||||||
"Orientation": 0,
|
|
||||||
"VerticalTabListWidth": 256,
|
|
||||||
"DocumentGroups": [
|
|
||||||
{
|
|
||||||
"DockedWidth": 200,
|
|
||||||
"SelectedChildIndex": 0,
|
|
||||||
"Children": [
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 0,
|
|
||||||
"Title": "appsettings.json",
|
|
||||||
"DocumentMoniker": "C:\\Users\\trishina.mariya\\Documents\\Projects\\tnsu-approval-route\\backend\\src\\Tnsu.ApprovalRoute.Api\\appsettings.json",
|
|
||||||
"RelativeDocumentMoniker": "Tnsu.ApprovalRoute.Api\\appsettings.json",
|
|
||||||
"ToolTip": "C:\\Users\\trishina.mariya\\Documents\\Projects\\tnsu-approval-route\\backend\\src\\Tnsu.ApprovalRoute.Api\\appsettings.json",
|
|
||||||
"RelativeToolTip": "Tnsu.ApprovalRoute.Api\\appsettings.json",
|
|
||||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAABUAAAAXAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
|
|
||||||
"WhenOpened": "2026-07-28T05:52:49.686Z",
|
|
||||||
"EditorCaption": ""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
{
|
|
||||||
"Version": 1,
|
|
||||||
"WorkspaceRootPath": "C:\\Users\\trishina.mariya\\Documents\\Projects\\tnsu-approval-route\\backend\\src\\",
|
|
||||||
"Documents": [
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\trishina.mariya\\Documents\\Projects\\tnsu-approval-route\\backend\\src\\Tnsu.ApprovalRoute.Api\\appsettings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}",
|
|
||||||
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:Tnsu.ApprovalRoute.Api\\appsettings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"DocumentGroupContainers": [
|
|
||||||
{
|
|
||||||
"Orientation": 0,
|
|
||||||
"VerticalTabListWidth": 256,
|
|
||||||
"DocumentGroups": [
|
|
||||||
{
|
|
||||||
"DockedWidth": 200,
|
|
||||||
"SelectedChildIndex": 0,
|
|
||||||
"Children": [
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 0,
|
|
||||||
"Title": "appsettings.json",
|
|
||||||
"DocumentMoniker": "C:\\Users\\trishina.mariya\\Documents\\Projects\\tnsu-approval-route\\backend\\src\\Tnsu.ApprovalRoute.Api\\appsettings.json",
|
|
||||||
"RelativeDocumentMoniker": "Tnsu.ApprovalRoute.Api\\appsettings.json",
|
|
||||||
"ToolTip": "C:\\Users\\trishina.mariya\\Documents\\Projects\\tnsu-approval-route\\backend\\src\\Tnsu.ApprovalRoute.Api\\appsettings.json",
|
|
||||||
"RelativeToolTip": "Tnsu.ApprovalRoute.Api\\appsettings.json",
|
|
||||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAABUAAAAXAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
|
|
||||||
"WhenOpened": "2026-07-28T05:52:49.686Z",
|
|
||||||
"EditorCaption": ""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
|
||||||
WORKDIR /src
|
|
||||||
COPY Directory.Build.props Directory.Packages.props ./
|
|
||||||
COPY src/Tnsu.ApprovalRoute.Domain/Tnsu.ApprovalRoute.Domain.csproj src/Tnsu.ApprovalRoute.Domain/
|
|
||||||
COPY src/Tnsu.ApprovalRoute.Application/Tnsu.ApprovalRoute.Application.csproj src/Tnsu.ApprovalRoute.Application/
|
|
||||||
COPY src/Tnsu.ApprovalRoute.Infrastructure/Tnsu.ApprovalRoute.Infrastructure.csproj src/Tnsu.ApprovalRoute.Infrastructure/
|
|
||||||
COPY src/Tnsu.ApprovalRoute.Api/Tnsu.ApprovalRoute.Api.csproj src/Tnsu.ApprovalRoute.Api/
|
|
||||||
RUN dotnet restore src/Tnsu.ApprovalRoute.Api/Tnsu.ApprovalRoute.Api.csproj
|
|
||||||
COPY src/ src/
|
|
||||||
RUN dotnet publish src/Tnsu.ApprovalRoute.Api/Tnsu.ApprovalRoute.Api.csproj -c Release -o /app/publish /p:UseAppHost=false
|
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final
|
|
||||||
WORKDIR /app
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*
|
|
||||||
COPY --from=build /app/publish .
|
|
||||||
ENV ASPNETCORE_URLS=http://+:8080
|
|
||||||
EXPOSE 8080
|
|
||||||
ENTRYPOINT ["dotnet", "Tnsu.ApprovalRoute.Api.dll"]
|
|
||||||
+2
-2
@@ -5,8 +5,8 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\src\Tnsu.ApprovalRoute.Infrastructure\Tnsu.ApprovalRoute.Infrastructure.csproj" />
|
<ProjectReference Include="..\..\Tnsu.ApprovalRoute.Infrastructure\Tnsu.ApprovalRoute.Infrastructure.csproj" />
|
||||||
<ProjectReference Include="..\..\src\Tnsu.ApprovalRoute.Application\Tnsu.ApprovalRoute.Application.csproj" />
|
<ProjectReference Include="..\..\Tnsu.ApprovalRoute.Application\Tnsu.ApprovalRoute.Application.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ services:
|
|||||||
api:
|
api:
|
||||||
build:
|
build:
|
||||||
context: ./backend
|
context: ./backend
|
||||||
dockerfile: src/Tnsu.ApprovalRoute.Api/Dockerfile
|
dockerfile: Tnsu.ApprovalRoute.Api/Dockerfile
|
||||||
container_name: tnsu-approval-route-api
|
container_name: tnsu-approval-route-api
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|||||||
@@ -62,6 +62,12 @@ export function AsyncSearchableSelect<T>({
|
|||||||
// Растущий счётчик запросов: если ответ пришёл не от последнего запроса
|
// Растущий счётчик запросов: если ответ пришёл не от последнего запроса
|
||||||
// (например, пользователь допечатал ещё символ) — просто игнорируем его.
|
// (например, пользователь допечатал ещё символ) — просто игнорируем его.
|
||||||
const requestIdRef = React.useRef(0);
|
const requestIdRef = React.useRef(0);
|
||||||
|
// getValue нужен внутри runSearch (дедуп при доклейке страницы), но в deps его
|
||||||
|
// класть нельзя: пропс приходит инлайновой стрелкой и меняет ссылку на каждом
|
||||||
|
// рендере — runSearch пересоздавался бы постоянно и перезапускал эффект
|
||||||
|
// бесконечной прокрутки. Держим последнюю версию в ref.
|
||||||
|
const getValueRef = React.useRef(getValue);
|
||||||
|
getValueRef.current = getValue;
|
||||||
|
|
||||||
const runSearch = React.useCallback((q: string, targetPage: number, append: boolean) => {
|
const runSearch = React.useCallback((q: string, targetPage: number, append: boolean) => {
|
||||||
const requestId = ++requestIdRef.current;
|
const requestId = ++requestIdRef.current;
|
||||||
@@ -71,7 +77,16 @@ export function AsyncSearchableSelect<T>({
|
|||||||
search(q, targetPage)
|
search(q, targetPage)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
if (requestIdRef.current !== requestId) return; // устарел
|
if (requestIdRef.current !== requestId) return; // устарел
|
||||||
setItems(prev => (append ? [...prev, ...result.items] : result.items));
|
// Дедуп при доклейке: соседние страницы могут пересекаться, если индекс
|
||||||
|
// переупорядочился между запросами (StartRow смещает окно по РАНГУ, а не
|
||||||
|
// по устойчивому курсору). Дубликат здесь = два пункта с одинаковым
|
||||||
|
// React-ключом, то есть заявка в списке дважды. Внутри одной страницы
|
||||||
|
// дубли отсекает уже источник (см. searchRequests в requestManageService).
|
||||||
|
setItems(prev => {
|
||||||
|
if (!append) return result.items;
|
||||||
|
const shown = new Set(prev.map(i => getValueRef.current(i)));
|
||||||
|
return [...prev, ...result.items.filter(i => !shown.has(getValueRef.current(i)))];
|
||||||
|
});
|
||||||
setHasMore(result.hasMore);
|
setHasMore(result.hasMore);
|
||||||
setPage(targetPage);
|
setPage(targetPage);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
} from '../models';
|
} from '../models';
|
||||||
|
|
||||||
// Тонкий 1:1 фасад над контроллерами бэкенда:
|
// Тонкий 1:1 фасад над контроллерами бэкенда:
|
||||||
// backend/src/Tnsu.ApprovalRoute.Api/Controllers/{RequestTypes,TemplateRoutes,TemplateRouteSteps}Controller.cs
|
// backend/Tnsu.ApprovalRoute.Api/Controllers/{RequestTypes,TemplateRoutes,TemplateRouteSteps}Controller.cs
|
||||||
|
|
||||||
export class ApprovalRouteApi {
|
export class ApprovalRouteApi {
|
||||||
constructor(private readonly http: IHttpClient) {}
|
constructor(private readonly http: IHttpClient) {}
|
||||||
|
|||||||
@@ -152,7 +152,22 @@ export class RequestManageService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const rawRows = (result.PrimarySearchResults ?? []) as Array<{ ListItemID?: string }>;
|
const rawRows = (result.PrimarySearchResults ?? []) as Array<{ ListItemID?: string }>;
|
||||||
const ids = rawRows.map(r => Number(r.ListItemID)).filter(id => !isNaN(id) && id > 0);
|
// Дедуп по Id обязателен: TrimDuplicates: false выше выключает штатную
|
||||||
|
// дедупликацию Search (она иногда схлопывает нужные нам заявки), и тогда
|
||||||
|
// индекс может отдать один и тот же элемент несколькими хитами
|
||||||
|
// (переиндексация, несколько «версий» в crawl). Без этого фильтра хиты
|
||||||
|
// превращались в пункты комбобокса один-в-один, и заявка показывалась в
|
||||||
|
// списке дважды — с одинаковым React-ключом. Та же причина и то же лечение,
|
||||||
|
// что в request-portal (features/myRequests/myRequests.service.ts/hitsToEntries).
|
||||||
|
const seen = new Set<number>();
|
||||||
|
const ids = rawRows
|
||||||
|
.map(r => Number(r.ListItemID))
|
||||||
|
.filter(id => !isNaN(id) && id > 0)
|
||||||
|
.filter(id => {
|
||||||
|
if (seen.has(id)) return false;
|
||||||
|
seen.add(id);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
if (ids.length === 0) return { items: [], hasMore: false };
|
if (ids.length === 0) return { items: [], hasMore: false };
|
||||||
|
|
||||||
const list = sp.web.getList(requestType.listId);
|
const list = sp.web.getList(requestType.listId);
|
||||||
|
|||||||
Reference in New Issue
Block a user