diff --git a/public/main.js b/public/main.js
index 1a2a68c..07e5d09 100644
--- a/public/main.js
+++ b/public/main.js
@@ -127,7 +127,22 @@ async function createTask(event) {
alert('Выберите хотя бы одного исполнителя');
return;
}
-
+ // Дополнительная проверка для задач типа "document"
+ if (taskType === 'document' && selectedUsers.length > 0) {
+ // Проверяем, что все выбранные пользователи - секретари
+ for (const userId of selectedUsers) {
+ const groups = await getUserGroups(userId);
+ const hasSecretaryGroup = groups.some(group =>
+ group.name === 'Секретарь' ||
+ (typeof group === 'string' && group.includes('Секретарь'))
+ );
+
+ if (!hasSecretaryGroup) {
+ alert('Для задач типа "Согласование документа" можно выбирать только пользователей из группы "Секретарь"');
+ return;
+ }
+ }
+ }
const formData = new FormData();
formData.append('title', title);
formData.append('description', description);
diff --git a/public/ui.js b/public/ui.js
index cb8fc4e..eb363a9 100644
--- a/public/ui.js
+++ b/public/ui.js
@@ -650,7 +650,7 @@ async function loadTaskFiles(taskId) {
}
// Функция для выбора типа задачи
-function selectTaskType(type) {
+async function selectTaskType(type) {
// Убираем активный класс со всех кнопок
document.querySelectorAll('.task-type-btn').forEach(btn => {
btn.classList.remove('active');
@@ -666,8 +666,66 @@ function selectTaskType(type) {
updateTaskFormBasedOnType(type);
// Предлагаем заголовок по умолчанию
suggestDefaultTitle(type);
+
+ // Для типа "document" перезагружаем пользователей с фильтрацией
+ if (type === 'document') {
+ await reloadUsersForDocumentType();
+ } else {
+ // Для других типов перезагружаем обычных пользователей
+ await loadUsers();
+ }
+}
+// функция для перезагрузки пользователей для типа "document"
+async function reloadUsersForDocumentType() {
+ try {
+ const response = await fetch('/api/users');
+ const allUsersData = await response.json();
+
+ // Фильтруем только пользователей из группы "Секретарь"
+ const secretaries = [];
+ for (const user of allUsersData) {
+ if (user.id === currentUser.id) continue;
+
+ const groups = await getUserGroups(user.id);
+ const hasSecretaryGroup = groups.some(group =>
+ group.name === 'Секретарь' ||
+ (typeof group === 'string' && group.includes('Секретарь'))
+ );
+
+ if (hasSecretaryGroup) {
+ secretaries.push(user);
+ }
+ }
+
+ users = secretaries;
+ filteredUsers = [...users];
+ renderUsersChecklist();
+
+ } catch (error) {
+ console.error('Ошибка загрузки секретарей:', error);
+ }
+}
+// Используем кэширование, чтобы не делать лишние запросы
+async function getUserGroups(userId) {
+ // Используем кэширование, чтобы не делать лишние запросы
+ if (!window.userGroupsCache) window.userGroupsCache = {};
+
+ if (window.userGroupsCache[userId]) {
+ return window.userGroupsCache[userId];
+ }
+
+ try {
+ const response = await fetch(`/api2/idusers/user/${userId}/groups`);
+ if (!response.ok) return [];
+
+ const groups = await response.json();
+ window.userGroupsCache[userId] = groups || [];
+ return window.userGroupsCache[userId];
+ } catch (error) {
+ console.error('Ошибка получения групп пользователя:', error);
+ return [];
+ }
}
-
// Функция для предложения заголовка по умолчанию
function suggestDefaultTitle(type) {
const titleField = document.getElementById('title');
@@ -695,6 +753,7 @@ function suggestDefaultTitle(type) {
// Функция для обновления формы в зависимости от типа задачи
function updateTaskFormBasedOnType(type) {
const userSearchField = document.getElementById('user-search');
+ const taskTypeInfo = document.getElementById('task-type-info');
// Устанавливаем заголовки placeholder для поиска исполнителей
const defaultPlaceholders = {
@@ -713,7 +772,22 @@ function updateTaskFormBasedOnType(type) {
if (userSearchField) {
userSearchField.placeholder = defaultPlaceholders[type] || 'Поиск исполнителей...';
}
-
+ // Показываем информацию о типе задачи
+ if (taskTypeInfo) {
+ const typeInfo = {
+ 'regular': 'Доступны все пользователи в зависимости от ваших прав',
+ 'document': 'Доступны только пользователи из группы "Секретарь"',
+ 'it': 'Доступны ИТ специалисты',
+ 'ahch': 'Доступны сотрудники АХЧ',
+ 'psychologist': 'Доступны психологи',
+ 'speech_therapist': 'Доступны логопеды',
+ 'hr': 'Доступны сотрудники кадровой службы',
+ 'certificate': 'Доступны секретари и завучи',
+ 'e_journal': 'Доступны администраторы электронного журнала'
+ };
+
+ taskTypeInfo.textContent = typeInfo[type] || '';
+ }
// Показываем/скрываем дополнительные поля в зависимости от типа
showAdditionalFieldsForType(type);
}
diff --git a/public/users.js b/public/users.js
index e23944c..6447866 100644
--- a/public/users.js
+++ b/public/users.js
@@ -6,6 +6,9 @@ let selectedUsers = [];
let editSelectedUsers = [];
let copySelectedUsers = [];
+// Добавьте переменную для хранения групп пользователей
+let userGroupsCache = {};
+
async function loadUsers() {
try {
const response = await fetch('/api/users');
@@ -24,9 +27,49 @@ async function loadUsers() {
console.error('Ошибка загрузки пользователей:', error);
}
}
-function filterAssignableUsers(allUsers) {
+
+// Добавьте функцию для получения групп пользователя
+async function getUserGroups(userId) {
+ if (userGroupsCache[userId]) {
+ return userGroupsCache[userId];
+ }
+
+ try {
+ const response = await fetch(`/api2/idusers/user/${userId}/groups`);
+ if (!response.ok) return [];
+
+ const groups = await response.json();
+ userGroupsCache[userId] = groups || [];
+ return userGroupsCache[userId];
+ } catch (error) {
+ console.error('Ошибка получения групп пользователя:', error);
+ return [];
+ }
+}
+
+// Обновите функцию filterAssignableUsers
+function filterAssignableUsers(allUsers, taskType = 'regular') {
if (!currentUser) return [];
+ // Для задач типа "document" - только пользователи из группы "Секретарь"
+ if (taskType === 'document') {
+ return allUsers.filter(async (user) => {
+ if (user.id === currentUser.id) return false;
+
+ // Получаем группы пользователя
+ const groups = await getUserGroups(user.id);
+
+ // Проверяем, есть ли группа "Секретарь"
+ const hasSecretaryGroup = groups.some(group =>
+ group.name === 'Секретарь' ||
+ (typeof group === 'string' && group.includes('Секретарь'))
+ );
+
+ return hasSecretaryGroup;
+ });
+ }
+
+ // Для других типов задач - обычная фильтрация
// Администратор видит всех пользователей
if (currentUser.role === 'admin') {
return allUsers.filter(user => user.id !== currentUser.id);
@@ -67,77 +110,8 @@ function filterAssignableUsers(allUsers) {
user.id !== currentUser.id
);
}
- // Проверяем группы пользователя для определения прав
- const userGroups = currentUser.groups || [];
- // Загружаем конфигурацию групп из настроек
- // (предполагается, что эти переменные определены в глобальной области)
- const allowedGroups = getGroupsForCurrentUser();
-
- // Если у пользователя нет специальных групп, возвращаем пустой массив
- if (allowedGroups.length === 0) {
- return [];
- }
-
- // Фильтруем пользователей по группам
- return allUsers.filter(user => {
- // Пользователь не может назначать задачи себе
- if (user.id === currentUser.id) return false;
-
- // Если у пользователя есть группы, проверяем пересечение
- if (user.groups && Array.isArray(user.groups)) {
- return user.groups.some(group => allowedGroups.includes(group));
- }
-
- return false;
- });
-}
-
-// Функция для получения групп, которым текущий пользователь может назначать задачи
-function getGroupsForCurrentUser() {
- const allowedGroups = [];
- const userGroups = currentUser.groups || [];
-
- // Определяем, какие группы доступны для назначения
- // На основе ролей и групп текущего пользователя
-
- // Пример: пользователи с ролью 'secretary' могут назначать задачи группам 'teachers'
- if (currentUser.role === 'secretary') {
- allowedGroups.push('teachers', 'staff');
- }
-
- // Пример: пользователи из группы 'department_head' могут назначать своей группе
- if (userGroups.includes('department_head')) {
- allowedGroups.push('department_head', 'teachers');
- }
-
- // Пример: для помощи (help) можно назначать всем
- if (currentUser.role === 'help') {
- // Можно указать конкретные группы или 'all' для всех
- allowedGroups.push('teachers', 'staff', 'administration');
- }
-
- // Пример: для IT поддержки
- if (currentUser.role === 'ithelp') {
- allowedGroups.push('teachers', 'staff', 'administration', 'it_department');
- }
-
- // Пример: пользователи с ролью 'request' могут создавать заявки для всех
- if (currentUser.role === 'request') {
- allowedGroups.push('all'); // Специальное значение "все"
- }
-
- // Пример: пользователи с ролью 'tasks' (задачи) могут назначать учителям
- if (currentUser.role === 'tasks') {
- allowedGroups.push('teachers');
- }
-
- // Если массив содержит 'all', возвращаем специальный маркер
- if (allowedGroups.includes('all')) {
- return ['all']; // Это будет обрабатываться в фильтрации
- }
-
- return [...new Set(allowedGroups)]; // Убираем дубликаты
+ return [];
}
function populateFilterDropdowns() {
const creatorFilter = document.getElementById('creator-filter');
@@ -157,33 +131,119 @@ function populateFilterDropdowns() {
});
}
-function filterUsers() {
+// Обновите функцию filterUsers с учетом типа задачи
+async function filterUsers() {
const search = document.getElementById('user-search').value.toLowerCase();
- filteredUsers = users.filter(user =>
- user.name.toLowerCase().includes(search) ||
- user.login.toLowerCase().includes(search) ||
- user.email.toLowerCase().includes(search)
- );
+ const taskType = document.getElementById('task-type').value || 'regular';
+
+ // Для задач типа "document" нужна особая фильтрация
+ if (taskType === 'document') {
+ // Сначала фильтруем по поисковому запросу
+ let tempFiltered = users.filter(user =>
+ user.name.toLowerCase().includes(search) ||
+ user.login.toLowerCase().includes(search) ||
+ user.email.toLowerCase().includes(search)
+ );
+
+ // Затем проверяем группы для каждого пользователя
+ filteredUsers = [];
+ for (const user of tempFiltered) {
+ const groups = await getUserGroups(user.id);
+ const hasSecretaryGroup = groups.some(group =>
+ group.name === 'Секретарь' ||
+ (typeof group === 'string' && group.includes('Секретарь'))
+ );
+
+ if (hasSecretaryGroup) {
+ filteredUsers.push(user);
+ }
+ }
+ } else {
+ // Обычная фильтрация для других типов задач
+ filteredUsers = users.filter(user =>
+ user.name.toLowerCase().includes(search) ||
+ user.login.toLowerCase().includes(search) ||
+ user.email.toLowerCase().includes(search)
+ );
+ }
+
renderUsersChecklist();
}
-function filterEditUsers() {
+async function filterEditUsers() {
const search = document.getElementById('edit-user-search').value.toLowerCase();
- const filtered = users.filter(user =>
- user.name.toLowerCase().includes(search) ||
- user.login.toLowerCase().includes(search) ||
- user.email.toLowerCase().includes(search)
- );
+ const task = tasks.find(t => t.id === document.getElementById('edit-task-id').value);
+ const taskType = task ? task.task_type : 'regular';
+
+ let filtered = [];
+
+ if (taskType === 'document') {
+ // Для задач типа "document" - только секретари
+ let tempFiltered = users.filter(user =>
+ user.name.toLowerCase().includes(search) ||
+ user.login.toLowerCase().includes(search) ||
+ user.email.toLowerCase().includes(search)
+ );
+
+ filtered = [];
+ for (const user of tempFiltered) {
+ const groups = await getUserGroups(user.id);
+ const hasSecretaryGroup = groups.some(group =>
+ group.name === 'Секретарь' ||
+ (typeof group === 'string' && group.includes('Секретарь'))
+ );
+
+ if (hasSecretaryGroup) {
+ filtered.push(user);
+ }
+ }
+ } else {
+ filtered = users.filter(user =>
+ user.name.toLowerCase().includes(search) ||
+ user.login.toLowerCase().includes(search) ||
+ user.email.toLowerCase().includes(search)
+ );
+ }
+
renderEditUsersChecklist(filtered);
}
-function filterCopyUsers() {
+async function filterCopyUsers() {
const search = document.getElementById('copy-user-search').value.toLowerCase();
- const filtered = users.filter(user =>
- user.name.toLowerCase().includes(search) ||
- user.login.toLowerCase().includes(search) ||
- user.email.toLowerCase().includes(search)
- );
+ const taskId = document.getElementById('copy-task-id').value;
+ const task = tasks.find(t => t.id === taskId);
+ const taskType = task ? task.task_type : 'regular';
+
+ let filtered = [];
+
+ if (taskType === 'document') {
+ // Для задач типа "document" - только секретари
+ let tempFiltered = users.filter(user =>
+ user.name.toLowerCase().includes(search) ||
+ user.login.toLowerCase().includes(search) ||
+ user.email.toLowerCase().includes(search)
+ );
+
+ filtered = [];
+ for (const user of tempFiltered) {
+ const groups = await getUserGroups(user.id);
+ const hasSecretaryGroup = groups.some(group =>
+ group.name === 'Секретарь' ||
+ (typeof group === 'string' && group.includes('Секретарь'))
+ );
+
+ if (hasSecretaryGroup) {
+ filtered.push(user);
+ }
+ }
+ } else {
+ filtered = users.filter(user =>
+ user.name.toLowerCase().includes(search) ||
+ user.login.toLowerCase().includes(search) ||
+ user.email.toLowerCase().includes(search)
+ );
+ }
+
renderCopyUsersChecklist(filtered);
}
@@ -197,6 +257,8 @@ function renderUsersChecklist() {
${user.name}
+ ${document.getElementById('task-type').value === 'document' ?
+ '(Секретарь)' : ''}
`).join('');