mirror of
https://github.com/nextcloud/all-in-one.git
synced 2025-12-19 22:16:49 +00:00
aio-interface: allow to manage the community containers via the AIO interface (#6443)
Signed-off-by: Simon L. <szaimen@e.mail.de> Signed-off-by: Jean-Yves <7360784+docjyJ@users.noreply.github.com>
This commit is contained in:
parent
17ec503bf3
commit
673b1db07e
15 changed files with 220 additions and 205 deletions
|
|
@ -1,81 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<files psalm-version="6.11.0@4ed53b7ccebc09ef60ec4c9e464bf8a01bfd35b0">
|
||||
<file src="src/Auth/AuthManager.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[AuthManager]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/Auth/PasswordGenerator.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[PasswordGenerator]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/Container/AioVariables.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[AioVariables]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/Container/Container.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[Container]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/Container/ContainerEnvironmentVariables.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[ContainerEnvironmentVariables]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/Container/ContainerPort.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[ContainerPort]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/Container/ContainerPorts.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[ContainerPorts]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/Container/ContainerVolume.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[ContainerVolume]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/Container/ContainerVolumes.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[ContainerVolumes]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/ContainerDefinitionFetcher.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[ContainerDefinitionFetcher]]></code>
|
||||
</ClassMustBeFinal>
|
||||
<PossiblyFalseArgument>
|
||||
<code><![CDATA[file_get_contents($path)]]></code>
|
||||
<code><![CDATA[file_get_contents(__DIR__ . '/../containers.json')]]></code>
|
||||
</PossiblyFalseArgument>
|
||||
</file>
|
||||
<file src="src/Controller/ConfigurationController.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[ConfigurationController]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/Controller/DockerController.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[DockerController]]></code>
|
||||
</ClassMustBeFinal>
|
||||
<InvalidOperand>
|
||||
<code><![CDATA[$port]]></code>
|
||||
</InvalidOperand>
|
||||
</file>
|
||||
<file src="src/Controller/LoginController.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[LoginController]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/Data/ConfigurationManager.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[ConfigurationManager]]></code>
|
||||
</ClassMustBeFinal>
|
||||
<FalsableReturnStatement>
|
||||
<code><![CDATA[$additionalBackupDirectories]]></code>
|
||||
</FalsableReturnStatement>
|
||||
|
|
@ -98,9 +34,6 @@
|
|||
</PossiblyFalseArgument>
|
||||
</file>
|
||||
<file src="src/Data/DataConst.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[DataConst]]></code>
|
||||
</ClassMustBeFinal>
|
||||
<FalsableReturnStatement>
|
||||
<code><![CDATA[realpath(__DIR__ . '/../../../community-containers/')]]></code>
|
||||
<code><![CDATA[realpath(__DIR__ . '/../../data/')]]></code>
|
||||
|
|
@ -112,57 +45,18 @@
|
|||
<code><![CDATA[string]]></code>
|
||||
</InvalidFalsableReturnType>
|
||||
</file>
|
||||
<file src="src/Data/InvalidSettingConfigurationException.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[InvalidSettingConfigurationException]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/Data/Setup.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[Setup]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/DependencyInjection.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[DependencyInjection]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/Docker/DockerActionManager.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[DockerActionManager]]></code>
|
||||
</ClassMustBeFinal>
|
||||
<PossiblyFalseArgument>
|
||||
<code><![CDATA[$line]]></code>
|
||||
<code><![CDATA[$line]]></code>
|
||||
</PossiblyFalseArgument>
|
||||
</file>
|
||||
<file src="src/Docker/DockerHubManager.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[DockerHubManager]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/Docker/GitHubContainerRegistryManager.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[GitHubContainerRegistryManager]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/Middleware/AuthMiddleware.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[AuthMiddleware]]></code>
|
||||
</ClassMustBeFinal>
|
||||
</file>
|
||||
<file src="src/Twig/ClassExtension.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[ClassExtension]]></code>
|
||||
</ClassMustBeFinal>
|
||||
<MissingOverrideAttribute>
|
||||
<code><![CDATA[public function getFunctions() : array]]></code>
|
||||
</MissingOverrideAttribute>
|
||||
</file>
|
||||
<file src="src/Twig/CsrfExtension.php">
|
||||
<ClassMustBeFinal>
|
||||
<code><![CDATA[CsrfExtension]]></code>
|
||||
</ClassMustBeFinal>
|
||||
<MissingOverrideAttribute>
|
||||
<code><![CDATA[public function getGlobals() : array]]></code>
|
||||
</MissingOverrideAttribute>
|
||||
|
|
|
|||
|
|
@ -19,5 +19,6 @@
|
|||
<directory name="vendor" />
|
||||
</extraFiles>
|
||||
<issueHandlers>
|
||||
<ClassMustBeFinal errorLevel="suppress" />
|
||||
</issueHandlers>
|
||||
</psalm>
|
||||
|
|
|
|||
88
php/public/containers-form-submit.js
Normal file
88
php/public/containers-form-submit.js
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// Hide submit button initially
|
||||
const optionsFormSubmit = document.getElementById("options-form-submit");
|
||||
optionsFormSubmit.style.display = 'none';
|
||||
|
||||
const communityFormSubmit = document.getElementById("community-form-submit");
|
||||
communityFormSubmit.style.display = 'none';
|
||||
|
||||
// Store initial states for all checkboxes
|
||||
const initialStateOptionsContainers = {};
|
||||
const initialStateCommunityContainers = {};
|
||||
const optionsContainersCheckboxes = document.querySelectorAll("#options-form input[type='checkbox']");
|
||||
const communityContainersCheckboxes = document.querySelectorAll("#community-form input[type='checkbox']");
|
||||
|
||||
optionsContainersCheckboxes.forEach(checkbox => {
|
||||
initialStateOptionsContainers[checkbox.id] = checkbox.checked; // Use checked property to capture actual initial state
|
||||
});
|
||||
|
||||
communityContainersCheckboxes.forEach(checkbox => {
|
||||
initialStateCommunityContainers[checkbox.id] = checkbox.checked; // Use checked property to capture actual initial state
|
||||
});
|
||||
|
||||
// Function to compare current states to initial states
|
||||
function checkForOptionContainerChanges() {
|
||||
let hasChanges = false;
|
||||
|
||||
optionsContainersCheckboxes.forEach(checkbox => {
|
||||
if (checkbox.checked !== initialStateOptionsContainers[checkbox.id]) {
|
||||
hasChanges = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Show or hide submit button based on changes
|
||||
optionsFormSubmit.style.display = hasChanges ? 'block' : 'none';
|
||||
}
|
||||
|
||||
// Function to compare current states to initial states
|
||||
function checkForCommunityContainerChanges() {
|
||||
let hasChanges = false;
|
||||
|
||||
communityContainersCheckboxes.forEach(checkbox => {
|
||||
if (checkbox.checked !== initialStateCommunityContainers[checkbox.id]) {
|
||||
hasChanges = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Show or hide submit button based on changes
|
||||
communityFormSubmit.style.display = hasChanges ? 'block' : 'none';
|
||||
}
|
||||
|
||||
// Event listener to trigger visibility check on each change
|
||||
optionsContainersCheckboxes.forEach(checkbox => {
|
||||
checkbox.addEventListener("change", checkForOptionContainerChanges);
|
||||
});
|
||||
|
||||
communityContainersCheckboxes.forEach(checkbox => {
|
||||
checkbox.addEventListener("change", checkForCommunityContainerChanges);
|
||||
});
|
||||
|
||||
// Custom behaviors for specific options
|
||||
function handleTalkVisibility() {
|
||||
const talkRecording = document.getElementById("talk-recording");
|
||||
if (document.getElementById("talk").checked) {
|
||||
talkRecording.disabled = false;
|
||||
} else {
|
||||
talkRecording.checked = false;
|
||||
talkRecording.disabled = true;
|
||||
}
|
||||
checkForOptionContainerChanges(); // Check changes after toggling Talk Recording
|
||||
}
|
||||
|
||||
function handleDockerSocketProxyWarning() {
|
||||
if (document.getElementById("docker-socket-proxy").checked) {
|
||||
alert('⚠️ Warning! Enabling this container comes with possible Security problems since you are exposing the docker socket and all its privileges to the Nextcloud container. Enable this only if you are sure what you are doing!');
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize event listeners for specific behaviors
|
||||
document.getElementById("talk").addEventListener('change', handleTalkVisibility);
|
||||
document.getElementById("docker-socket-proxy").addEventListener('change', handleDockerSocketProxyWarning);
|
||||
|
||||
// Initialize talk-recording visibility on page load
|
||||
handleTalkVisibility(); // Ensure talk-recording is correctly initialized
|
||||
|
||||
// Initial call to check for changes
|
||||
checkForOptionContainerChanges();
|
||||
checkForCommunityContainerChanges();
|
||||
});
|
||||
|
|
@ -128,7 +128,9 @@ $app->get('/containers', function (Request $request, Response $response, array $
|
|||
'is_nvidia_gpu_enabled' => $configurationManager->isNvidiaGpuEnabled(),
|
||||
'is_talk_recording_enabled' => $configurationManager->isTalkRecordingEnabled(),
|
||||
'is_docker_socket_proxy_enabled' => $configurationManager->isDockerSocketProxyEnabled(),
|
||||
'is_whiteboard_enabled' => $configurationManager->isWhiteboardEnabled(),
|
||||
'is_whiteboard_enabled' => $configurationManager->isWhiteboardEnabled(),
|
||||
'community_containers' => $configurationManager->listAvailableCommunityContainers(),
|
||||
'community_containers_enabled' => $configurationManager->GetEnabledCommunityContainers(),
|
||||
]);
|
||||
})->setName('profile');
|
||||
$app->get('/login', function (Request $request, Response $response, array $args) use ($container) {
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// Hide submit button initially
|
||||
const optionsFormSubmit = document.getElementById("options-form-submit");
|
||||
optionsFormSubmit.style.display = 'none';
|
||||
|
||||
// Store initial states for all checkboxes
|
||||
const initialState = {};
|
||||
const checkboxes = document.querySelectorAll("#options-form input[type='checkbox']");
|
||||
|
||||
checkboxes.forEach(checkbox => {
|
||||
initialState[checkbox.id] = checkbox.checked; // Use checked property to capture actual initial state
|
||||
});
|
||||
|
||||
// Function to compare current states to initial states
|
||||
function checkForChanges() {
|
||||
let hasChanges = false;
|
||||
|
||||
checkboxes.forEach(checkbox => {
|
||||
if (checkbox.checked !== initialState[checkbox.id]) {
|
||||
hasChanges = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Show or hide submit button based on changes
|
||||
optionsFormSubmit.style.display = hasChanges ? 'block' : 'none';
|
||||
}
|
||||
|
||||
// Event listener to trigger visibility check on each change
|
||||
checkboxes.forEach(checkbox => {
|
||||
checkbox.addEventListener("change", checkForChanges);
|
||||
});
|
||||
|
||||
// Custom behaviors for specific options
|
||||
function handleTalkVisibility() {
|
||||
const talkRecording = document.getElementById("talk-recording");
|
||||
if (document.getElementById("talk").checked) {
|
||||
talkRecording.disabled = false;
|
||||
} else {
|
||||
talkRecording.checked = false;
|
||||
talkRecording.disabled = true;
|
||||
}
|
||||
checkForChanges(); // Check changes after toggling Talk Recording
|
||||
}
|
||||
|
||||
function handleDockerSocketProxyWarning() {
|
||||
if (document.getElementById("docker-socket-proxy").checked) {
|
||||
alert('⚠️ Warning! Enabling this container comes with possible Security problems since you are exposing the docker socket and all its privileges to the Nextcloud container. Enable this only if you are sure what you are doing!');
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize event listeners for specific behaviors
|
||||
document.getElementById("talk").addEventListener('change', handleTalkVisibility);
|
||||
document.getElementById("docker-socket-proxy").addEventListener('change', handleDockerSocketProxyWarning);
|
||||
|
||||
// Initialize talk-recording visibility on page load
|
||||
handleTalkVisibility(); // Ensure talk-recording is correctly initialized
|
||||
|
||||
// Initial call to check for changes
|
||||
checkForChanges();
|
||||
});
|
||||
12
php/src/Container/CommunityContainer.php
Normal file
12
php/src/Container/CommunityContainer.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace AIO\Container;
|
||||
|
||||
readonly class CommunityContainer {
|
||||
public function __construct(
|
||||
string $id,
|
||||
string $name,
|
||||
string $documentation,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ readonly class ConfigurationController {
|
|||
) {
|
||||
}
|
||||
|
||||
public function SetConfig(Request $request, Response $response, array $args) : Response {
|
||||
public function SetConfig(Request $request, Response $response, array $args): Response {
|
||||
try {
|
||||
if (isset($request->getParsedBody()['domain'])) {
|
||||
$domain = $request->getParsedBody()['domain'] ?? '';
|
||||
|
|
@ -125,6 +125,10 @@ readonly class ConfigurationController {
|
|||
}
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['community-form'])) {
|
||||
$this->configurationManager->SetEnabledCommunityContainers($request->getParsedBody()['enabled-community'] ?? []);
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['delete_collabora_dictionaries'])) {
|
||||
$this->configurationManager->DeleteCollaboraDictionaries();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace AIO\Data;
|
||||
|
||||
use AIO\Auth\PasswordGenerator;
|
||||
use AIO\Container\CommunityContainer;
|
||||
use AIO\Controller\DockerController;
|
||||
|
||||
class ConfigurationManager
|
||||
|
|
@ -75,7 +76,7 @@ class ConfigurationManager
|
|||
if (!file_exists(DataConst::GetBackupArchivesList())) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
$content = file_get_contents(DataConst::GetBackupArchivesList());
|
||||
if ($content === '') {
|
||||
return '';
|
||||
|
|
@ -95,7 +96,7 @@ class ConfigurationManager
|
|||
if ($lastBackupTime === "") {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
return $lastBackupTime;
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +104,7 @@ class ConfigurationManager
|
|||
if (!file_exists(DataConst::GetBackupArchivesList())) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
$content = file_get_contents(DataConst::GetBackupArchivesList());
|
||||
if ($content === '') {
|
||||
return [];
|
||||
|
|
@ -114,7 +115,7 @@ class ConfigurationManager
|
|||
foreach($backupLines as $lines) {
|
||||
if ($lines !== "") {
|
||||
$backupTimesTemp = explode(',', $lines);
|
||||
$backupTimes[] = $backupTimesTemp[1];
|
||||
$backupTimes[] = $backupTimesTemp[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -140,7 +141,7 @@ class ConfigurationManager
|
|||
}
|
||||
}
|
||||
|
||||
public function isClamavEnabled() : bool {
|
||||
public function isClamavEnabled() : bool {
|
||||
$config = $this->GetConfig();
|
||||
if (isset($config['isClamavEnabled']) && $config['isClamavEnabled'] === 1) {
|
||||
return true;
|
||||
|
|
@ -375,7 +376,7 @@ class ConfigurationManager
|
|||
$testUrl = $protocol . $domain . ':443';
|
||||
curl_setopt($ch, CURLOPT_URL, $testUrl);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||||
$response = (string)curl_exec($ch);
|
||||
# Get rid of trailing \n
|
||||
|
|
@ -474,7 +475,7 @@ class ConfigurationManager
|
|||
} elseif ($location !== '' && $repo !== '') {
|
||||
throw new InvalidSettingConfigurationException("Location and remote repo url are mutually exclusive!");
|
||||
}
|
||||
|
||||
|
||||
if ($location !== '') {
|
||||
$isValidPath = false;
|
||||
if (str_starts_with($location, '/') && !str_ends_with($location, '/')) {
|
||||
|
|
@ -629,7 +630,7 @@ class ConfigurationManager
|
|||
if (!file_exists(DataConst::GetBackupPublicKey())) {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
return trim(file_get_contents(DataConst::GetBackupPublicKey()));
|
||||
}
|
||||
|
||||
|
|
@ -771,7 +772,7 @@ class ConfigurationManager
|
|||
if (!preg_match("#^[0-1][0-9]:[0-5][0-9]$#", $time) && !preg_match("#^2[0-3]:[0-5][0-9]$#", $time)) {
|
||||
throw new InvalidSettingConfigurationException("You did not enter a correct time! One correct example is '04:00'!");
|
||||
}
|
||||
|
||||
|
||||
if ($enableAutomaticUpdates === false) {
|
||||
$time .= PHP_EOL . 'automaticUpdatesAreNotEnabled';
|
||||
} else {
|
||||
|
|
@ -1008,16 +1009,59 @@ class ConfigurationManager
|
|||
}
|
||||
|
||||
private function GetCommunityContainers() : string {
|
||||
$envVariableName = 'AIO_COMMUNITY_CONTAINERS';
|
||||
$configName = 'aio_community_containers';
|
||||
$defaultValue = '';
|
||||
return $this->GetEnvironmentalVariableOrConfig($envVariableName, $configName, $defaultValue);
|
||||
$config = $this->GetConfig();
|
||||
if(!isset($config['aio_community_containers'])) {
|
||||
$config['aio_community_containers'] = '';
|
||||
}
|
||||
|
||||
return $config['aio_community_containers'];
|
||||
}
|
||||
|
||||
public function GetEnabledCommunityContainers() : array {
|
||||
|
||||
/** @return list<CommunityContainer> */
|
||||
public function listAvailableCommunityContainers() : array {
|
||||
$cc = [];
|
||||
$dir = scandir(DataConst::GetCommunityContainersDirectory());
|
||||
if ($dir === false) {
|
||||
return $cc;
|
||||
}
|
||||
foreach ($dir as $id) {
|
||||
$filePath = DataConst::GetCommunityContainersDirectory() . '/' . $id . '/' . $id . '.json';
|
||||
$fileContents = apcu_fetch($filePath);
|
||||
if (!is_string($fileContents)) {
|
||||
$fileContents = file_get_contents($filePath);
|
||||
if (is_string($fileContents)) {
|
||||
apcu_add($filePath, $fileContents);
|
||||
}
|
||||
}
|
||||
$json = is_string($fileContents) ? json_decode($fileContents) : false;
|
||||
if(is_array($json) && is_array($json['aio_services_v1'])) {
|
||||
foreach ($json['aio_services_v1'] as $service) {
|
||||
$documentation = is_string($service['documentation']) ? $service['documentation'] : '';
|
||||
if (is_string($service['display_name'])) {
|
||||
$cc[] = new CommunityContainer(
|
||||
$id,
|
||||
$service['display_name'],
|
||||
$documentation);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $cc;
|
||||
}
|
||||
|
||||
/** @return list<string> */
|
||||
public function GetEnabledCommunityContainers(): array {
|
||||
return explode(' ', $this->GetCommunityContainers());
|
||||
}
|
||||
|
||||
public function SetEnabledCommunityContainers(array $enabledCommunityContainers) : void {
|
||||
$config = $this->GetConfig();
|
||||
$config['aio_community_containers'] = implode(' ', $enabledCommunityContainers);
|
||||
$this->WriteConfig($config);
|
||||
}
|
||||
|
||||
private function GetEnabledDriDevice() : string {
|
||||
$envVariableName = 'NEXTCLOUD_ENABLE_DRI_DEVICE';
|
||||
$configName = 'nextcloud_enable_dri_device';
|
||||
|
|
|
|||
|
|
@ -606,6 +606,10 @@
|
|||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{{ include('includes/community-containers.twig') }}
|
||||
|
||||
<script type="text/javascript" src="containers-form-submit.js?v4"></script>
|
||||
|
||||
{% if isApacheStarting == true or is_backup_container_running == true or isWatchtowerRunning == true or is_daily_backup_running == true %}
|
||||
<script type="text/javascript" src="automatic_reload.js"></script>
|
||||
{% else %}
|
||||
|
|
|
|||
42
php/templates/includes/community-containers.twig
Normal file
42
php/templates/includes/community-containers.twig
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<h2>Community Containers</h2>
|
||||
<p>In this section you can enable or disable optional Community Containers that are not included by default in the main installation. These containers are provided by the community and can be useful for various purposes and are automatically integrated in AIOs backup solution and update mechanisms.</p>
|
||||
<p><strong>⚠️ Caution: </strong>Community Containers are maintained by the community and not officially by Nextcloud. Some containers may not be compatible with your system, may not work as expected or may discontinue. Use them at your own risk. Please read the documentation for each container first before adding any as some are also incompatible between each other! Never add all of them at the same time!</p>
|
||||
<details>
|
||||
<summary>Show/Hide available Community Containers</summary>
|
||||
{% if isAnyRunning == true %}
|
||||
<p><strong>Please note:</strong> You can enable or disable the options below only when your containers are stopped.</p>
|
||||
{% else %}
|
||||
<p><strong>Please note:</strong> Make sure to save your changes by clicking <strong>Save changes</strong> below the list of Community Containers. The changes will not be auto-saved.</p>
|
||||
{% endif %}
|
||||
<form id="community-form" method="POST" action="/api/configuration" class="xhr">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="hidden" name="community-form" value="community-form">
|
||||
{% for cc in community_containers %}
|
||||
<p>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="enabled-community[]"
|
||||
value="{{ cc.id }}"
|
||||
name="{{ cc.id }}"
|
||||
{% if cc.id in community_containers_enabled %}
|
||||
checked="checked"
|
||||
data-initial-state="true"
|
||||
{% else %}
|
||||
data-initial-state="false"
|
||||
{% endif %}
|
||||
{% if isAnyRunning == true %}
|
||||
disabled="disabled"
|
||||
{% endif %}
|
||||
>
|
||||
<label for="{{ cc.id }}">{{ cc.name }}
|
||||
{% if cc.documentation != '' %}
|
||||
<a href="{{ cc.documentation }}" target="_blank">(Documentation)</a>
|
||||
{% endif %}
|
||||
</label>
|
||||
</p>
|
||||
{% endfor %}
|
||||
|
||||
<input id="community-form-submit" type="submit" value="Save changes" onclick="return confirm('Are you sure that you read the documentation of all community containers that you enabled? If no, please do not continue as this might break your instance!')" />
|
||||
</form>
|
||||
</details>
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
<h2>Optional containers</h2>
|
||||
<p>In this section you can enable or disable optional containers. There are further community containers available that are not listed below. See <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/tree/main/community-containers#community-containers">this documentation</a></strong> how to add them.</p>
|
||||
<p>In this section you can enable or disable optional containers.</p>
|
||||
{% if isAnyRunning == true %}
|
||||
<p><strong>Please note:</strong> You can enable or disable the options below only when your containers are stopped.</p>
|
||||
{% else %}
|
||||
<p><strong>Please note:</strong> Make sure to save your changes by clicking <strong>Save changes</strong> below the list of optional containers. The changes will not be auto-saved.</p>
|
||||
{% endif %}
|
||||
<form id="options-form" method="POST" action="/api/configuration" class="xhr">
|
||||
<form id="container-form" method="POST" action="/api/configuration" class="xhr">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="hidden" name="options-form" value="options-form">
|
||||
|
|
@ -143,7 +143,6 @@
|
|||
<label for="whiteboard">Whiteboard</label>
|
||||
</p>
|
||||
<input id="options-form-submit" type="submit" value="Save changes" />
|
||||
<script type="text/javascript" src="options-form-submit.js?v3"></script>
|
||||
</form>
|
||||
<p><strong>Minimal system requirements:</strong> When any optional container is enabled, at least 2GB RAM, a dual-core CPU and 40GB system storage are required. When enabling ClamAV, Nextcloud Talk Recording-server or Fulltextsearch, at least 3GB RAM are required. For Talk Recording-server additional 2 vCPUs are required. When enabling everything, at least 5GB RAM and a quad-core CPU are required. Recommended are at least 1GB more RAM than the minimal requirement. For further advice and recommendations see <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/1335">this documentation</a></strong></p>
|
||||
{% if isAnyRunning == true %}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue