|
@@ -6,80 +6,198 @@ import (
|
|
|
componentForm "github.com/speedianet/os/src/presentation/ui/component/form"
|
|
|
componentStructural "github.com/speedianet/os/src/presentation/ui/component/structural"
|
|
|
presenterDto "github.com/speedianet/os/src/presentation/ui/presenter/dto"
|
|
|
+ "strconv"
|
|
|
)
|
|
|
|
|
|
-script PhpRuntimeHorizontalTabContentLocalState(defaultVhostHostname string) {
|
|
|
+script PhpRuntimeHorizontalTabContentLocalState() {
|
|
|
document.addEventListener('alpine:init', () => {
|
|
|
Alpine.data('php', () => ({
|
|
|
- // Primary states
|
|
|
+ // Primary States
|
|
|
phpConfigs: {},
|
|
|
- get phpModulesAsApiFormat() {
|
|
|
- const modulesAsObjectsArray = []
|
|
|
- for (const moduleName of Object.keys(this.phpConfigs.modules)) {
|
|
|
- modulesAsObjectsArray.push({
|
|
|
- name: moduleName,
|
|
|
- status: this.phpConfigs.modules[moduleName]
|
|
|
- });
|
|
|
+ resetPrimaryStates() {
|
|
|
+ phpConfigsElement = document.getElementById('phpConfigs');
|
|
|
+ if (!phpConfigsElement) {
|
|
|
+ return;
|
|
|
}
|
|
|
- return modulesAsObjectsArray;
|
|
|
- },
|
|
|
- get phpSettingsAsApiFormat() {
|
|
|
- const settingsAsObjectsArray = []
|
|
|
- for (const settingName of Object.keys(this.phpConfigs.settings)) {
|
|
|
- settingsAsObjectsArray.push({
|
|
|
- name: settingName,
|
|
|
- value: this.phpConfigs.settings[settingName]
|
|
|
- });
|
|
|
- }
|
|
|
- return settingsAsObjectsArray;
|
|
|
+ this.phpConfigs = JSON.parse(phpConfigsElement.textContent);
|
|
|
},
|
|
|
init() {
|
|
|
- this.phpConfigs = {
|
|
|
- vhostHostname: defaultVhostHostname,
|
|
|
- version: document.getElementById('phpVersion').textContent,
|
|
|
- modules: Object.fromEntries(
|
|
|
- JSON.parse(
|
|
|
- document.getElementById('phpModulesCheckInputsSwitchToggles').textContent
|
|
|
- ).map(item => [item.name, item.status])
|
|
|
- ),
|
|
|
- settings: Object.fromEntries(
|
|
|
- JSON.parse(
|
|
|
- document.getElementById('phpSettingsInputs').textContent
|
|
|
- ).map(item => [item.name, item.value])
|
|
|
- ),
|
|
|
- };
|
|
|
+ this.resetPrimaryStates();
|
|
|
+ },
|
|
|
+ async updatePhpConfigs() {
|
|
|
+ await jsonAjax(
|
|
|
+ 'PUT', '/api/v1/runtime/php/' + this.vhostHostname + '/',
|
|
|
+ {
|
|
|
+ version: this.phpConfigs.version.value,
|
|
|
+ modules: this.phpConfigs.modules,
|
|
|
+ settings: this.phpConfigs.settings,
|
|
|
+ },
|
|
|
+ );
|
|
|
},
|
|
|
|
|
|
- // Auxiliary states
|
|
|
+ // Auxiliary States
|
|
|
selectedPhpVerticalTab: 'modules',
|
|
|
updateSelectedPhpVerticalTab(tabName) {
|
|
|
this.selectedPhpVerticalTab = tabName;
|
|
|
},
|
|
|
|
|
|
- // Modal states
|
|
|
+ // Modal States
|
|
|
isUpdatePhpVersionModalOpen: false,
|
|
|
- openUpdatePhpVersionModal(phpVersion) {
|
|
|
- this.phpConfigs.version = phpVersion;
|
|
|
+ openUpdatePhpVersionModal() {
|
|
|
this.isUpdatePhpVersionModalOpen = true;
|
|
|
},
|
|
|
closeUpdatePhpVersionModal() {
|
|
|
this.isUpdatePhpVersionModalOpen = false;
|
|
|
},
|
|
|
- updateVersion() {
|
|
|
+ updatePhpVersion() {
|
|
|
+ this.closeUpdatePhpVersionModal();
|
|
|
htmx.ajax(
|
|
|
- 'PUT',
|
|
|
- '/api/v1/runtime/php/' + this.phpConfigs.vhostHostname + '/',
|
|
|
+ 'PUT', '/api/v1/runtime/php/' + this.vhostHostname + '/',
|
|
|
{
|
|
|
swap: 'none',
|
|
|
- values: { version: this.phpConfigs.version },
|
|
|
+ values: { version: this.phpConfigs.version.value },
|
|
|
},
|
|
|
- );
|
|
|
- this.closeUpdatePhpVersionModal();
|
|
|
+ ).then(() => {
|
|
|
+ this.$dispatch('refresh:runtimes-page-content');
|
|
|
+ });
|
|
|
},
|
|
|
}));
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+templ PhpRuntimeHorizontalTabContent(
|
|
|
+ runtimeOverview presenterDto.RuntimeOverview,
|
|
|
+ vhostsHostnames []string,
|
|
|
+) {
|
|
|
+ <!-- PhpRuntimeHorizontalTabContent JavaScript -->
|
|
|
+ @PhpRuntimeHorizontalTabContentLocalState()
|
|
|
+ <!-- PhpRuntimeHorizontalTabContent HTML -->
|
|
|
+ <div class="bg-os-800 -mt-4 rounded-b-xl rounded-r-xl p-4" x-data="php">
|
|
|
+ <div class="bg-os-500 rounded-b-lg rounded-r-lg p-6">
|
|
|
+ if runtimeOverview.IsInstalled {
|
|
|
+ <div class="lg:max-w-1/3">
|
|
|
+ @componentForm.SelectInput(
|
|
|
+ "virtualHost", "Virtual Host Hostname", "vhostHostname",
|
|
|
+ "updateSelectedVhostHostname(vhostHostname)",
|
|
|
+ vhostsHostnames, false,
|
|
|
+ )
|
|
|
+ </div>
|
|
|
+ if runtimeOverview.IsVirtualHostUsingRuntime {
|
|
|
+ @FunctionalPhpRuntimeContent(runtimeOverview, vhostsHostnames)
|
|
|
+ @UpdatePhpVersionModal()
|
|
|
+ } else {
|
|
|
+ @CreatePhpMappingForm(runtimeOverview.VirtualHostHostname)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ @componentStructural.ServiceNotInstalledWarningForm("php")
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+}
|
|
|
+
|
|
|
+templ PhpModulesCheckboxInputsSwitchToggles(phpConfigs *entity.PhpConfigs) {
|
|
|
+ <!-- PhpModulesCheckboxInputsSwitchToggles -->
|
|
|
+ <div
|
|
|
+ x-show="selectedPhpVerticalTab == 'modules'"
|
|
|
+ class="gap-7.5 grid grid-cols-5 lg:grid-cols-6"
|
|
|
+ >
|
|
|
+ // Using the index as the key is not recommended, but in this case, the entities
|
|
|
+ // list used here is the exact same as the one that will be on Alpine.js, so
|
|
|
+ // the position of the entities will also be the same. Since we need Alpine to
|
|
|
+ // control the state of the checkboxes, we have to use the index as the key.
|
|
|
+ for moduleIndex, moduleEntity := range phpConfigs.Modules {
|
|
|
+ @componentForm.CheckboxInputSwitchToggle(
|
|
|
+ "", moduleEntity.Name.String(),
|
|
|
+ "phpConfigs.modules["+strconv.FormatInt(int64(moduleIndex), 10)+"].status",
|
|
|
+ "",
|
|
|
+ )
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+}
|
|
|
+
|
|
|
+func transformPhpSettingsOptionsIntoStringSlice(
|
|
|
+ options []valueObject.PhpSettingOption,
|
|
|
+) []string {
|
|
|
+ optionsStrSlice := []string{}
|
|
|
+ for _, phpOption := range options {
|
|
|
+ optionsStrSlice = append(optionsStrSlice, phpOption.String())
|
|
|
+ }
|
|
|
+
|
|
|
+ return optionsStrSlice
|
|
|
+}
|
|
|
+
|
|
|
+templ PhpSettingsInputs(phpConfigs *entity.PhpConfigs) {
|
|
|
+ <!-- PhpSettingsInputs -->
|
|
|
+ <div
|
|
|
+ x-show="selectedPhpVerticalTab == 'settings'"
|
|
|
+ class="grid grid-cols-3 gap-7"
|
|
|
+ >
|
|
|
+ for settingIndex, settingEntity := range phpConfigs.Settings {
|
|
|
+ if settingEntity.Type.String() == "text" {
|
|
|
+ @componentForm.InputField(
|
|
|
+ settingEntity.Value.GetType(), "", settingEntity.Name.String(),
|
|
|
+ "phpConfigs.settings["+strconv.FormatInt(int64(settingIndex), 10)+"].value",
|
|
|
+ false,
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ @componentForm.SelectInput(
|
|
|
+ "", settingEntity.Name.String(),
|
|
|
+ "phpConfigs.settings["+strconv.FormatInt(int64(settingIndex), 10)+"].value",
|
|
|
+ "", transformPhpSettingsOptionsIntoStringSlice(settingEntity.Options), false,
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+}
|
|
|
+
|
|
|
+func transformPhpVersionOptionsIntoStringSlice(
|
|
|
+ versionOptions []valueObject.PhpVersion,
|
|
|
+) []string {
|
|
|
+ versionOptionsStrSlice := []string{}
|
|
|
+ for _, versionOption := range versionOptions {
|
|
|
+ versionOptionsStrSlice = append(versionOptionsStrSlice, versionOption.String())
|
|
|
+ }
|
|
|
+
|
|
|
+ return versionOptionsStrSlice
|
|
|
+}
|
|
|
+
|
|
|
+templ FunctionalPhpRuntimeContent(
|
|
|
+ runtimeOverview presenterDto.RuntimeOverview,
|
|
|
+ vhostsHostnames []string,
|
|
|
+) {
|
|
|
+ <!-- FunctionalPhpRuntimeContent JavaScript -->
|
|
|
+ @templ.JSONScript("phpConfigs", runtimeOverview.PhpConfigs)
|
|
|
+ <!-- FunctionalPhpRuntimeContent HTML -->
|
|
|
+ <div class="mt-6">
|
|
|
+ <div class="lg:max-w-1/3">
|
|
|
+ @componentForm.SelectInput(
|
|
|
+ "version", "Version", "phpConfigs.version.value",
|
|
|
+ "openUpdatePhpVersionModal()",
|
|
|
+ transformPhpVersionOptionsIntoStringSlice(runtimeOverview.PhpConfigs.Version.Options),
|
|
|
+ false,
|
|
|
+ )
|
|
|
+ </div>
|
|
|
+ <div class="mt-6 flex justify-stretch">
|
|
|
+ @componentStructural.VerticalTabHeader(
|
|
|
+ []componentStructural.VerticalTabHeaderItem{
|
|
|
+ {Label: "Modules", Icon: "ph-puzzle-piece", ComponentValue: "modules"},
|
|
|
+ {Label: "Settings", Icon: "ph-gear", ComponentValue: "settings"},
|
|
|
+ }, "updateSelectedPhpVerticalTab",
|
|
|
+ )
|
|
|
+ <div id="php-vertical-tab-content" class="w-full p-8">
|
|
|
+ @PhpModulesCheckboxInputsSwitchToggles(runtimeOverview.PhpConfigs)
|
|
|
+ @PhpSettingsInputs(runtimeOverview.PhpConfigs)
|
|
|
+ <div class="max-w-1/3 mt-12">
|
|
|
+ @componentForm.SubmitButton(
|
|
|
+ "apply-php-runtime-configs-changes", "Apply changes",
|
|
|
+ "ph-check-fat", "updatePhpConfigs()", false,
|
|
|
+ )
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+}
|
|
|
+
|
|
|
templ CreatePhpMappingForm(selectedVhostHostname valueObject.Fqdn) {
|
|
|
<!-- CreatePhpMappingForm -->
|
|
|
<form
|
|
@@ -87,6 +205,7 @@ templ CreatePhpMappingForm(selectedVhostHostname valueObject.Fqdn) {
|
|
|
hx-post="/api/v1/vhosts/mapping/"
|
|
|
hx-indicator="#loading-overlay"
|
|
|
hx-swap="none"
|
|
|
+ class="mt-4 p-4"
|
|
|
>
|
|
|
<h1 class="flex text-3xl">The Selected Virtual Host Doesn't Map to PHP Yet</h1>
|
|
|
<p class="mt-2 text-justify">
|
|
@@ -123,177 +242,21 @@ templ CreatePhpMappingForm(selectedVhostHostname valueObject.Fqdn) {
|
|
|
</form>
|
|
|
}
|
|
|
|
|
|
-func transformPhpVersionOptionsIntoStringSlice(
|
|
|
- versionOptions []valueObject.PhpVersion,
|
|
|
-) []string {
|
|
|
- versionOptionsStrSlice := []string{}
|
|
|
- for _, versionOption := range versionOptions {
|
|
|
- versionOptionsStrSlice = append(versionOptionsStrSlice, versionOption.String())
|
|
|
- }
|
|
|
-
|
|
|
- return versionOptionsStrSlice
|
|
|
-}
|
|
|
-
|
|
|
-templ PhpModulesCheckboxInputsSwitchToggles(
|
|
|
- selectedPhpVersion entity.PhpVersion,
|
|
|
- modules []entity.PhpModule,
|
|
|
-) {
|
|
|
- <!-- PhpModulesCheckboxInputsSwitchToggles JavaScript -->
|
|
|
- @templ.JSONScript("phpModulesCheckInputsSwitchToggles", modules)
|
|
|
- <!-- PhpModulesCheckboxInputsSwitchToggles HTML -->
|
|
|
- <div
|
|
|
- x-show="selectedPhpVerticalTab == 'modules'"
|
|
|
- class="grid grid-cols-9 gap-10"
|
|
|
- >
|
|
|
- for _, module := range modules {
|
|
|
- @componentForm.CheckboxInputSwitchToggle(
|
|
|
- "", module.Name.String(),
|
|
|
- "phpConfigs.modules['"+module.Name.String()+"']", "",
|
|
|
- )
|
|
|
- }
|
|
|
- </div>
|
|
|
- <input name="modules" type="hidden" x-bind:value="phpModulesAsApiFormat"/>
|
|
|
-}
|
|
|
-
|
|
|
-func transformPhpSettingsOptionsIntoStringSlice(
|
|
|
- options []valueObject.PhpSettingOption,
|
|
|
-) []string {
|
|
|
- optionsStrSlice := []string{}
|
|
|
- for _, phpOption := range options {
|
|
|
- optionsStrSlice = append(optionsStrSlice, phpOption.String())
|
|
|
- }
|
|
|
-
|
|
|
- return optionsStrSlice
|
|
|
-}
|
|
|
-
|
|
|
-templ PhpSettingsInputs(
|
|
|
- selectedPhpVersion entity.PhpVersion,
|
|
|
- settings []entity.PhpSetting,
|
|
|
-) {
|
|
|
- <!-- PhpSettingsInputs JavaScript -->
|
|
|
- @templ.JSONScript("phpSettingsInputs", settings)
|
|
|
- <!-- PhpSettingsInputs HTML -->
|
|
|
- <div
|
|
|
- x-show="selectedPhpVerticalTab == 'settings'"
|
|
|
- class="grid grid-cols-4 gap-7"
|
|
|
- >
|
|
|
- for _, setting := range settings {
|
|
|
- if setting.Type.String() == "text" {
|
|
|
- @componentForm.InputField(
|
|
|
- setting.Value.GetType(), "",
|
|
|
- setting.Name.String(),
|
|
|
- "phpConfigs.settings['"+setting.Name.String()+"']",
|
|
|
- false,
|
|
|
- )
|
|
|
- } else {
|
|
|
- @componentForm.SelectInput(
|
|
|
- "", setting.Name.String(),
|
|
|
- "phpConfigs.settings['"+setting.Name.String()+"']", "",
|
|
|
- transformPhpSettingsOptionsIntoStringSlice(setting.Options),
|
|
|
- false,
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- </div>
|
|
|
- <input name="settings" type="hidden" x-bind:value="phpSettingsAsApiFormat"/>
|
|
|
-}
|
|
|
-
|
|
|
templ UpdatePhpVersionWarningContent() {
|
|
|
<h3 class="text-pretty mb-3 text-xl font-bold leading-relaxed">
|
|
|
Do you really want to change the PHP version?
|
|
|
</h3>
|
|
|
- <strong>Before changing, make sure your application is compatible with PHP version <span x-text="phpConfigs.version"></span>.</strong>
|
|
|
- <p>Remember to then enable/disable the desired modules and adjust the settings in the new version, since the modules/settings of the previous version may be different.</p>
|
|
|
+ <p class="font-bold">Make sure your application is compatible with PHP <span x-text="phpConfigs.version.value"></span> before proceeding.</p>
|
|
|
+ <p class="mt-4 text-sm">You must also remember to enable/disable any modules and adjust the settings in the new version, as the modules/settings of the previous version will not be automatically transferred.</p>
|
|
|
}
|
|
|
|
|
|
templ UpdatePhpVersionModal() {
|
|
|
<!-- UpdatePhpVersionModal -->
|
|
|
@componentStructural.WarningModal(
|
|
|
"isUpdatePhpVersionModalOpen", "closeUpdatePhpVersionModal()",
|
|
|
- "Cancel", "updateVersion()",
|
|
|
+ "Cancel", "updatePhpVersion()",
|
|
|
"update-version-button", "ph-swap", "Yes, change version",
|
|
|
) {
|
|
|
@UpdatePhpVersionWarningContent()
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-templ InstalledPhpRuntimeContent(
|
|
|
- runtimeOverview presenterDto.RuntimeOverview,
|
|
|
- vhostsHostnames []string,
|
|
|
-) {
|
|
|
- <div class="p-4">
|
|
|
- <div class="float-left w-1/5">
|
|
|
- @componentForm.SelectInput(
|
|
|
- "virtualHost", "Virtual Host Hostname",
|
|
|
- "phpConfigs.vhostHostname",
|
|
|
- "const vhostHostname = $event.target.value; updateSelectedVhostHostname(vhostHostname)",
|
|
|
- vhostsHostnames, false,
|
|
|
- )
|
|
|
- </div>
|
|
|
- if runtimeOverview.CanVirtualHostHostnameAccessRuntime {
|
|
|
- <form
|
|
|
- id="update-php-runtime-configs-form"
|
|
|
- hx-put={ "/api/v1/runtime/php/" + runtimeOverview.VirtualHostHostname.String() + "/" }
|
|
|
- hx-ext="encoding-request-as-json"
|
|
|
- hx-swap="none"
|
|
|
- >
|
|
|
- <div class="w-1/7 flex pl-5">
|
|
|
- <p id="phpVersion" class="hidden">{ runtimeOverview.PhpConfigs.Version.Value.String() }</p>
|
|
|
- @componentForm.SelectInput(
|
|
|
- "version", "Version", "phpConfigs.version",
|
|
|
- "const phpVersion = $event.target.value; openUpdatePhpVersionModal(phpVersion)",
|
|
|
- transformPhpVersionOptionsIntoStringSlice(runtimeOverview.PhpConfigs.Version.Options),
|
|
|
- false,
|
|
|
- )
|
|
|
- </div>
|
|
|
- <div class="mt-6 flex">
|
|
|
- @componentStructural.VerticalTabHeader(
|
|
|
- []componentStructural.VerticalTabHeaderItem{
|
|
|
- {Label: "Modules", Icon: "ph-puzzle-piece", ComponentValue: "modules"},
|
|
|
- {Label: "Settings", Icon: "ph-gear", ComponentValue: "settings"},
|
|
|
- }, "updateSelectedPhpVerticalTab",
|
|
|
- )
|
|
|
- <div class="px-10 py-4">
|
|
|
- @PhpModulesCheckboxInputsSwitchToggles(
|
|
|
- runtimeOverview.PhpConfigs.Version,
|
|
|
- runtimeOverview.PhpConfigs.Modules,
|
|
|
- )
|
|
|
- @PhpSettingsInputs(
|
|
|
- runtimeOverview.PhpConfigs.Version,
|
|
|
- runtimeOverview.PhpConfigs.Settings,
|
|
|
- )
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="mt-5 flex justify-end">
|
|
|
- <div class="w-1/4">
|
|
|
- @componentForm.SubmitButton(
|
|
|
- "apply-php-runtime-configs-changes", "Apply changes",
|
|
|
- "ph-check-fat", "", false,
|
|
|
- )
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </form>
|
|
|
- } else {
|
|
|
- <div class="mb-6 flex w-full"></div>
|
|
|
- @CreatePhpMappingForm(runtimeOverview.VirtualHostHostname)
|
|
|
- }
|
|
|
- </div>
|
|
|
-}
|
|
|
-
|
|
|
-templ PhpRuntimeHorizontalTabContent(
|
|
|
- runtimeOverview presenterDto.RuntimeOverview,
|
|
|
- vhostsHostnames []string,
|
|
|
-) {
|
|
|
- <!-- PhpRuntimeHorizontalTabContent -->
|
|
|
- @PhpRuntimeHorizontalTabContentLocalState(runtimeOverview.VirtualHostHostname.String())
|
|
|
- <div class="bg-os-800 -mt-4 rounded-b-xl rounded-r-xl p-4" x-data="php">
|
|
|
- <div class="bg-os-500 rounded-b-lg rounded-r-lg px-4 py-2">
|
|
|
- if runtimeOverview.IsInstalled {
|
|
|
- @InstalledPhpRuntimeContent(runtimeOverview, vhostsHostnames)
|
|
|
- } else {
|
|
|
- @componentStructural.ServiceNotInstalledWarningForm("php")
|
|
|
- }
|
|
|
- </div>
|
|
|
- @UpdatePhpVersionModal()
|
|
|
- </div>
|
|
|
-}
|