Skip to content

Commit

Permalink
chore: merge pull request #171
Browse files Browse the repository at this point in the history
  • Loading branch information
ntorga authored Sep 23, 2024
2 parents 2e53365 + 03b31de commit 81430fe
Show file tree
Hide file tree
Showing 25 changed files with 772 additions and 160 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ require (
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/text v0.16.0
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.23.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
Expand Down
28 changes: 18 additions & 10 deletions src/presentation/api/controller/ssl.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,27 +46,35 @@ func (controller *SslController) Read(c echo.Context) error {
return apiHelper.ServiceResponseWrapper(c, controller.sslService.Read())
}

func parseRawVhosts(rawVhostsInput interface{}) (rawVhosts []string, err error) {
rawVhostsSlice, assertOk := rawVhostsInput.([]interface{})
func (controller *SslController) parseRawVhosts(
rawVhostsInput interface{},
) (rawVhostsStrSlice []string, err error) {
var assertOk bool

rawVhostsStrSlice, assertOk = rawVhostsInput.([]string)
if assertOk {
return rawVhostsStrSlice, nil
}

rawVhostsInterfaceSlice, assertOk := rawVhostsInput.([]interface{})
if !assertOk {
rawVhostUniqueStr, err := voHelper.InterfaceToString(rawVhostsInput)
if err != nil {
return rawVhosts, errors.New("VirtualHostsMustBeStringOrStringSlice")
return rawVhostsStrSlice, errors.New("VirtualHostsMustBeStringOrStringSlice")
}
return append(rawVhosts, rawVhostUniqueStr), err
return append(rawVhostsStrSlice, rawVhostUniqueStr), err
}

rawVhosts = []string{}
for _, rawVhost := range rawVhostsSlice {
for _, rawVhost := range rawVhostsInterfaceSlice {
rawVhostStr, err := voHelper.InterfaceToString(rawVhost)
if err != nil {
slog.Debug(err.Error(), slog.Any("vhost", rawVhost))
continue
}
rawVhosts = append(rawVhosts, rawVhostStr)
rawVhostsStrSlice = append(rawVhostsStrSlice, rawVhostStr)
}

return rawVhosts, err
return rawVhostsStrSlice, nil
}

// CreateSslPair godoc
Expand All @@ -85,7 +93,7 @@ func (controller *SslController) Create(c echo.Context) error {
return err
}

rawVhosts, err := parseRawVhosts(requestBody["virtualHosts"])
rawVhosts, err := controller.parseRawVhosts(requestBody["virtualHosts"])
if err != nil {
return apiHelper.ResponseWrapper(c, http.StatusBadRequest, err.Error())
}
Expand Down Expand Up @@ -166,7 +174,7 @@ func (controller *SslController) DeleteVhosts(c echo.Context) error {
return err
}

rawVhosts, err := parseRawVhosts(requestBody["virtualHosts"])
rawVhosts, err := controller.parseRawVhosts(requestBody["virtualHosts"])
if err != nil {
return apiHelper.ResponseWrapper(c, http.StatusBadRequest, err.Error())
}
Expand Down
8 changes: 7 additions & 1 deletion src/presentation/api/helper/readRequestBody.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,15 @@ func ReadRequestBody(c echo.Context) (map[string]interface{}, error) {
}

for formKey, keyValues := range formData {
if len(keyValues) != 1 {
if len(keyValues) == 0 {
continue
}

if len(keyValues) > 1 {
requestBody[formKey] = keyValues
continue
}

keyValue := keyValues[0]
if keyValue == "" {
continue
Expand Down
2 changes: 1 addition & 1 deletion src/presentation/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func HttpServerInit(
e := echo.New()

api.ApiInit(e, persistentDbSvc, transientDbSvc, trailDbSvc)
ui.UiInit(e, persistentDbSvc)
ui.UiInit(e, persistentDbSvc, transientDbSvc)

httpServer := http.Server{Addr: ":1618", Handler: e}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ func transformDbUserPrivilegeIntoComponentValueFormat(
return strings.ToLower(privilegeWithHyphen)
}

templ DatabaseUserPrivilegesRadioInputsSwitchToggles() {
<!-- DatabaseUserPrivilegesRadioInputsSwitchToggles -->
templ DatabaseUserPrivilegesCheckboxInputsSwitchToggles() {
<!-- DatabaseUserPrivilegesCheckboxInputsSwitchToggles -->
<div class="bg-os-500 p-5 rounded-md grid grid-cols-2 gap-6">
for _, databaseUserPrivilege := range valueObject.AvailableDatabasePrivileges {
@componentForm.RadioInputSwitchToggle(
@componentForm.CheckboxInputSwitchToggle(
"privileges", databaseUserPrivilege,
transformDbUserPrivilegeIntoComponentValueFormat(databaseUserPrivilege),
"databaseUser.privileges",
transformDbUserPrivilegeIntoComponentValueFormat(databaseUserPrivilege),
)
}
</div>
Expand Down
21 changes: 21 additions & 0 deletions src/presentation/ui/component/form/checkboxInputSwitchToggle.templ
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package componentForm

// Note: "bindModelPath" may be an array (in which case the "customValue" will be
// pushed into the array) OR "bindModelPath" may be just a boolean state (in which
// case the "customValue" is not necessary and will be ignored).
templ CheckboxInputSwitchToggle(id, label, bindModelPath, customValue string) {
<!-- CheckboxInputSwitchToggle -->
<label class="inline-flex cursor-pointer items-center">
<input
type="checkbox"
name={ id }
x-model={ bindModelPath }
if customValue != "" {
value={ customValue }
}
class="peer sr-only"
/>
<div class="peer-checked:bg-speedia-500 bg-os-100 peer relative h-6 w-11 rounded-full after:absolute after:start-[2px] after:top-0.5 after:h-5 after:w-5 after:rounded-full after:border after:bg-white after:transition-all after:content-[''] peer-checked:after:translate-x-full peer-checked:after:border-white"></div>
<span class="ml-2 text-sm text-neutral-100">{ label }</span>
</label>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package componentForm

script FileUploadTextInputFileContentReaderLocalState() {
document.addEventListener('alpine:init', () => {
Alpine.data('fileUploadTextInputFileContentReader', () => ({
uploadedFileName: '',
get uploadedFileNameLabel() {
if (this.uploadedFileName == '') {
return 'No file chosen';
}

return this.uploadedFileName;
},
init() {
this.uploadedFileName = '';
},
handleFileUpload(event) {
const inputFiles = Array.from(event.target.files);
if (inputFiles.length == 0) {
return;
}

const uploadedFile = inputFiles[0];
this.uploadedFileName = uploadedFile.name;

const reader = new FileReader();
reader.onload = (event) => {
this.$dispatch('file-content-readed', event.target.result);
};
reader.readAsText(uploadedFile);
}
}));
});
}

templ FileUploadTextInputFileContentReader(
id, label, bindValuePath, acceptAttr string,
) {
<!-- FileUploadTextInputFileContentReader -->
@FileUploadTextInputFileContentReaderLocalState()
<div class="relative w-full" x-data="fileUploadTextInputFileContentReader">
<input
x-ref={ id + "FileInput" }
type="file"
accept={ acceptAttr }
class="hidden"
@change="handleFileUpload"
@file-content-readed={ bindValuePath + " = $event.detail" }
/>
<div
@click={ "$refs." + id + "fileInput.click()" }
class="bg-os-300 border-os-200 hover:border-os-100 autofill:bg-os-300 focus:border-os-50 peer relative h-10 w-full cursor-default cursor-pointer rounded-md border px-3 pt-2 text-sm text-slate-400 placeholder-transparent outline-none transition-all"
>
<label class="cursor-pointer" x-text="uploadedFileNameLabel"></label>
</div>
<label class="from-os-300 via-os-300 absolute -top-2 left-1.5 cursor-text bg-gradient-to-t to-transparent to-50% px-1.5 text-xs font-bold text-neutral-50 text-opacity-80">
{ label }
</label>
</div>
}
8 changes: 4 additions & 4 deletions src/presentation/ui/component/form/inputField.templ
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ templ InputFieldWithPrefix(
) {
<!-- InputFieldWithPrefix -->
<div class="relative w-full">
<div class="flex items-center border-os-200 border rounded-md hover:border-os-100 focus:border-os-50">
<span class="bg-os-200 h-10 px-3 border-r border-os-200 rounded-s-md pt-2.7 text-slate-400 text-sm relative cursor-default" x-text={ prefix }></span>
<div class="border-os-200 hover:border-os-100 focus:border-os-50 flex items-center rounded-md border">
<span class="bg-os-200 border-os-200 pt-2.7 relative h-10 cursor-default rounded-s-md border-r px-3 text-sm text-slate-400" x-text={ prefix }></span>
<input
type={ inputType }
id={ id }
Expand Down Expand Up @@ -79,9 +79,9 @@ templ InputFieldReadOnly(
name={ id }
x-model:value={ bindValuePath }
if denseMode {
class="bg-os-300 border-os-200 hover:border-os-100 autofill:bg-os-300 focus:border-os-50 h-7.5 peer relative w-full rounded-md border px-1.5 text-[13px] text-neutral-100 placeholder-transparent outline-none transition-all cursor-default text-slate-400"
class="bg-os-300 border-os-200 hover:border-os-100 autofill:bg-os-300 focus:border-os-50 h-7.5 peer relative w-full cursor-default rounded-md border px-1.5 text-[13px] text-slate-400 placeholder-transparent outline-none transition-all"
} else {
class="bg-os-300 border-os-200 hover:border-os-100 autofill:bg-os-300 focus:border-os-50 peer relative h-10 w-full rounded-md border px-3 text-sm text-neutral-100 placeholder-transparent outline-none transition-all cursor-default text-slate-400"
class="bg-os-300 border-os-200 hover:border-os-100 autofill:bg-os-300 focus:border-os-50 peer relative h-10 w-full cursor-default rounded-md border px-3 text-sm text-slate-400 placeholder-transparent outline-none transition-all"
}
readonly
/>
Expand Down
23 changes: 4 additions & 19 deletions src/presentation/ui/component/form/radioInput.templ
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,18 @@ package componentForm
templ RadioInput(id, label, bindValue, bindModelPath string) {
<!-- RadioInput -->
<div class="inline-flex items-center">
<label class="relative flex items-center p-3 -mr-2 rounded-full cursor-pointer">
<label class="relative -mr-2 flex cursor-pointer items-center rounded-full p-3">
<input
type="radio"
name={ id }
value={ bindValue }
x-model={ bindModelPath }
class="peer relative h-3.5 w-3.5 cursor-pointer appearance-none rounded-full border border-speedia-500 bg-inherit transition-all checked:h-4 checked:w-4 checked:border-inherit checked:bg-speedia-500"
class="border-speedia-500 checked:bg-speedia-500 peer relative h-3.5 w-3.5 cursor-pointer appearance-none rounded-full border bg-inherit transition-all checked:h-4 checked:w-4 checked:border-inherit"
/>
<span class="absolute text-white transition-opacity opacity-0 peer-checked:opacity-100 text-xs mx-0.5 mt-0.5">
<i class="ph-duotone ph-check-fat w-full h-full"></i>
<span class="absolute mx-0.5 mt-0.5 text-xs text-white opacity-0 transition-opacity peer-checked:opacity-100">
<i class="ph-duotone ph-check-fat h-full w-full"></i>
</span>
</label>
<label class="ml-1 text-sm font-medium text-neutral-100">{ label }</label>
</div>
}

templ RadioInputSwitchToggle(id, label, bindValue, bindModelPath string) {
<!-- RadioInputSwitchToggle -->
<label class="inline-flex items-center cursor-pointer">
<input
type="checkbox"
name={ id }
value={ bindValue }
x-model={ bindModelPath }
class="sr-only peer"
/>
<div class="relative w-11 h-6 bg-gray-200 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:start-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:border after:transition-all peer-checked:bg-speedia-500"></div>
<span class="ml-2 text-sm text-neutral-50">{ label }</span>
</label>
}
75 changes: 75 additions & 0 deletions src/presentation/ui/component/form/selectInput.templ
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,78 @@ templ SelectInputWithLabelValuePair(
<i class="ph-bold ph-caret-down pointer-events-none absolute right-2.5 top-3.5 text-sm"></i>
</div>
}

script MultiSelectInputLocalState() {
document.addEventListener('alpine:init', () => {
Alpine.data('multiSelectInput', () => ({
getFormattedSelectedItems(bindSelectedItemsPath) {
if (bindSelectedItemsPath.length == 0) {
return '--';
}

let formattedSelectedItems = bindSelectedItemsPath.join(', ');
if (formattedSelectedItems.length > 80) {
return formattedSelectedItems.substr(0, 80) + '...';
}
return formattedSelectedItems;
},
shouldExpandOptions: false,
closeDropdown() {
this.shouldExpandOptions = false;
},
toggleDropdownDisplay() {
if (this.shouldExpandOptions) {
this.closeDropdown();
return;
}

this.shouldExpandOptions = true;
},
}));
});
}

templ MultiSelectInput(
id, label, bindModelPath string,
options []string,
) {
<!-- MultiSelectInput -->
@MultiSelectInputLocalState()
<div
class="relative w-full"
x-data="multiSelectInput"
@click.away="closeDropdown()"
>
<div
@click="toggleDropdownDisplay()"
class="border-os-200 hover:border-os-100 bg-os-300 autofill:bg-os-300 pt-2.3 peer relative h-10 w-full appearance-none rounded-md border px-3 text-sm text-neutral-100 placeholder-transparent outline-none transition-all"
>
<label
class="cursor-pointer text-neutral-100"
x-text={ "getFormattedSelectedItems(" + bindModelPath + ")" }
></label>
</div>
<label class="from-os-300 via-os-300 absolute -top-2 left-1.5 cursor-text bg-gradient-to-t to-transparent to-50% px-1.5 text-xs font-bold text-neutral-50 text-opacity-80">
{ label }
</label>
<i class="ph-bold ph-caret-down pointer-events-none absolute right-2.5 top-3.5 text-sm"></i>
<div x-show="shouldExpandOptions" class="bg-os-500 border-os-200 rounded-b-md border">
for _, option := range options {
<div class="px-3 pb-1.5 pt-1">
<label class="inline-flex w-full cursor-pointer items-center">
<span class="text-sm text-neutral-50">{ option }</span>
<input
type="checkbox"
id={ id }
name={ id }
value={ option }
x-model={ bindModelPath }
class="peer sr-only"
/>
<div class="h-4.5 peer-checked:bg-speedia-500 peer relative ml-auto w-8 rounded-full bg-gray-400 after:absolute after:start-[2px] after:top-0.5 after:h-3.5 after:w-3.5 after:rounded-full after:border after:bg-white after:transition-all after:content-[''] peer-checked:after:translate-x-full peer-checked:after:border-white"></div>
</label>
</div>
}
</div>
</div>
}
9 changes: 6 additions & 3 deletions src/presentation/ui/component/form/submitButton.templ
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
package componentForm

templ SubmitButton(
label, icon, onClick string,
id, label, icon, onClick string,
denseMode bool,
) {
<!-- SubmitButton -->
<button
if id != "" {
id={ id }
}
type="submit"
if onClick != "" {
@click={ onClick }
}
if denseMode {
class="bg-speedia-500 hover:bg-speedia-300 rounded-md border-none px-2 py-1 text-center text-sm font-bold lowercase text-white"
class={ "bg-speedia-500 hover:bg-speedia-300 rounded-md border-none text-center font-bold lowercase text-white px-2 py-1 text-sm" }
} else {
class="bg-speedia-500 hover:bg-speedia-300 w-full rounded-md border-none p-3 text-center text-base font-bold lowercase leading-none text-white"
class={ "bg-speedia-500 hover:bg-speedia-300 rounded-md border-none text-center font-bold lowercase text-white w-full p-3 text-base leading-none" }
}
>
if icon != "" {
Expand Down
Loading

0 comments on commit 81430fe

Please sign in to comment.