fix: папка файлов чата называется по RequestUniqueCode, а не formKey-id
Раньше папка в библиотеке «Файлы чата» называлась «clearance-form-42» — это техническое имя ничего не говорит без открытого портала. Теперь имя папки — тот же код заявки, что показан в её заголовке («13-2608-42»), поэтому папку легко узнать прямо в библиотеке.
This commit is contained in:
@@ -1,16 +1,21 @@
|
|||||||
import '@pnp/sp/webs';
|
import '@pnp/sp/webs';
|
||||||
import '@pnp/sp/lists';
|
import '@pnp/sp/lists';
|
||||||
|
import '@pnp/sp/items';
|
||||||
import '@pnp/sp/folders';
|
import '@pnp/sp/folders';
|
||||||
import '@pnp/sp/files';
|
import '@pnp/sp/files';
|
||||||
import type { IFolder } from '@pnp/sp/folders';
|
import type { IFolder } from '@pnp/sp/folders';
|
||||||
import { getSP } from '../pnp/pnpjs';
|
import { getSP } from '../pnp/pnpjs';
|
||||||
|
import { resolveDataList } from '../dataList';
|
||||||
import { CHAT_FILES_LIBRARY_TITLE } from '../listTitles';
|
import { CHAT_FILES_LIBRARY_TITLE } from '../listTitles';
|
||||||
import { RequestTypeId } from '../../models/types';
|
import { RequestTypeId } from '../../models/types';
|
||||||
import { fileStamp, storedFileName } from './chatFileNames';
|
import { fileStamp, sanitizeFileName, storedFileName } from './chatFileNames';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Файлы, прикреплённые к сообщениям чата, — библиотека «Файлы чата» на сайте
|
* Файлы, прикреплённые к сообщениям чата, — библиотека «Файлы чата» на сайте
|
||||||
* данных, папка на каждую заявку: «Файлы чата/<тип заявки>-<id>».
|
* данных, папка на каждую заявку: «Файлы чата/<RequestUniqueCode>», например
|
||||||
|
* «Файлы чата/13-2608-42» — тот же код, что показан в заголовке заявки (см.
|
||||||
|
* FormCard subtitle в <Форма>View.tsx). Так папку легко узнать в самой
|
||||||
|
* библиотеке, не открывая портал.
|
||||||
*
|
*
|
||||||
* Почему не вложения самой заявки (shared/attachments): вложения — это
|
* Почему не вложения самой заявки (shared/attachments): вложения — это
|
||||||
* документы заявки, они попадают в её карточку и печать. Файл из переписки —
|
* документы заявки, они попадают в её карточку и печать. Файл из переписки —
|
||||||
@@ -57,18 +62,41 @@ function chatLibraryRoot(): Promise<string> {
|
|||||||
return libraryRootPromise;
|
return libraryRootPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Имя папки заявки в библиотеке. Тип заявки в имени — чтобы id разных типов не смешивались. */
|
/**
|
||||||
function requestFolderName(formKey: RequestTypeId, itemId: number): string {
|
* Имя папки заявки в библиотеке — RequestUniqueCode элемента.
|
||||||
return `${formKey}-${itemId}`;
|
*
|
||||||
|
* Код читаем из самого элемента, а не собираем строкой (formKey+itemId), чтобы
|
||||||
|
* папка называлась ровно тем номером, который видит пользователь на заявке.
|
||||||
|
* Код записывается сразу после создания элемента (см. saveRequestItem в
|
||||||
|
* shared/dataList.ts) и с этого момента не меняется, поэтому лишний раз его
|
||||||
|
* не кешируем: запрос — это одно select-поле, а не тяжёлая операция.
|
||||||
|
*
|
||||||
|
* Пустой код (гипотетическая гонка на только что созданной заявке) — откат на
|
||||||
|
* старую схему имени, чтобы папка всё равно нашлась однозначно.
|
||||||
|
*/
|
||||||
|
async function requestFolderName(
|
||||||
|
formKey: RequestTypeId,
|
||||||
|
itemId: number,
|
||||||
|
listId: string | undefined
|
||||||
|
): Promise<string> {
|
||||||
|
const item = (await resolveDataList(formKey, listId)
|
||||||
|
.items.getById(itemId)
|
||||||
|
.select('RequestUniqueCode')()) as { RequestUniqueCode?: string };
|
||||||
|
const code = (item.RequestUniqueCode || '').trim();
|
||||||
|
return sanitizeFileName(code || `${formKey}-${itemId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Адрес папки заявки. Папки может ещё не существовать — для чтения ссылок это неважно. */
|
/** Адрес папки заявки. Папки может ещё не существовать — для чтения ссылок это неважно. */
|
||||||
export async function chatFilesFolderUrl(
|
export async function chatFilesFolderUrl(
|
||||||
formKey: RequestTypeId,
|
formKey: RequestTypeId,
|
||||||
itemId: number
|
itemId: number,
|
||||||
|
listId?: string
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const root = await chatLibraryRoot();
|
const [root, name] = await Promise.all([
|
||||||
return `${root}/${requestFolderName(formKey, itemId)}`;
|
chatLibraryRoot(),
|
||||||
|
requestFolderName(formKey, itemId, listId)
|
||||||
|
]);
|
||||||
|
return `${root}/${name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,9 +107,15 @@ export async function chatFilesFolderUrl(
|
|||||||
* addUsingPath с overwrite=true СНОСИТ содержимое — то есть все ранее
|
* addUsingPath с overwrite=true СНОСИТ содержимое — то есть все ранее
|
||||||
* приложенные к заявке файлы.
|
* приложенные к заявке файлы.
|
||||||
*/
|
*/
|
||||||
async function ensureRequestFolder(formKey: RequestTypeId, itemId: number): Promise<IFolder> {
|
async function ensureRequestFolder(
|
||||||
const root = await chatLibraryRoot();
|
formKey: RequestTypeId,
|
||||||
const name = requestFolderName(formKey, itemId);
|
itemId: number,
|
||||||
|
listId: string | undefined
|
||||||
|
): Promise<IFolder> {
|
||||||
|
const [root, name] = await Promise.all([
|
||||||
|
chatLibraryRoot(),
|
||||||
|
requestFolderName(formKey, itemId, listId)
|
||||||
|
]);
|
||||||
const folder = getSP().web.getFolderByServerRelativePath(`${root}/${name}`);
|
const folder = getSP().web.getFolderByServerRelativePath(`${root}/${name}`);
|
||||||
|
|
||||||
const exists = await folder
|
const exists = await folder
|
||||||
@@ -106,11 +140,12 @@ async function ensureRequestFolder(formKey: RequestTypeId, itemId: number): Prom
|
|||||||
export async function uploadChatFiles(
|
export async function uploadChatFiles(
|
||||||
formKey: RequestTypeId,
|
formKey: RequestTypeId,
|
||||||
itemId: number,
|
itemId: number,
|
||||||
|
listId: string | undefined,
|
||||||
files: File[]
|
files: File[]
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
if (files.length === 0) return [];
|
if (files.length === 0) return [];
|
||||||
|
|
||||||
const folder = await ensureRequestFolder(formKey, itemId);
|
const folder = await ensureRequestFolder(formKey, itemId, listId);
|
||||||
const stamp = fileStamp(new Date());
|
const stamp = fileStamp(new Date());
|
||||||
const storedNames: string[] = [];
|
const storedNames: string[] = [];
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export async function getChatMessages(
|
|||||||
// Адрес библиотеки спрашиваем, только если в переписке ЕСТЬ файлы: у заявки
|
// Адрес библиотеки спрашиваем, только если в переписке ЕСТЬ файлы: у заявки
|
||||||
// без вложений чат тогда вообще не зависит от библиотеки — ни лишнего
|
// без вложений чат тогда вообще не зависит от библиотеки — ни лишнего
|
||||||
// запроса, ни падения, если её переименуют.
|
// запроса, ни падения, если её переименуют.
|
||||||
const folderUrl = hasAttachments(comments) ? await chatFilesFolderUrl(formKey, itemId) : '';
|
const folderUrl = hasAttachments(comments) ? await chatFilesFolderUrl(formKey, itemId, listId) : '';
|
||||||
return toChatMessages(comments, currentUserEmail, folderUrl);
|
return toChatMessages(comments, currentUserEmail, folderUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +73,6 @@ export async function addChatMessage(
|
|||||||
text: string,
|
text: string,
|
||||||
files: File[] = []
|
files: File[] = []
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const storedNames = await uploadChatFiles(formKey, itemId, files);
|
const storedNames = await uploadChatFiles(formKey, itemId, listId, files);
|
||||||
await commentsOf(formKey, itemId, listId).add(buildCommentText(text, storedNames));
|
await commentsOf(formKey, itemId, listId).add(buildCommentText(text, storedNames));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user