diff --git a/README.md b/README.md index 84c0524ed4..5a5a06f64c 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,13 @@
-POST
запросы на указанный URL адрес, с информацией о происходящих событиях. Подробности на странице инструкции по использованию вебхуков.
+settings.add_webhook_desc=Мирокод будет оправлять POST
запросы на указанный URL адрес, с информацией о происходящих событиях. Подробности на странице инструкции по использованию вебхуков.
settings.payload_url=URL обработчика
settings.http_method=Метод HTTP
settings.content_type=Тип содержимого
@@ -1827,19 +1858,19 @@ settings.event_desc=На какие события этот веб-хук дол
settings.event_push_only=Просто push событие
settings.event_send_everything=Все события
settings.event_choose=Позвольте мне выбрать то, что нужно.
-settings.event_header_repository=События репозитория
+settings.event_header_repository=События проекта
settings.event_create=Создать
settings.event_create_desc=Ветка или тэг созданы.
settings.event_delete=Удалить
settings.event_delete_desc=Ветка или тег удалены.
settings.event_fork=Форкнуть
-settings.event_fork_desc=Репозиторий форкнут.
+settings.event_fork_desc=Проект форкнут.
settings.event_release=Релиз
-settings.event_release_desc=Релиз опубликован, обновлён или удалён из репозитория.
+settings.event_release_desc=Релиз опубликован, обновлён или удалён из проекта.
settings.event_push=Push
-settings.event_push_desc=Push в репозиторий.
-settings.event_repository=Репозиторий
-settings.event_repository_desc=Репозиторий создан или удален.
+settings.event_push_desc=Push в проект.
+settings.event_repository=Проект
+settings.event_repository_desc=Проект создан или удален.
settings.event_header_issue=События задачи
settings.event_issues=Задачи
settings.event_issues_desc=Задача открыта, закрыта, переоткрыта или отредактирована.
@@ -1876,22 +1907,22 @@ settings.update_hook_success=Вебхук был обновлён.
settings.delete_webhook=Удалить вебхук
settings.recent_deliveries=Недавние рассылки
settings.hook_type=Тип hook'а
-settings.add_slack_hook_desc=Добавить интеграцию с Slack в ваш репозиторий.
+settings.add_slack_hook_desc=Добавить интеграцию с Slack в ваш проект.
settings.slack_token=Slack токен
settings.slack_domain=Домен
settings.slack_channel=Канал
settings.add_discord_hook_desc=Добавить уведомления о событиях через Discord.
-settings.add_dingtalk_hook_desc=Добавить интеграцию с Dingtalk в ваш репозиторий.
-settings.add_telegram_hook_desc=Добавить интеграцию с Telegram в ваш репозиторий.
-settings.add_matrix_hook_desc=Добавить интеграцию Matrix в ваш репозиторий.
-settings.add_msteams_hook_desc=Добавить интеграцию с Microsoft Teams в ваш репозиторий.
-settings.add_feishu_hook_desc=Добавить интеграцию Feishu в ваш репозиторий.
-settings.add_Wechat_hook_desc=Добавить интеграцию с Wechatwork в ваш репозиторий.
+settings.add_dingtalk_hook_desc=Добавить интеграцию с Dingtalk в ваш проект.
+settings.add_telegram_hook_desc=Добавить интеграцию с Telegram в ваш проект.
+settings.add_matrix_hook_desc=Добавить интеграцию Matrix в ваш проект.
+settings.add_msteams_hook_desc=Добавить интеграцию с Microsoft Teams в ваш проект.
+settings.add_feishu_hook_desc=Добавить интеграцию Feishu в ваш проект.
+settings.add_Wechat_hook_desc=Добавить интеграцию с Wechatwork в ваш проект.
settings.deploy_keys=Ключи развертывания
settings.add_deploy_key=Добавить ключ развертывания
settings.deploy_key_desc=Ключи развёртывания доступны только для чтения. Это не то же самое что и SSH-ключи аккаунта.
settings.is_writable=Разрешить запись
-settings.is_writable_info=Может ли этот ключ быть использован для выполнения push в репозиторий? Ключи развёртывания всегда имеют доступ на pull.
+settings.is_writable_info=Может ли этот ключ быть использован для выполнения push в проект? Ключи развёртывания всегда имеют доступ на pull.
settings.no_deploy_keys=Вы не добавляли ключи развертывания.
settings.title=Заголовок
settings.deploy_key_content=Содержимое
@@ -1926,7 +1957,7 @@ settings.protect_merge_whitelist_users=Пользователи с правом
settings.protect_merge_whitelist_teams=Команды, члены которых обладают правом на слияние:
settings.protect_check_status_contexts=Включить проверку статуса
settings.protect_check_status_contexts_desc=Требуется пройти проверку состояния перед слиянием. Выберите, какие проверки состояния должны быть пройдены, прежде чем ветви можно будет объединить в ветвь, соответствующую этому правилу. Если этот параметр включен, коммиты сначала должны быть перемещены в другую ветвь, а затем объединены или перемещены непосредственно в ветвь, соответствующую этому правилу, после прохождения проверки состояния. Если контексты не выбраны, то последняя фиксация должна быть успешной независимо от контекста.
-settings.protect_check_status_contexts_list=Проверки состояния за последнюю неделю для этого репозитория
+settings.protect_check_status_contexts_list=Проверки состояния за последнюю неделю для этого проекта
settings.protect_required_approvals=Необходимые одобрения:
settings.protect_required_approvals_desc=Разрешить принятие запроса на слияние только с достаточным количеством положительных отзывов.
settings.protect_approvals_whitelist_enabled=Ограничить утверждения белым списком пользователей или команд
@@ -1988,10 +2019,10 @@ settings.unarchive.header=Разархивировать этот репозит
settings.unarchive.text=Разархивация восстанавливает возможность совершать push в репозиторий, создавать новые коммиты, задачи и запросы на слияние.
settings.unarchive.success=Репозиторий был успешно разархивирован.
settings.unarchive.error=Ошибка при попытке разархивировать репозиторий. Смотрите логи для получения подробностей.
-settings.update_avatar_success=Аватар репозитория обновлён.
+settings.update_avatar_success=Аватар проекта обновлён.
settings.lfs=LFS
settings.lfs_filelist=Файлы LFS хранятся в этом репозитории
-settings.lfs_no_lfs_files=Нет файлов LFS в этом репозитории
+settings.lfs_no_lfs_files=Нет файлов Large file storage (LFS) в этом репозитории1
settings.lfs_findcommits=Найти коммиты
settings.lfs_lfs_file_no_commits=Для этого LFS файла не найдено коммитов
settings.lfs_noattribute=Этот путь не имеет блокируемого атрибута в ветке по умолчанию
@@ -2010,7 +2041,7 @@ settings.lfs_force_unlock=Принудительная разблокировк
settings.lfs_pointers.found=Найдено %d указатель(ей) блоков - присоединено %d, %d не привязано (%d отсутствует в хранилище)
settings.lfs_pointers.sha=Blob SHA
settings.lfs_pointers.oid=OID
-settings.lfs_pointers.inRepo=В репозитории
+settings.lfs_pointers.inRepo=В проекте
settings.lfs_pointers.exists=Существуют в хранилище
settings.lfs_pointers.accessible=Доступно для пользователя
settings.lfs_pointers.associateAccessible=Связать доступные %d OID
@@ -2158,15 +2189,15 @@ error.csv.unexpected=Не удается отобразить этот файл,
error.csv.invalid_field_count=Не удается отобразить этот файл, потому что он имеет неправильное количество полей в строке %d.
[org]
-org_name_holder=Название организации
-org_full_name_holder=Полное название организации
-org_name_helper=Лучшие названия организаций коротки и запоминаемы.
-create_org=Создать организацию
+org_name_holder=Название сообщества
+org_full_name_holder=Полное название сообщества
+org_name_helper=Лучшие названия сообществ коротки и запоминаемы.
+create_org=Создать сообщество
repo_updated=Обновлено
people=Люди
teams=Команды
lower_members=Участники
-lower_repositories=Репозитории
+lower_repositories=Проекты
create_new_team=Создание команды
create_team=Создать команду
org_desc=Описание
@@ -2174,43 +2205,44 @@ team_name=Название команды
team_desc=Описание
team_name_helper=Названия команд должны быть короткими и запоминающимися.
team_desc_helper=Что это за команда?
-team_access_desc=Доступ к репозиторию
+team_access_desc=Доступ к проекту
team_permission_desc=Разрешение
-team_unit_desc=Разрешить доступ к разделам репозитория
+team_unit_desc=Разрешить доступ к разделам проекта
team_unit_disabled=(Отключено)
-form.name_reserved=Наименование организации '%s' зарезервированно.
-form.name_pattern_not_allowed=Шаблон организации '%s' не допускается.
-form.create_org_not_allowed=Этому пользователю не разрешено создавать организацию.
+form.name_reserved=Наименование сообщества '%s' зарезервированно.
+form.name_pattern_not_allowed=Шаблон сообщества '%s' не допускается.
+form.create_org_not_allowed=Этому пользователю не разрешено создавать сообщество.
settings=Настройки
-settings.options=Организация
+settings.options=Сообщество
settings.full_name=Полное имя
settings.website=Сайт
settings.location=Местоположение
+settings.locationcoordinate=Координаты
settings.permission=Разрешения
-settings.repoadminchangeteam=Администратор репозитория может добавлять и удалять права доступа для команд
+settings.repoadminchangeteam=Администратор проекта может добавлять и удалять права доступа для команд
settings.visibility=Видимость
settings.visibility.public=Публичный
settings.visibility.limited=Ограничено (Видно только для авторизованных пользователей)
settings.visibility.limited_shortname=Ограничить
-settings.visibility.private=Частный (Видимый только для участников организации)
+settings.visibility.private=Частный (Видимый только для участников сообщества)
settings.visibility.private_shortname=Приватный
settings.update_settings=Обновить настройки
-settings.update_setting_success=Настройки организации обновлены.
-settings.change_orgname_prompt=Это изменение изменит ссылки на организацию.
+settings.update_setting_success=Настройки сообщества обновлены.
+settings.change_orgname_prompt=Это изменение изменит ссылки на сообщество.
settings.change_orgname_redirect_prompt=Старое имя будет перенаправлено до тех пор, пока оно не будет введено.
-settings.update_avatar_success=Аватар организации обновлён.
-settings.delete=Удалить организацию
-settings.delete_account=Удалить эту организацию
-settings.delete_prompt=Это действие БЕЗВОЗВРАТНО удалит эту организацию навсегда.
+settings.update_avatar_success=Аватар сообщества обновлён.
+settings.delete=Удалить сообщество
+settings.delete_account=Удалить это сообщество
+settings.delete_prompt=Это действие БЕЗВОЗВРАТНО удалит это сообщество навсегда.
settings.confirm_delete_account=Подтвердить удаление
-settings.delete_org_title=Удалить организацию
-settings.delete_org_desc=Эта организация будет безвозвратно удалена. Продолжить?
-settings.hooks_desc=Добавьте вебхуки, которые будет вызываться для всех репозиториев под этой организации.
+settings.delete_org_title=Удалить сообщество
+settings.delete_org_desc=Это сообщество будет безвозвратно удалена. Продолжить?
+settings.hooks_desc=Добавьте вебхуки, которые будет вызываться для всех репозиториев под этим сообществом.
-settings.labels_desc=Добавьте метки, которые могут быть использованы в задачах для всех репозиториев этой организации.
+settings.labels_desc=Добавьте метки, которые могут быть использованы в задачах для всех репозиториев этого сообщества.
members.membership_visibility=Видимость участника команды:
members.public=Видимый
@@ -2230,12 +2262,12 @@ members.invite_now=Пригласите сейчас
teams.join=Объединить
teams.leave=Выйти
teams.leave.detail=Покинуть %s?
-teams.can_create_org_repo=Создать репозитории
-teams.can_create_org_repo_helper=Участники могут создавать новые репозитории в организации. Создатель получит администраторский доступ к новому репозиторию.
-teams.read_access_helper=Участники могут просматривать и клонировать командные репозитории.
-teams.write_access_helper=Участники могут читать и выполнять push в командные репозитории.
+teams.can_create_org_repo=Создать проекты
+teams.can_create_org_repo_helper=Участники могут создавать новые проекты в сообщество. Создатель получит администраторский доступ к новому репозиторию.
+teams.read_access_helper=Участники могут просматривать и клонировать командные проекты.
+teams.write_access_helper=Участники могут читать и выполнять push в командные проекты.
teams.admin_access=Доступ администратора
-teams.admin_access_helper=Участники могут выполнять pull, push в командные репозитории и добавлять соавторов в команду.
+teams.admin_access_helper=Участники могут выполнять pull, push в командные проекты и добавлять соавторов в команду.
teams.no_desc=Эта группа не имеет описания
teams.settings=Настройки
teams.owners_permission_desc=Владельцы имеют полный доступ ко всем репозиториям и имеют права администратора организации.
@@ -2246,33 +2278,33 @@ teams.add_team_member=Добавление члена группы разраб
teams.delete_team_title=Удалить команду
teams.delete_team_desc=Удаление команды отменяет доступ к репозиторию для её членов. Продолжить?
teams.delete_team_success=Команда удалена.
-teams.read_permission_desc=Эта команда предоставляет доступ на Чтение: члены могут просматривать и клонировать репозитории команды.
-teams.write_permission_desc=Эта команда предоставляет доступ на Запись: члены могут получать и выполнять push команды в репозитории.
+teams.read_permission_desc=Эта команда предоставляет доступ на Чтение: члены могут просматривать и клонировать проекты команды.
+teams.write_permission_desc=Эта команда предоставляет доступ на Запись: члены могут получать и выполнять push команды в проекты.
teams.admin_permission_desc=Эта команда дает административный доступ: участники могут читать, пушить и добавлять соавторов к ее репозиториям.
-teams.create_repo_permission_desc=Кроме того, эта команда предоставляет право Создание репозитория: члены команды могут создавать новые репозитории в организации.
-teams.repositories=Репозитории группы разработки
-teams.search_repo_placeholder=Поиск репозитория…
-teams.remove_all_repos_title=Удалить все репозитории команды
-teams.remove_all_repos_desc=Удаляет все репозитории из команды.
-teams.add_all_repos_title=Добавить все репозитории
-teams.add_all_repos_desc=Добавит все репозитории организации в команду.
+teams.create_repo_permission_desc=Кроме того, эта команда предоставляет право Создание проекта: члены команды могут создавать новые репозитории в сообщество.
+teams.repositories=Проекты группы разработки
+teams.search_repo_placeholder=Поиск проекта…
+teams.remove_all_repos_title=Удалить все проекты команды
+teams.remove_all_repos_desc=Удаляет все проекты из команды.
+teams.add_all_repos_title=Добавить все проекты
+teams.add_all_repos_desc=Добавит все проекты сообщества в команду.
teams.add_nonexistent_repo=Вы добавляете в отсутствующий репозиторий, пожалуйста сначала его создайте.
teams.add_duplicate_users=Пользователь уже состоит в команде.
teams.repos.none=Для этой команды нет доступных репозиториев.
teams.members.none=В этой команде нет участников.
-teams.specific_repositories=Конкретные репозитории
-teams.specific_repositories_helper=Участники будут иметь доступ только к репозиториям, явно добавленным в команду. Выбор этого не автоматически удалит репозитории, уже добавленные в Все репозитории.
-teams.all_repositories=Все репозитории
-teams.all_repositories_helper=Команда имеет доступ ко всем репозиториям. Выбрав его, добавит все существующие репозитории в команду.
-teams.all_repositories_read_permission_desc=Эта команда предоставляет прочтено доступ к всем репозиториям: участники могут просматривать и клонировать репозитории.
-teams.all_repositories_write_permission_desc=Эта команда предоставляет Написать доступ к всем репозиториям: участники могут читать и выполнять push в репозитории.
-teams.all_repositories_admin_permission_desc=Эта команда предоставляет администратору доступ к всем репозиториям: участники могут читать, отправлять сообщения и добавлять соавторов в репозитории.
+teams.specific_repositories=Конкретные проекты
+teams.specific_repositories_helper=Участники будут иметь доступ только к проектам, явно добавленным в команду. Выбор этого не автоматически удалит репозитории, уже добавленные в Все репозитории.
+teams.all_repositories=Все проекты
+teams.all_repositories_helper=Команда имеет доступ ко всем проектам. Выбрав его, добавит все существующие проекты в команду.
+teams.all_repositories_read_permission_desc=Эта команда предоставляет прочтено доступ к всем проектам: участники могут просматривать и клонировать репозитории.
+teams.all_repositories_write_permission_desc=Эта команда предоставляет Написать доступ к всем проектам: участники могут читать и выполнять push в репозитории.
+teams.all_repositories_admin_permission_desc=Эта команда предоставляет администратору доступ к всем проектам: участники могут читать, отправлять сообщения и добавлять соавторов в репозитории.
[admin]
dashboard=Панель
users=Пользователи
-organizations=Организации
-repositories=Репозитории
+organizations=Сообщества
+repositories=Проекты
hooks=Веб-хуки
authentication=Авторизация
emails=Адреса эл. почты пользователей
@@ -2286,7 +2318,7 @@ total=Всего: %d
dashboard.statistic=Статистика
dashboard.operations=Операции
dashboard.system_status=Статус системного монитора
-dashboard.statistic_info=В базе данных Gitea записано %d пользователей, %d организаций, %d публичных ключей, %d репозиториев, %d подписок на репозитории, %d добавлений в избранное, %d действий, %d доступов, %d задач, %d комментариев, %d социальных учетных записей, %d подписок на пользователей, %d зеркал, %d релизов, %d источников входа, %d вебхуков, %d этапов, %d меток, %d задач hook'ов, %d команд, %d задач по обновлению, %d присоединённых файлов.
+dashboard.statistic_info=В базе данных Мирокод записано %d пользователей, %d сообществ, %d публичных ключей, %d репозиториев, %d подписок на репозитории, %d добавлений в избранное, %d действий, %d доступов, %d задач, %d комментариев, %d социальных учетных записей, %d подписок на пользователей, %d зеркал, %d релизов, %d источников входа, %d вебхуков, %d этапов, %d меток, %d задач hook'ов, %d команд, %d задач по обновлению, %d присоединённых файлов.
dashboard.operation_name=Имя операции
dashboard.operation_switch=Переключить
dashboard.operation_run=Запуск
@@ -2317,9 +2349,9 @@ dashboard.archive_cleanup=Удалить старые архивы репози
dashboard.deleted_branches_cleanup=Очистка удалённых ветвей
dashboard.update_migration_poster_id=Обновить ID плакатов миграции
dashboard.git_gc_repos=Выполнить сборку мусора для всех репозиториев
-dashboard.resync_all_sshkeys=Обновить файл '.ssh/authorized_keys' с SSH ключами Gitea.
+dashboard.resync_all_sshkeys=Обновить файл '.ssh/authorized_keys' с SSH ключами Мирокод.
dashboard.resync_all_sshkeys.desc=(Не требуется для встроенного SSH сервера.)
-dashboard.resync_all_sshprincipals=Обновите файл '.ssh/authorized_principals' SSH данными участника Gitea.
+dashboard.resync_all_sshprincipals=Обновите файл '.ssh/authorized_principals' SSH данными участника Мирокод.
dashboard.resync_all_sshprincipals.desc=(Не требуется для встроенного SSH сервера.)
dashboard.resync_all_hooks=Повторная синхронизация hook'ов pre-receive, update и post-receive во всех репозиториях.
dashboard.reinit_missing_repos=Переинициализировать все отсутствующие Git репозитории, для которых существуют записи
@@ -2365,7 +2397,7 @@ users.activated=Активирован
users.admin=Администратор
users.restricted=Ограничено
users.2fa=Двухфакторная авторизация
-users.repos=Репозитории
+users.repos=Проекты
users.created=Создано
users.last_login=Последний вход
users.never_login=Никогда не входил
@@ -2378,20 +2410,20 @@ users.auth_login_name=Логин для авторизации
users.password_helper=Оставьте пустым, чтобы оставить без изменений.
users.update_profile_success=Профиль учётной записи обновлён успешно.
users.edit_account=Изменение учетной записи
-users.max_repo_creation=Максимальное количество репозиториев
+users.max_repo_creation=Максимальное количество проектов
users.max_repo_creation_desc=(Установите -1 для использования стандартного глобального значения предела)
users.is_activated=Эта учетная запись активирована
users.prohibit_login=Этой учетной записи запрещён вход в систему
users.is_admin=У этой учетной записи есть права администратора
users.is_restricted=Ограничен
users.allow_git_hook=Эта учётная запись имеет разрешение на создание Git hook'ов
-users.allow_git_hook_tooltip=Git Hooks выполняется как пользователь ОС с Gitea и будет иметь одинаковый уровень доступа к хосту. В результате пользователи с привилегией Git Hook могут получить доступ и модифицировать все репозитории Gitea, а также базу данных, используемую Gitea. Следовательно, они также могут получить привилегии администратора Gitea.
-users.allow_import_local=Пользователь имеет право импортировать локальные репозитории
-users.allow_create_organization=Эта учетная запись имеет разрешения на создание организаций
+users.allow_git_hook_tooltip=Git Hooks выполняется как пользователь ОС с Мирокод и будет иметь одинаковый уровень доступа к хосту. В результате пользователи с привилегией Git Hook могут получить доступ и модифицировать все репозитории Мирокод, а также базу данных, используемую Мирокод. Следовательно, они также могут получить привилегии администратора Мирокод.
+users.allow_import_local=Пользователь имеет право импортировать локальные проекты
+users.allow_create_organization=Эта учетная запись имеет разрешения на создание сообществ
users.update_profile=Обновить профиль учетной записи
users.delete_account=Удалить эту учетную запись
users.still_own_repo=На вашем аккаунте все еще остается один или более репозиториев, сначала вам нужно удалить или передать их.
-users.still_has_org=Эта учетная запись все еще является членом одной или более организаций. Для продолжения, покиньте или удалите организации.
+users.still_has_org=Эта учетная запись все еще является членом одной или более сообществ. Для продолжения, покиньте или удалите сообщества.
users.deletion_success=Учётная запись успешно удалена.
users.reset_2fa=Сброс 2FA
users.list_status_filter.menu_text=Фильтр
@@ -2420,15 +2452,15 @@ emails.duplicate_active=Этот адрес электронной почты у
emails.change_email_header=Обновить свойства электронной почты
emails.change_email_text=Вы уверены, что хотите обновить этот адрес электронной почты?
-orgs.org_manage_panel=Управление организациями
+orgs.org_manage_panel=Управление сообществами
orgs.name=Название
orgs.teams=Команды
orgs.members=Участники
-orgs.new_orga=Новая организация
+orgs.new_orga=Новое сообщество
-repos.repo_manage_panel=Управление репозиториями
-repos.unadopted=Непринятые репозитории
-repos.unadopted.no_more=Больше непринятых репозиториев не найдено
+repos.repo_manage_panel=Управление проектами
+repos.unadopted=Непринятые проекты
+repos.unadopted.no_more=Больше непринятых проектов не найдено
repos.owner=Владелец
repos.name=Название
repos.private=Личный
@@ -2439,12 +2471,12 @@ repos.issues=Задачи
repos.size=Размер
defaulthooks=Стандартные Веб-хуки
-defaulthooks.desc=Вебхуки автоматически делают HTTP-POST запросы на сервер, когда вызываются определенные события Gitea. Вебхуки, определённые здесь, по умолчанию и будут скопированы во все новые репозитории. Подробнее читайте в руководстве по вебхукам.
+defaulthooks.desc=Вебхуки автоматически делают HTTP-POST запросы на сервер, когда вызываются определенные события Мирокод. Вебхуки, определённые здесь, по умолчанию и будут скопированы во все новые репозитории. Подробнее читайте в руководстве по вебхукам.
defaulthooks.add_webhook=Добавить стандартный Веб-хук
defaulthooks.update_webhook=Обновить стандартный Веб-хук
systemhooks=Системные вебхуки
-systemhooks.desc=Вебхуки автоматически делают HTTP-POST запросы на сервер, когда вызываются определённые события Gitea. Определённые вебхуки будут действовать на всех репозиториях системы, поэтому пожалуйста, учитывайте любые последствия для производительности. Подробнее читайте в руководстве по вебхукам.
+systemhooks.desc=Вебхуки автоматически делают HTTP-POST запросы на сервер, когда вызываются определённые события Мирокод. Определённые вебхуки будут действовать на всех репозиториях системы, поэтому пожалуйста, учитывайте любые последствия для производительности. Подробнее читайте в руководстве по вебхукам.
systemhooks.add_webhook=Добавить системный вебхук
systemhooks.update_webhook=Обновить системный вебхук
@@ -2555,8 +2587,8 @@ auths.login_source_of_type_exist=Источник аутентификации
config.server_config=Конфигурация сервера
config.app_name=Название сайта
-config.app_ver=Версия Gitea
-config.app_url=Базовый URL-адрес Gitea
+config.app_ver=Версия Мирокод
+config.app_url=Базовый URL-адрес Мирокод
config.custom_conf=Путь к файлу конфигурации
config.custom_file_root_path=Пользовательский путь до папки с файлами
config.domain=Домен сервера
@@ -2565,7 +2597,7 @@ config.disable_router_log=Отключение журнала маршрутиз
config.run_user=Запуск от имени пользователя
config.run_mode=Режим выполнения
config.git_version=Версия Git
-config.repo_root_path=Путь до папки репозиториев
+config.repo_root_path=Путь до папки проектов
config.lfs_root_path=Корневой путь LFS
config.static_file_root_path=Путь до папки со статичными файлами
config.log_file_root_path=Путь к журналу
@@ -2601,7 +2633,7 @@ config.db_path=Путь
config.service_config=Сервисная конфигурация
config.register_email_confirm=Требуется подтверждение по электронной почте
config.disable_register=Отключить самостоятельную регистрацию
-config.allow_only_internal_registration=Разрешить регистрацию только через Gitea
+config.allow_only_internal_registration=Разрешить регистрацию только через Мирокод
config.allow_only_external_registration=Разрешить регистрацию только через сторонние сервисы
config.enable_openid_signup=Включить cамостоятельную регистрацию OpenID
config.enable_openid_signin=Включение входа через OpenID
@@ -2613,13 +2645,14 @@ config.enable_captcha=Включить CAPTCHA
config.active_code_lives=Время жизни кода для активации
config.reset_password_code_lives=Время действия кода восстановления аккаунта
config.default_keep_email_private=Скрывать адреса электронной почты по умолчанию
-config.default_allow_create_organization=Разрешить создание организаций по умолчанию
+config.default_allow_create_organization=Разрешить создание сообществ по умолчанию
config.enable_timetracking=Включить отслеживание времени
config.default_enable_timetracking=Включить отслеживание времени по умолчанию
config.default_allow_only_contributors_to_track_time=Учитывать только участников разработки в подсчёте времени
config.no_reply_address=No-reply адрес
-config.default_visibility_organization=Видимость по умолчанию для новых организаций
+config.default_visibility_organization=Видимость по умолчанию для новых сообществ
config.default_enable_dependencies=Включение зависимостей для задач по умолчанию
+config.default_enable_parents=Включение родителей для задач по умолчанию
config.webhook_config=Конфигурация вебхуков
config.queue_length=Длина очереди
@@ -2764,15 +2797,15 @@ notices.inverse_selection=Инверсия выделения
notices.delete_selected=Удалить выбранные
notices.delete_all=Удалить все уведомления
notices.type=Тип
-notices.type_1=Репозиторий
+notices.type_1=Проект
notices.type_2=Задача
notices.desc=Описание
notices.op=Oп.
notices.delete_success=Уведомления системы были удалены.
[action]
-create_repo=создал(а) репозиторий %s
-rename_repo=переименовал(а) репозиторий из %[1]s
на %[3]s
+create_repo=создал(а) Проект %s
+rename_repo=переименовал(а) Проект из %[1]s
на %[3]s
commit_repo=отправил(а) изменения в %[3]s в %[4]s
create_issue=`открыл(а) задачу %[3]s#%[2]s`
close_issue=`закрыл(а) задачу %[3]s#%[2]s`
@@ -2783,7 +2816,7 @@ reopen_pull_request=`переоткрыл(а) запрос на слияние <
comment_issue=`прокомментировал(а) задачу %[3]s#%[2]s`
comment_pull=`прокомментировал(а) запрос на слияние %[3]s#%[2]s`
merge_pull_request=`принял(а) запрос на слияние %[3]s#%[2]s`
-transfer_repo=передал(а) репозиторий %s
%s
+transfer_repo=передал(а) Проект %s
%s
push_tag=создал(а) тег %[3]s в %[4]s
delete_tag=удалил(а) тэг %[2]s из %[3]s
delete_branch=удалил(а) ветку %[2]s из %[3]s
diff --git a/package-lock.json b/package-lock.json
index 2f8d921e21..e7e1a78627 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1711,6 +1711,8 @@
"version": "8.9.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz",
"integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==",
+ "optional": true,
+ "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -1725,7 +1727,9 @@
"node_modules/ajv-formats/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
- "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "optional": true,
+ "peer": true
},
"node_modules/ajv-keywords": {
"version": "3.5.2",
@@ -2119,13 +2123,19 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001301",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001301.tgz",
- "integrity": "sha512-csfD/GpHMqgEL3V3uIgosvh+SVIQvCh43SNu9HRbP1lnxkKm1kjDG4f32PP571JplkLjfS+mg2p1gxR7MYrrIA==",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- }
+ "version": "1.0.30001374",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001374.tgz",
+ "integrity": "sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ }
+ ]
},
"node_modules/chalk": {
"version": "4.1.2",
@@ -11189,14 +11199,13 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
- "requires": {
- "ajv": "^8.0.0"
- },
+ "requires": {},
"dependencies": {
"ajv": {
- "version": "8.9.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz",
+ "version": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz",
"integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==",
+ "optional": true,
+ "peer": true,
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -11207,7 +11216,9 @@
"json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
- "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "optional": true,
+ "peer": true
}
}
},
@@ -11497,9 +11508,9 @@
}
},
"caniuse-lite": {
- "version": "1.0.30001301",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001301.tgz",
- "integrity": "sha512-csfD/GpHMqgEL3V3uIgosvh+SVIQvCh43SNu9HRbP1lnxkKm1kjDG4f32PP571JplkLjfS+mg2p1gxR7MYrrIA=="
+ "version": "1.0.30001374",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001374.tgz",
+ "integrity": "sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw=="
},
"chalk": {
"version": "4.1.2",
diff --git a/public/img/logo.png b/public/img/logo.png
index c7971f9183..35d3130230 100644
Binary files a/public/img/logo.png and b/public/img/logo.png differ
diff --git a/public/img/logo.svg b/public/img/logo.svg
index afeeacb77c..e3db89903e 100644
--- a/public/img/logo.svg
+++ b/public/img/logo.svg
@@ -1 +1,107 @@
-
\ No newline at end of file
+
+
diff --git a/public/img/logo1.svg b/public/img/logo1.svg
new file mode 100644
index 0000000000..65fe4bc970
--- /dev/null
+++ b/public/img/logo1.svg
@@ -0,0 +1,102 @@
+
+
diff --git a/public/img/logo2.svg b/public/img/logo2.svg
new file mode 100644
index 0000000000..fe2aade512
--- /dev/null
+++ b/public/img/logo2.svg
@@ -0,0 +1,51 @@
+
+
\ No newline at end of file
diff --git a/routers/api/v1/admin/org.go b/routers/api/v1/admin/org.go
index bdfe87fd4e..40d67f5e62 100644
--- a/routers/api/v1/admin/org.go
+++ b/routers/api/v1/admin/org.go
@@ -62,6 +62,7 @@ func CreateOrg(ctx *context.APIContext) {
Description: form.Description,
Website: form.Website,
Location: form.Location,
+ LocationCoordinate: form.LocationCoordinate,
IsActive: true,
Type: user_model.UserTypeOrganization,
Visibility: visibility,
diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go
index 7262073bbd..a987e59096 100644
--- a/routers/api/v1/admin/user.go
+++ b/routers/api/v1/admin/user.go
@@ -240,6 +240,9 @@ func EditUser(ctx *context.APIContext) {
if form.Location != nil {
u.Location = *form.Location
}
+ if form.LocationCoordinate != nil {
+ u.LocationCoordinate = *form.LocationCoordinate
+ }
if form.Description != nil {
u.Description = *form.Description
}
diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go
index 133cce3416..817d6d5c98 100644
--- a/routers/api/v1/org/org.go
+++ b/routers/api/v1/org/org.go
@@ -267,6 +267,7 @@ func Create(ctx *context.APIContext) {
Description: form.Description,
Website: form.Website,
Location: form.Location,
+ LocationCoordinate: form.LocationCoordinate,
IsActive: true,
Type: user_model.UserTypeOrganization,
Visibility: visibility,
@@ -340,6 +341,7 @@ func Edit(ctx *context.APIContext) {
org.Description = form.Description
org.Website = form.Website
org.Location = form.Location
+ org.LocationCoordinate = form.LocationCoordinate
if form.Visibility != "" {
org.Visibility = api.VisibilityModes[form.Visibility]
}
diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go
index 851505fe4a..7449ecabcf 100644
--- a/routers/api/v1/repo/repo.go
+++ b/routers/api/v1/repo/repo.go
@@ -776,6 +776,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
EnableTimetracker: opts.InternalTracker.EnableTimeTracker,
AllowOnlyContributorsToTrackTime: opts.InternalTracker.AllowOnlyContributorsToTrackTime,
EnableDependencies: opts.InternalTracker.EnableIssueDependencies,
+ EnableParents: opts.InternalTracker.EnableIssueParents,
}
} else if unit, err := repo.GetUnit(unit_model.TypeIssues); err != nil {
// Unit type doesn't exist so we make a new config file with default values
@@ -783,6 +784,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
EnableTimetracker: true,
AllowOnlyContributorsToTrackTime: true,
EnableDependencies: true,
+ EnableParents: true,
}
} else {
config = unit.IssuesConfig()
diff --git a/routers/api/v1/user/settings.go b/routers/api/v1/user/settings.go
index 5f4d76ed72..8f01da4543 100644
--- a/routers/api/v1/user/settings.go
+++ b/routers/api/v1/user/settings.go
@@ -57,6 +57,9 @@ func UpdateUserSettings(ctx *context.APIContext) {
if form.Location != nil {
ctx.User.Location = *form.Location
}
+ if form.LocationCoordinate != nil {
+ ctx.User.LocationCoordinate = *form.LocationCoordinate
+ }
if form.Language != nil {
ctx.User.Language = *form.Language
}
diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go
index 1576f58b41..4b94fe9e10 100644
--- a/routers/web/admin/users.go
+++ b/routers/web/admin/users.go
@@ -371,7 +371,9 @@ func EditUserPost(ctx *context.Context) {
emailChanged := !strings.EqualFold(u.Email, form.Email)
u.Email = form.Email
u.Website = form.Website
+ u.Description = form.Description
u.Location = form.Location
+ u.LocationCoordinate = form.LocationCoordinate
u.MaxRepoCreation = form.MaxRepoCreation
u.IsActive = form.Active
u.IsAdmin = form.Admin
diff --git a/routers/web/map/umap.go b/routers/web/map/umap.go
new file mode 100644
index 0000000000..e53e84ae13
--- /dev/null
+++ b/routers/web/map/umap.go
@@ -0,0 +1,127 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package umap
+
+import (
+ "bytes"
+ "net/http"
+
+ "code.gitea.io/gitea/models/db"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/markup"
+ "code.gitea.io/gitea/modules/markup/markdown"
+
+)
+
+const (
+ // tplExploreUsers map page template
+ tplExploreUsers base.TplName = "map/umap"
+)
+
+// UserSearchDefaultSortType is the default sort type for user search
+const UserSearchDefaultSortType = "alphabetically"
+
+var (
+ nullByte = []byte{0x00}
+)
+
+func isKeywordValid(keyword string) bool {
+ return !bytes.Contains([]byte(keyword), nullByte)
+}
+
+// RenderUserSearch render user search page
+func RenderUserSearch(ctx *context.Context, opts *user_model.SearchUserOptions, tplName base.TplName) {
+ opts.PageSize = 8 * 1024 // Get all users
+ opts.Page = ctx.FormInt("page")
+ if opts.Page <= 1 {
+ opts.Page = 1
+ }
+
+ var (
+ users []*user_model.User
+ count int64
+ err error
+ orderBy db.SearchOrderBy
+ )
+
+ // we can not set orderBy to `models.SearchOrderByXxx`, because there may be a JOIN in the statement, different tables may have the same name columns
+ ctx.Data["SortType"] = ctx.FormString("sort")
+ switch ctx.FormString("sort") {
+ case "newest":
+ orderBy = "`user`.id DESC"
+ case "oldest":
+ orderBy = "`user`.id ASC"
+ case "recentupdate":
+ orderBy = "`user`.updated_unix DESC"
+ case "leastupdate":
+ orderBy = "`user`.updated_unix ASC"
+ case "reversealphabetically":
+ orderBy = "`user`.name DESC"
+ case UserSearchDefaultSortType: // "alphabetically"
+ default:
+ orderBy = "`user`.name ASC"
+ ctx.Data["SortType"] = UserSearchDefaultSortType
+ }
+
+ opts.Keyword = ctx.FormTrim("q")
+ opts.OrderBy = orderBy
+ if len(opts.Keyword) == 0 || isKeywordValid(opts.Keyword) {
+ users, count, err = user_model.SearchUsers(opts)
+ if err != nil {
+ ctx.ServerError("SearchUsers", err)
+ return
+ }
+ }
+
+ for i := range users {
+ if len(users[i].Description) != 0 {
+ content, err := markdown.RenderString(&markup.RenderContext{
+ URLPrefix: ctx.Repo.RepoLink,
+ Metas: map[string]string{"mode": "document"},
+ GitRepo: ctx.Repo.GitRepo,
+ Ctx: ctx,
+ }, users[i].Description)
+ if err != nil {
+ ctx.ServerError("RenderString", err)
+ return
+ }
+ users[i].Description = content
+ }
+ }
+
+ ctx.Data["Keyword"] = opts.Keyword
+ ctx.Data["Total"] = count
+ ctx.Data["Users"] = users
+ ctx.Data["UsersTwoFaStatus"] = user_model.UserList(users).GetTwoFaStatus()
+ ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
+
+ ctx.HTML(http.StatusOK, tplName)
+}
+
+// Users render explore users page
+func UsersMap(ctx *context.Context) {
+ if setting.Service.Explore.DisableUsersPage {
+ ctx.Redirect(setting.AppSubURL + "/map/umap")
+ return
+ }
+ ctx.Data["Title"] = ctx.Tr("map")
+ ctx.Data["PageIsMap"] = true
+ ctx.Data["PageIsMapUsers"] = true
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
+
+ RenderUserSearch(ctx, &user_model.SearchUserOptions{
+ Actor: ctx.User,
+ Type: user_model.UserTypeIndividual,
+ ListOptions: db.ListOptions{PageSize: setting.UI.ExplorePagingNum},
+ IsActive: util.OptionalBoolTrue,
+ Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate},
+ }, tplExploreUsers)
+}
diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go
index 081e103f79..16f83f8b80 100644
--- a/routers/web/org/setting.go
+++ b/routers/web/org/setting.go
@@ -100,6 +100,7 @@ func SettingsPost(ctx *context.Context) {
org.Description = form.Description
org.Website = form.Website
org.Location = form.Location
+ org.LocationCoordinate = form.LocationCoordinate
org.RepoAdminChangeTeamAccess = form.RepoAdminChangeTeamAccess
visibilityChanged := form.Visibility != org.Visibility
diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go
index 248743471b..8d1f4986d6 100644
--- a/routers/web/repo/issue.go
+++ b/routers/web/repo/issue.go
@@ -47,6 +47,7 @@ const (
tplAttachment base.TplName = "repo/issue/view_content/attachments"
tplIssues base.TplName = "repo/issue/list"
+ tplIssuesTree base.TplName = "repo/issue/tree"
tplIssueNew base.TplName = "repo/issue/new"
tplIssueChoose base.TplName = "repo/issue/choose"
tplIssueView base.TplName = "repo/issue/view"
@@ -114,7 +115,7 @@ func MustAllowPulls(ctx *context.Context) {
}
}
-func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption util.OptionalBool) {
+func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption util.OptionalBool, page_size int) {
var err error
viewType := ctx.FormString("type")
sortType := ctx.FormString("sort")
@@ -210,7 +211,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
} else {
total = int(issueStats.ClosedCount)
}
- pager := context.NewPagination(total, setting.UI.IssuePagingNum, page, 5)
+ pager := context.NewPagination(total, page_size, page, 5)
var mileIDs []int64
if milestoneID > 0 {
@@ -224,7 +225,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
issues, err = models.Issues(&models.IssuesOptions{
ListOptions: db.ListOptions{
Page: pager.Paginater.Current(),
- PageSize: setting.UI.IssuePagingNum,
+ PageSize: page_size,
},
RepoID: repo.ID,
AssigneeID: assigneeID,
@@ -391,7 +392,7 @@ func Issues(ctx *context.Context) {
ctx.Data["NewIssueChooseTemplate"] = len(ctx.IssueTemplatesFromDefaultBranch()) > 0
}
- issues(ctx, ctx.FormInt64("milestone"), ctx.FormInt64("project"), util.OptionalBoolOf(isPullList))
+ issues(ctx, ctx.FormInt64("milestone"), ctx.FormInt64("project"), util.OptionalBoolOf(isPullList), setting.UI.IssuePagingNum)
if ctx.Written() {
return
}
@@ -412,6 +413,47 @@ func Issues(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplIssues)
}
+// Issues Tree render issues page
+func IssuesTree(ctx *context.Context) {
+ isPullList := ctx.Params(":type") == "pulls"
+ if isPullList {
+ MustAllowPulls(ctx)
+ if ctx.Written() {
+ return
+ }
+ ctx.Data["Title"] = ctx.Tr("repo.pulls")
+ ctx.Data["PageIsPullList"] = true
+ } else {
+ MustEnableIssues(ctx)
+ if ctx.Written() {
+ return
+ }
+ ctx.Data["Title"] = ctx.Tr("repo.issues_tree")
+ ctx.Data["PageIsIssueList"] = true
+ ctx.Data["NewIssueChooseTemplate"] = len(ctx.IssueTemplatesFromDefaultBranch()) > 0
+ }
+
+ issues(ctx, ctx.FormInt64("milestone"), ctx.FormInt64("project"), util.OptionalBoolOf(isPullList), 32*1024)
+ if ctx.Written() {
+ return
+ }
+
+ var err error
+ // Get milestones
+ ctx.Data["Milestones"], _, err = models.GetMilestones(models.GetMilestonesOption{
+ RepoID: ctx.Repo.Repository.ID,
+ State: api.StateType(ctx.FormString("state")),
+ })
+ if err != nil {
+ ctx.ServerError("GetAllRepoMilestones", err)
+ return
+ }
+
+ ctx.Data["CanWriteIssuesOrPulls"] = ctx.Repo.CanWriteIssuesOrPulls(isPullList)
+
+ ctx.HTML(http.StatusOK, tplIssuesTree)
+}
+
// RetrieveRepoMilestonesAndAssignees find all the milestones and assignees of a repository
func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *repo_model.Repository) {
var err error
@@ -701,6 +743,9 @@ func RetrieveRepoMetas(ctx *context.Context, repo *repo_model.Repository, isPull
// Contains true if the user can create issue dependencies
ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx.User, isPull)
+ // Contains true if the user can create issue parents
+ ctx.Data["CanCreateIssueParents"] = ctx.Repo.CanCreateIssueParents(ctx.User, isPull)
+
return labels
}
@@ -1324,6 +1369,12 @@ func ViewIssue(ctx *context.Context) {
// check if dependencies can be created across repositories
ctx.Data["AllowCrossRepositoryDependencies"] = setting.Service.AllowCrossRepositoryDependencies
+ // Check if the user can use the parents
+ ctx.Data["CanCreateIssueParents"] = ctx.Repo.CanCreateIssueParents(ctx.User, issue.IsPull)
+
+ // check if parents can be created across repositories
+ ctx.Data["AllowCrossRepositoryParents"] = setting.Service.AllowCrossRepositoryParents
+
if issue.ShowRole, err = roleDescriptor(repo, issue.Poster, issue); err != nil {
ctx.ServerError("roleDescriptor", err)
return
@@ -1422,6 +1473,13 @@ func ViewIssue(ctx *context.Context) {
return
}
}
+ } else if comment.Type == models.CommentTypeRemoveParent || comment.Type == models.CommentTypeAddParent {
+ if err = comment.LoadParentIssueDetails(); err != nil {
+ if !models.IsErrIssueNotExist(err) {
+ ctx.ServerError("LoadParentIssueDetails", err)
+ return
+ }
+ }
} else if comment.Type == models.CommentTypeCode || comment.Type == models.CommentTypeReview || comment.Type == models.CommentTypeDismissReview {
comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,
@@ -1650,6 +1708,18 @@ func ViewIssue(ctx *context.Context) {
return
}
+ // Get Parents
+ ctx.Data["BlockedByParents"], err = issue.BlockedByParents()
+ if err != nil {
+ ctx.ServerError("BlockedByParents", err)
+ return
+ }
+ ctx.Data["BlockingParents"], err = issue.BlockingParents()
+ if err != nil {
+ ctx.ServerError("BlockingParents", err)
+ return
+ }
+
ctx.Data["Participants"] = participants
ctx.Data["NumParticipants"] = len(participants)
ctx.Data["Issue"] = issue
diff --git a/routers/web/repo/issue_parent.go b/routers/web/repo/issue_parent.go
new file mode 100644
index 0000000000..364c06efce
--- /dev/null
+++ b/routers/web/repo/issue_parent.go
@@ -0,0 +1,129 @@
+// Copyright 2018-2022 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package repo
+
+import (
+ "net/http"
+
+ "code.gitea.io/gitea/models"
+ "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/setting"
+)
+
+// AddParent adds new parents
+func AddParent(ctx *context.Context) {
+ issueIndex := ctx.ParamsInt64("index")
+ issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, issueIndex)
+ if err != nil {
+ ctx.ServerError("GetIssueByIndex", err)
+ return
+ }
+
+ // Check if the Repo is allowed to have parents
+ if !ctx.Repo.CanCreateIssueParents(ctx.User, issue.IsPull) {
+ ctx.Error(http.StatusForbidden, "CanCreateIssueParents")
+ return
+ }
+
+ parentID := ctx.FormInt64("newParent")
+
+ if err = issue.LoadRepo(); err != nil {
+ ctx.ServerError("LoadRepo", err)
+ return
+ }
+
+ // Redirect
+ defer ctx.Redirect(issue.HTMLURL(), http.StatusSeeOther)
+
+ // Parent
+ parent, err := models.GetIssueByID(parentID)
+ if err != nil {
+ ctx.Flash.Error(ctx.Tr("repo.issues.parent.add_error_dep_issue_not_exist"))
+ return
+ }
+
+ // Check if both issues are in the same repo if cross repository parents is not enabled
+ if issue.RepoID != parent.RepoID && !setting.Service.AllowCrossRepositoryParents {
+ ctx.Flash.Error(ctx.Tr("repo.issues.parent.add_error_dep_not_same_repo"))
+ return
+ }
+
+ // Check if issue and parent is the same
+ if parent.ID == issue.ID {
+ ctx.Flash.Error(ctx.Tr("repo.issues.parent.add_error_same_issue"))
+ return
+ }
+
+ err = models.CreateIssueParent(ctx.User, issue, parent)
+ if err != nil {
+ if models.IsErrParentExists(err) {
+ ctx.Flash.Error(ctx.Tr("repo.issues.parent.add_error_dep_exists"))
+ return
+ } else if models.IsErrCircularParent(err) {
+ ctx.Flash.Error(ctx.Tr("repo.issues.parent.add_error_cannot_create_circular"))
+ return
+ } else {
+ ctx.ServerError("CreateOrUpdateIssueParent", err)
+ return
+ }
+ }
+}
+
+// RemoveParent removes the parent
+func RemoveParent(ctx *context.Context) {
+ issueIndex := ctx.ParamsInt64("index")
+ issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, issueIndex)
+ if err != nil {
+ ctx.ServerError("GetIssueByIndex", err)
+ return
+ }
+
+ // Check if the Repo is allowed to have dependencies
+ if !ctx.Repo.CanCreateIssueParents(ctx.User, issue.IsPull) {
+ ctx.Error(http.StatusForbidden, "CanCreateIssueParents")
+ return
+ }
+
+ parentID := ctx.FormInt64("removeParentID")
+
+ if err = issue.LoadRepo(); err != nil {
+ ctx.ServerError("LoadRepo", err)
+ return
+ }
+
+ // Parent Type
+ parentTypeStr := ctx.Req.PostForm.Get("parentType")
+
+ var parentType models.ParentType
+
+ switch parentTypeStr {
+ case "father":
+ parentType = models.ParentTypeFather
+ case "child":
+ parentType = models.ParentTypeChild
+ default:
+ ctx.Error(http.StatusBadRequest, "GetParentType")
+ return
+ }
+
+ // Parent
+ parent, err := models.GetIssueByID(parentID)
+ if err != nil {
+ ctx.ServerError("GetIssueByID", err)
+ return
+ }
+
+ if err = models.RemoveIssueParent(ctx.User, issue, parent, parentType); err != nil {
+ if models.IsErrParentNotExists(err) {
+ ctx.Flash.Error(ctx.Tr("repo.issues.parent.add_error_dep_not_exist"))
+ return
+ }
+ ctx.ServerError("RemoveIssueParent", err)
+ return
+ }
+
+ // Redirect
+ ctx.Redirect(issue.HTMLURL(), http.StatusSeeOther)
+}
diff --git a/routers/web/repo/milestone.go b/routers/web/repo/milestone.go
index df5fd411b4..e8660392d8 100644
--- a/routers/web/repo/milestone.go
+++ b/routers/web/repo/milestone.go
@@ -289,7 +289,7 @@ func MilestoneIssuesAndPulls(ctx *context.Context) {
ctx.Data["Title"] = milestone.Name
ctx.Data["Milestone"] = milestone
- issues(ctx, milestoneID, 0, util.OptionalBoolNone)
+ issues(ctx, milestoneID, 0, util.OptionalBoolNone, setting.UI.IssuePagingNum)
ctx.Data["NewIssueChooseTemplate"] = len(ctx.IssueTemplatesFromDefaultBranch()) > 0
ctx.Data["CanWriteIssues"] = ctx.Repo.CanWriteIssuesOrPulls(false)
diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go
index f89bffb00f..f0548aaffe 100644
--- a/routers/web/repo/setting.go
+++ b/routers/web/repo/setting.go
@@ -434,6 +434,7 @@ func SettingsPost(ctx *context.Context) {
EnableTimetracker: form.EnableTimetracker,
AllowOnlyContributorsToTrackTime: form.AllowOnlyContributorsToTrackTime,
EnableDependencies: form.EnableIssueDependencies,
+ EnableParents: form.EnableIssueParents,
},
})
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalTracker)
diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go
index e98d94f7ca..da328ded45 100644
--- a/routers/web/repo/view.go
+++ b/routers/web/repo/view.go
@@ -697,6 +697,16 @@ func Home(ctx *context.Context) {
return
}
+ Wiki(ctx)
+}
+
+// Code render repository page
+func Code(ctx *context.Context) {
+ checkHomeCodeViewable(ctx)
+ if ctx.Written() {
+ return
+ }
+
renderCode(ctx)
}
diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go
index ab156b43fc..ddc5a7c47d 100644
--- a/routers/web/user/setting/profile.go
+++ b/routers/web/user/setting/profile.go
@@ -119,6 +119,7 @@ func ProfilePost(ctx *context.Context) {
ctx.User.KeepEmailPrivate = form.KeepEmailPrivate
ctx.User.Website = form.Website
ctx.User.Location = form.Location
+ ctx.User.LocationCoordinate = form.LocationCoordinate
ctx.User.Description = form.Description
ctx.User.KeepActivityPrivate = form.KeepActivityPrivate
ctx.User.Visibility = form.Visibility
diff --git a/routers/web/web.go b/routers/web/web.go
index e18ed8f8ee..aa946dd343 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -28,6 +28,7 @@ import (
"code.gitea.io/gitea/routers/web/dev"
"code.gitea.io/gitea/routers/web/events"
"code.gitea.io/gitea/routers/web/explore"
+ "code.gitea.io/gitea/routers/web/map"
"code.gitea.io/gitea/routers/web/org"
"code.gitea.io/gitea/routers/web/repo"
"code.gitea.io/gitea/routers/web/user"
@@ -254,6 +255,9 @@ func RegisterRoutes(m *web.Route) {
m.Get("/organizations", explore.Organizations)
m.Get("/code", explore.Code)
}, ignExploreSignIn)
+ m.Group("/map", func() {
+ m.Get("/umap", umap.UsersMap)
+ }, ignExploreSignIn)
m.Get("/issues", reqSignIn, user.Issues)
m.Get("/pulls", reqSignIn, user.Pulls)
m.Get("/milestones", reqSignIn, reqMilestonesDashboardPageEnabled, user.Milestones)
@@ -737,6 +741,10 @@ func RegisterRoutes(m *web.Route) {
m.Post("/add", repo.AddDependency)
m.Post("/delete", repo.RemoveDependency)
})
+ m.Group("/parent", func() {
+ m.Post("/add", repo.AddParent)
+ m.Post("/delete", repo.RemoveParent)
+ })
m.Combo("/comments").Post(repo.MustAllowUserComment, bindIgnErr(forms.CreateCommentForm{}), repo.NewComment)
m.Group("/times", func() {
m.Post("/add", bindIgnErr(forms.AddTimeManuallyForm{}), repo.AddTimeManually)
@@ -877,6 +885,7 @@ func RegisterRoutes(m *web.Route) {
m.Group("/{username}/{reponame}", func() {
m.Group("", func() {
m.Get("/{type:issues|pulls}", repo.Issues)
+ m.Get("/issues_tree", repo.IssuesTree)
m.Get("/{type:issues|pulls}/{index}", repo.ViewIssue)
m.Group("/{type:issues|pulls}/{index}/content-history", func() {
m.Get("/overview", repo.GetContentHistoryOverview)
@@ -1033,11 +1042,11 @@ func RegisterRoutes(m *web.Route) {
}, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader)
m.Group("/src", func() {
- m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.Home)
- m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.Home)
- m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.Home)
+ m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.Code)
+ m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.Code)
+ m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.Code)
// "/*" route is deprecated, and kept for backward compatibility
- m.Get("/*", context.RepoRefByType(context.RepoRefLegacy), repo.Home)
+ m.Get("/*", context.RepoRefByType(context.RepoRefLegacy), repo.Code)
}, repo.SetEditorconfigIfExists)
m.Group("", func() {
@@ -1058,6 +1067,7 @@ func RegisterRoutes(m *web.Route) {
m.Group("/{username}", func() {
m.Group("/{reponame}", func() {
m.Get("", repo.SetEditorconfigIfExists, repo.Home)
+ m.Get("/code", repo.SetEditorconfigIfExists, repo.Code)
}, ignSignIn, context.RepoAssignment, context.RepoRef(), context.UnitTypes())
m.Group("/{reponame}", func() {
diff --git a/services/forms/admin.go b/services/forms/admin.go
index 5abef0550e..8a4aaaed50 100644
--- a/services/forms/admin.go
+++ b/services/forms/admin.go
@@ -41,7 +41,9 @@ type AdminEditUserForm struct {
Email string `binding:"Required;Email;MaxSize(254)"`
Password string `binding:"MaxSize(255)"`
Website string `binding:"ValidUrl;MaxSize(255)"`
+ Description string `binding:"MaxSize(1024)"`
Location string `binding:"MaxSize(50)"`
+ LocationCoordinate string `binding:"MaxSize(255)"`
MaxRepoCreation int
Active bool
Admin bool
diff --git a/services/forms/org.go b/services/forms/org.go
index dec2dbfa65..a5a0b06d7b 100644
--- a/services/forms/org.go
+++ b/services/forms/org.go
@@ -39,9 +39,10 @@ func (f *CreateOrgForm) Validate(req *http.Request, errs binding.Errors) binding
type UpdateOrgSettingForm struct {
Name string `binding:"Required;AlphaDashDot;MaxSize(40)" locale:"org.org_name_holder"`
FullName string `binding:"MaxSize(100)"`
- Description string `binding:"MaxSize(255)"`
+ Description string `binding:"MaxSize(1024)"`
Website string `binding:"ValidUrl;MaxSize(255)"`
Location string `binding:"MaxSize(50)"`
+ LocationCoordinate string `binding:"MaxSize(255)"`
Visibility structs.VisibleType
MaxRepoCreation int
RepoAdminChangeTeamAccess bool
diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go
index e78559912e..550375bd7a 100644
--- a/services/forms/repo_form.go
+++ b/services/forms/repo_form.go
@@ -74,7 +74,7 @@ type MigrateRepoForm struct {
LFS bool `json:"lfs"`
LFSEndpoint string `json:"lfs_endpoint"`
Private bool `json:"private"`
- Description string `json:"description" binding:"MaxSize(255)"`
+ Description string `json:"description" binding:"MaxSize(1024)"`
Wiki bool `json:"wiki"`
Milestones bool `json:"milestones"`
Labels bool `json:"labels"`
@@ -155,6 +155,7 @@ type RepoSettingForm struct {
EnableTimetracker bool
AllowOnlyContributorsToTrackTime bool
EnableIssueDependencies bool
+ EnableIssueParents bool
IsArchived bool
// Signing Settings
diff --git a/services/forms/user_form.go b/services/forms/user_form.go
index a886e89f87..1ea967ca1b 100644
--- a/services/forms/user_form.go
+++ b/services/forms/user_form.go
@@ -245,7 +245,8 @@ type UpdateProfileForm struct {
KeepEmailPrivate bool
Website string `binding:"ValidSiteUrl;MaxSize(255)"`
Location string `binding:"MaxSize(50)"`
- Description string `binding:"MaxSize(255)"`
+ LocationCoordinate string `binding:"MaxSize(255)"`
+ Description string `binding:"MaxSize(1024)"`
Visibility structs.VisibleType
KeepActivityPrivate bool
}
@@ -273,7 +274,7 @@ const (
AvatarByMail string = "bymail"
)
-// AvatarForm form for changing avatar
+// AvatarForm form for changing avDescriptionatar
type AvatarForm struct {
Source string
Avatar *multipart.FileHeader
diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl
index 2a27baf535..e31fe3cae6 100644
--- a/templates/admin/config.tmpl
+++ b/templates/admin/config.tmpl
@@ -186,6 +186,8 @@
{{.i18n.Tr "admin.users.password_helper"}}
+{{$.RenderedDescription|Str2html}}
{{end}}+ {{if .Issue.IsPull}} + {{.i18n.Tr "repo.issues.parent.pr_no_parents"}} + {{else}} + {{.i18n.Tr "repo.issues.parent.issue_no_parents"}} + {{end}} +
+ {{end}} + + {{if .BlockingParents}} + + {{.i18n.Tr "repo.issues.parent.blocks_short"}} + +{{if .Issue.IsPull}} + {{.i18n.Tr "repo.issues.parent.pr_remove_text"}} + {{else}} + {{.i18n.Tr "repo.issues.parent.issue_remove_text"}} + {{end}}
+