Browse Source

pruned and added files and directories

cli-archive
nic 2 years ago
parent
commit
1dc8ad4e9a
  1. 2
      Readme.md
  2. 72
      internal/api/attachments.go
  3. 20
      internal/api/common.go
  4. 0
      internal/api/invoices.go
  5. 0
      internal/api/jobs.go
  6. 46
      internal/api/session_store.go
  7. 0
      internal/handlers/cli/admin.go
  8. 0
      internal/handlers/cli/assets.go
  9. 0
      internal/handlers/cli/companies.go
  10. 0
      internal/handlers/cli/contacts.go
  11. 0
      internal/handlers/cli/contracts.go
  12. 0
      internal/handlers/cli/dashboard.go
  13. 0
      internal/handlers/cli/generic.go
  14. 0
      internal/handlers/cli/invoices.go
  15. 0
      internal/handlers/cli/jobs.go
  16. 0
      internal/handlers/cli/locations.go
  17. 0
      internal/handlers/cli/login.go
  18. 0
      internal/handlers/cli/notifications.go
  19. 0
      internal/handlers/cli/quotes.go
  20. 0
      internal/handlers/cli/services.go
  21. 0
      internal/handlers/cli/tags.go
  22. 0
      internal/handlers/cli/users.go
  23. 24
      internal/handlers/web/admin.go
  24. 11
      internal/handlers/web/assets.go
  25. 11
      internal/handlers/web/companies.go
  26. 11
      internal/handlers/web/contacts.go
  27. 11
      internal/handlers/web/contracts.go
  28. 34
      internal/handlers/web/dashboard.go
  29. 11
      internal/handlers/web/generic.go
  30. 57
      internal/handlers/web/invoices.go
  31. 26
      internal/handlers/web/jobs.go
  32. 11
      internal/handlers/web/locations.go
  33. 104
      internal/handlers/web/login.go
  34. 11
      internal/handlers/web/notifications.go
  35. 11
      internal/handlers/web/quotes.go
  36. 11
      internal/handlers/web/services.go
  37. 11
      internal/handlers/web/tags.go
  38. 11
      internal/handlers/web/users.go
  39. 189
      internal/menu/jobs.go
  40. 129
      internal/menu/menu.go
  41. 36
      internal/middleware/auth_middleware.go
  42. 0
      internal/utils/ui.go

2
Readme.md

@ -3,7 +3,7 @@
## Project Structure
```project_root/
├── cmd/
├── apps/
│ ├── cli/
│ │ └── main.go
│ └── web/

72
internal/api/attachments.go

@ -1,72 +0,0 @@
package api
import (
"encoding/json"
"fmt"
"marmic/servicetrade-toolbox/internal/auth"
"strings"
)
func GetAttachmentsForJob(session *auth.Session, jobID string) (map[string]interface{}, error) {
url := fmt.Sprintf("%s/job/%s/paperwork", BaseURL, jobID)
req, err := AuthenticatedRequest(session, "GET", url, nil)
if err != nil {
return nil, fmt.Errorf("error creating request: %v", err)
}
resp, err := DoAuthenticatedRequest(session, req)
if err != nil {
return nil, fmt.Errorf("error sending request: %v", err)
}
defer resp.Body.Close()
var result map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("error decoding response: %v", err)
}
return result, nil
}
func GenerateDeleteEndpoints(data map[string]interface{}, filenames []string) []string {
var endpoints []string
filenamesToDeleteMap := make(map[string]struct{})
for _, name := range filenames {
filenamesToDeleteMap[strings.ToLower(strings.TrimSpace(name))] = struct{}{}
}
if dataMap, ok := data["data"].(map[string]interface{}); ok {
if attachments, ok := dataMap["attachments"].([]interface{}); ok {
for _, item := range attachments {
attachment := item.(map[string]interface{})
if filename, ok := attachment["fileName"].(string); ok {
trimmedFilename := strings.ToLower(strings.TrimSpace(filename))
if _, exists := filenamesToDeleteMap[trimmedFilename]; exists {
endpoints = append(endpoints, fmt.Sprintf("%s/attachment/%d", BaseURL, int64(attachment["id"].(float64))))
}
}
}
}
}
return endpoints
}
func DeleteAttachment(session *auth.Session, endpoint string) error {
req, err := AuthenticatedRequest(session, "DELETE", endpoint, nil)
if err != nil {
return fmt.Errorf("failed to create DELETE request: %v", err)
}
resp, err := DoAuthenticatedRequest(session, req)
if err != nil {
return fmt.Errorf("failed to send DELETE request: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 && resp.StatusCode != 204 {
return fmt.Errorf("failed to delete attachment: %s", resp.Status)
}
return nil
}

20
internal/api/common.go

@ -1,20 +0,0 @@
package api
import (
"encoding/json"
"fmt"
"net/http"
)
const BaseURL = "https://api.servicetrade.com/api"
// DecodeJSONResponse decodes a JSON response into the provided interface
func DecodeJSONResponse(resp *http.Response, v interface{}) error {
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("API request failed with status code: %d", resp.StatusCode)
}
return json.NewDecoder(resp.Body).Decode(v)
}

0
internal/api/invoices.go

0
internal/api/jobs.go

46
internal/api/session_store.go

@ -1,46 +0,0 @@
package api
import (
"sync"
"time"
)
type SessionStore struct {
sessions map[string]*Session
mu sync.RWMutex
}
func NewSessionStore() *SessionStore {
return &SessionStore{
sessions: make(map[string]*Session),
}
}
func (store *SessionStore) Set(sessionID string, session *Session) {
store.mu.Lock()
defer store.mu.Unlock()
store.sessions[sessionID] = session
}
func (store *SessionStore) Get(sessionID string) (*Session, bool) {
store.mu.RLock()
defer store.mu.RUnlock()
session, ok := store.sessions[sessionID]
return session, ok
}
func (store *SessionStore) Delete(sessionID string) {
store.mu.Lock()
defer store.mu.Unlock()
delete(store.sessions, sessionID)
}
func (store *SessionStore) CleanupSessions() {
store.mu.Lock()
defer store.mu.Unlock()
for id, session := range store.sessions {
if time.Since(session.LastAccessed) > 24*time.Hour {
delete(store.sessions, id)
}
}
}

0
internal/handlers/admin.go → internal/handlers/cli/admin.go

0
internal/handlers/assets.go → internal/handlers/cli/assets.go

0
internal/handlers/companies.go → internal/handlers/cli/companies.go

0
internal/handlers/contacts.go → internal/handlers/cli/contacts.go

0
internal/handlers/contracts.go → internal/handlers/cli/contracts.go

0
internal/handlers/dashboard.go → internal/handlers/cli/dashboard.go

0
internal/handlers/generic.go → internal/handlers/cli/generic.go

0
internal/handlers/invoices.go → internal/handlers/cli/invoices.go

0
internal/handlers/jobs.go → internal/handlers/cli/jobs.go

0
internal/handlers/locations.go → internal/handlers/cli/locations.go

0
internal/handlers/login.go → internal/handlers/cli/login.go

0
internal/handlers/notifications.go → internal/handlers/cli/notifications.go

0
internal/handlers/quotes.go → internal/handlers/cli/quotes.go

0
internal/handlers/services.go → internal/handlers/cli/services.go

0
internal/handlers/tags.go → internal/handlers/cli/tags.go

0
internal/handlers/users.go → internal/handlers/cli/users.go

24
internal/handlers/web/admin.go

@ -0,0 +1,24 @@
package handlers
import (
"html/template"
"net/http"
)
func AdminHandler(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("HX-Request") == "true" {
// This is an HTMX request, return only the jobs partial
tmpl := template.Must(template.ParseFiles("templates/partials/jobs.html"))
jobs := r.Cookies() // Replace with actual data fetching
tmpl.Execute(w, jobs)
} else {
// This is a full page request
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/partials/admin.html"))
jobs := []string{"Job 1", "Job 2", "Job 3"} // Replace with actual data fetching
tmpl.Execute(w, map[string]interface{}{
"Title": "Jobs",
"Jobs": jobs,
})
}
}

11
internal/handlers/web/assets.go

@ -0,0 +1,11 @@
package handlers
import (
"html/template"
"net/http"
)
func AssetsHandler(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/assets.html"))
tmpl.Execute(w, nil)
}

11
internal/handlers/web/companies.go

@ -0,0 +1,11 @@
package handlers
import (
"html/template"
"net/http"
)
func CompaniesHandler(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/companies.html"))
tmpl.Execute(w, nil)
}

11
internal/handlers/web/contacts.go

@ -0,0 +1,11 @@
package handlers
import (
"html/template"
"net/http"
)
func ContactsHandler(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/contacts.html"))
tmpl.Execute(w, nil)
}

11
internal/handlers/web/contracts.go

@ -0,0 +1,11 @@
package handlers
import (
"html/template"
"net/http"
)
func ContractsHandler(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/contracts.html"))
tmpl.Execute(w, nil)
}

34
internal/handlers/web/dashboard.go

@ -0,0 +1,34 @@
package handlers
import (
"html/template"
"log"
"net/http"
)
func DashboardHandler(w http.ResponseWriter, r *http.Request) {
tmpl, err := template.ParseFiles(
"templates/layout.html",
"templates/dashboard.html",
"templates/partials/invoice_search.html",
"templates/partials/invoice_search_results.html",
)
if err != nil {
log.Printf("Template parsing error: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
data := struct{}{} // Empty struct as data
if r.Header.Get("HX-Request") == "true" {
err = tmpl.ExecuteTemplate(w, "content", data)
} else {
err = tmpl.ExecuteTemplate(w, "layout.html", data)
}
if err != nil {
log.Printf("Template execution error: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
}

11
internal/handlers/web/generic.go

@ -0,0 +1,11 @@
package handlers
import (
"html/template"
"net/http"
)
func GenericHandler(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/generic.html"))
tmpl.Execute(w, nil)
}

57
internal/handlers/web/invoices.go

@ -0,0 +1,57 @@
package handlers
import (
"html/template"
"log"
"marmic/servicetrade-toolbox/internal/api"
"net/http"
"strings"
)
func InvoicesHandler(w http.ResponseWriter, r *http.Request) {
session, ok := r.Context().Value("session").(*api.Session)
if !ok {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// Handle the search request
if r.Method == "GET" && r.URL.Query().Get("search") != "" {
handleInvoiceSearch(w, r, session)
return
}
// Handle the initial page load
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/invoices.html"))
err := tmpl.Execute(w, nil)
if err != nil {
log.Printf("Error executing template: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}
func handleInvoiceSearch(w http.ResponseWriter, r *http.Request, session *api.Session) {
searchTerm := strings.TrimSpace(r.URL.Query().Get("search"))
if searchTerm == "" {
log.Println("Empty search term, returning empty response")
w.WriteHeader(http.StatusOK)
return
}
invoice, err := session.GetInvoice(searchTerm)
if err != nil {
log.Printf("Error fetching invoice: %v", err)
w.WriteHeader(http.StatusInternalServerError)
tmpl := template.Must(template.ParseFiles("templates/partials/invoice_search_results.html"))
tmpl.ExecuteTemplate(w, "invoice_search_results", map[string]interface{}{"Error": err.Error()})
return
}
tmpl := template.Must(template.ParseFiles("templates/partials/invoice_search_results.html"))
err = tmpl.ExecuteTemplate(w, "invoice_search_results", invoice)
if err != nil {
log.Printf("Error executing template: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}

26
internal/handlers/web/jobs.go

@ -0,0 +1,26 @@
package handlers
import (
"html/template"
"net/http"
)
func JobsHandler(w http.ResponseWriter, r *http.Request) {
jobs := []string{"Job 1", "Job 2", "Job 3"} // Replace with actual data fetching
if r.Header.Get("HX-Request") == "true" {
// This is an HTMX request, return the jobs content wrapped in the content template
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/partials/jobs.html"))
tmpl.ExecuteTemplate(w, "content", map[string]interface{}{
"Title": "Jobs",
"Jobs": jobs,
})
} else {
// This is a full page request
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/partials/jobs.html"))
tmpl.Execute(w, map[string]interface{}{
"Title": "Jobs",
"Jobs": jobs,
})
}
}

11
internal/handlers/web/locations.go

@ -0,0 +1,11 @@
package handlers
import (
"html/template"
"net/http"
)
func LocationsHandler(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/locations.html"))
tmpl.Execute(w, nil)
}

104
internal/handlers/web/login.go

@ -0,0 +1,104 @@
package handlers
import (
"html/template"
"log"
"marmic/servicetrade-toolbox/internal/api"
"marmic/servicetrade-toolbox/internal/middleware"
"net/http"
"strings"
)
func LoginHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
tmpl := template.Must(template.ParseFiles("templates/login.html"))
tmpl.Execute(w, nil)
return
}
if r.Method == "POST" {
email := r.FormValue("email")
password := r.FormValue("password")
session := api.NewSession()
err := session.Login(email, password)
if err != nil {
if r.Header.Get("HX-Request") == "true" {
w.Write([]byte("<div class='error'>Login failed: " + err.Error() + "</div>"))
} else {
http.Error(w, "Login failed", http.StatusUnauthorized)
}
return
}
cookieParts := strings.Split(session.Cookie, ";")
sessionID := strings.TrimPrefix(cookieParts[0], "PHPSESSID=")
middleware.SessionStore.Set(sessionID, session)
http.SetCookie(w, &http.Cookie{
Name: "PHPSESSID",
Value: sessionID,
Path: "/",
HttpOnly: true,
Secure: r.TLS != nil,
SameSite: http.SameSiteLaxMode,
})
if r.Header.Get("HX-Request") == "true" {
w.Header().Set("HX-Redirect", "/")
w.WriteHeader(http.StatusOK)
w.Write([]byte("Login successful"))
} else {
http.Redirect(w, r, "/", http.StatusSeeOther)
}
}
}
func LogoutHandler(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie("PHPSESSID")
if err != nil {
log.Printf("No session cookie found: %v", err)
redirectToLogin(w, r)
return
}
sessionID := cookie.Value
session, exists := middleware.SessionStore.Get(sessionID)
if !exists {
log.Println("No session found in store")
redirectToLogin(w, r)
return
}
err = session.Logout()
if err != nil {
log.Printf("Logout failed: %v", err)
http.Error(w, "Logout failed", http.StatusInternalServerError)
return
}
middleware.SessionStore.Delete(sessionID)
http.SetCookie(w, &http.Cookie{
Name: "PHPSESSID",
Value: "",
Path: "/",
MaxAge: -1,
HttpOnly: true,
Secure: r.TLS != nil,
SameSite: http.SameSiteLaxMode,
})
log.Println("Logout successful, redirecting to login page")
redirectToLogin(w, r)
}
func redirectToLogin(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("HX-Request") != "" {
w.Header().Set("HX-Redirect", "/login")
w.WriteHeader(http.StatusOK)
} else {
http.Redirect(w, r, "/login", http.StatusSeeOther)
}
}

11
internal/handlers/web/notifications.go

@ -0,0 +1,11 @@
package handlers
import (
"html/template"
"net/http"
)
func NotificationsHandler(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/notifications.html"))
tmpl.Execute(w, nil)
}

11
internal/handlers/web/quotes.go

@ -0,0 +1,11 @@
package handlers
import (
"html/template"
"net/http"
)
func QuotesHandler(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/quotes.html"))
tmpl.Execute(w, nil)
}

11
internal/handlers/web/services.go

@ -0,0 +1,11 @@
package handlers
import (
"html/template"
"net/http"
)
func ServicesHandler(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/services.html"))
tmpl.Execute(w, nil)
}

11
internal/handlers/web/tags.go

@ -0,0 +1,11 @@
package handlers
import (
"html/template"
"net/http"
)
func TagsHandler(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/tags.html"))
tmpl.Execute(w, nil)
}

11
internal/handlers/web/users.go

@ -0,0 +1,11 @@
package handlers
import (
"html/template"
"net/http"
)
func UsersHandler(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/users.html"))
tmpl.Execute(w, nil)
}

189
internal/menu/jobs.go

@ -1,189 +0,0 @@
package menu
import (
"encoding/json"
"fmt"
"marmic/servicetrade-toolbox/internal/api"
"marmic/servicetrade-toolbox/internal/ui"
)
func HandleJobs(session *api.Session) {
jobsMenu := getJobsMenu()
for {
choice := DisplayMenuAndGetChoice(jobsMenu, "Jobs Menu")
if choice == len(jobsMenu)+1 {
return // Go back to main menu
}
jobsMenu[choice-1].Handler(session)
}
}
func getJobsMenu() []MenuItem {
return []MenuItem{
{"Search Job by ID", searchJobByID, nil},
{"List Recent Jobs", listRecentJobs, nil},
{"Create New Job", createNewJob, nil},
{"Manage Job Attachments", manageJobAttachments, nil},
{"View Deficiencies", viewDeficiencyById, nil},
}
}
func searchJobByID(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("We will search a job ID here.")
ui.PressEnterToContinue()
}
func listRecentJobs(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("Listing recent jobs...")
ui.PressEnterToContinue()
}
func createNewJob(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("Creating a new job...")
ui.PressEnterToContinue()
}
func manageJobAttachments(session *api.Session) {
ui.ClearScreen()
jobID := ui.PromptForInput("Enter Job ID: ")
attachments, err := session.GetAttachmentsForJob(jobID)
if err != nil {
ui.DisplayError("Failed to retrieve attachments:", err)
return
}
// Display attachments
ui.DisplayMessage("Attachments for Job " + jobID + ":")
if dataMap, ok := attachments["data"].(map[string]interface{}); ok {
if attachmentsList, ok := dataMap["attachments"].([]interface{}); ok {
for i, attachment := range attachmentsList {
if att, ok := attachment.(map[string]interface{}); ok {
fmt.Printf("%d. %s\n", i+1, att["fileName"])
}
}
}
}
// Prompt for attachments to delete
toDelete := ui.PromptForInput("Enter the numbers of attachments to delete (comma-separated), or 'all' for all: ")
var filesToDelete []string
if toDelete == "all" {
if dataMap, ok := attachments["data"].(map[string]interface{}); ok {
if attachmentsList, ok := dataMap["attachments"].([]interface{}); ok {
for _, attachment := range attachmentsList {
if att, ok := attachment.(map[string]interface{}); ok {
filesToDelete = append(filesToDelete, att["fileName"].(string))
}
}
}
}
} else {
// Parse the input and get the corresponding filenames
// This part needs to be implemented
}
// Generate delete endpoints
endpoints := generateDeleteEndpoints(attachments, filesToDelete)
// Confirm deletion
ui.DisplayMessage(fmt.Sprintf("You are about to delete %d attachments. Are you sure? (y/n)", len(endpoints)))
confirm := ui.PromptForInput("")
if confirm != "y" {
ui.DisplayMessage("Deletion cancelled.")
return
}
// Perform deletion
for _, endpoint := range endpoints {
err := session.DeleteAttachment(endpoint)
if err != nil {
ui.DisplayError(fmt.Sprintf("Failed to delete attachment %s:", endpoint), err)
} else {
ui.DisplayMessage(fmt.Sprintf("Successfully deleted attachment: %s", endpoint))
}
}
ui.DisplayMessage("Attachment management completed.")
ui.PressEnterToContinue()
}
func viewDeficiencyById(session *api.Session) {
ui.ClearScreen()
deficiencyId := ui.PromptForInput("Enter Deficiency ID: ")
ui.DisplayMessage(fmt.Sprintf("Fetching information for Deficiency %s...", deficiencyId))
result, err := session.GetDeficiencyById(deficiencyId)
if err != nil {
ui.DisplayError("Failed to retrieve deficiency information:", err)
ui.PressEnterToContinue()
return
}
ui.ClearScreen()
ui.DisplayMessage(fmt.Sprintf("Information for Deficiency %s:", deficiencyId))
if data, ok := result["data"].(map[string]interface{}); ok {
if len(data) == 0 {
ui.DisplayMessage("No information found for this deficiency.")
} else {
fmt.Println("Deficiency Details:")
for key, value := range data {
fmt.Printf("- %s:\n", key)
if details, ok := value.(map[string]interface{}); ok {
for detailKey, detailValue := range details {
if detailValue != nil {
// Handle potential json.Number values
if num, ok := detailValue.(json.Number); ok {
fmt.Printf(" %s: %s\n", detailKey, num.String())
} else {
fmt.Printf(" %s: %v\n", detailKey, detailValue)
}
}
}
} else if num, ok := value.(json.Number); ok {
fmt.Printf(" %s\n", num.String())
} else {
fmt.Printf(" %v\n", value)
}
fmt.Println()
}
}
} else {
ui.DisplayMessage("Unexpected data structure in the API response.")
fmt.Printf("Response structure: %+v\n", result)
}
ui.DisplayMessage("\nDeficiency information viewing completed.")
ui.PressEnterToContinue()
}
// Helper function to generate delete endpoints
func generateDeleteEndpoints(data map[string]interface{}, filenames []string) []string {
var endpoints []string
filenamesToDeleteMap := make(map[string]struct{})
for _, name := range filenames {
filenamesToDeleteMap[name] = struct{}{}
}
if dataMap, ok := data["data"].(map[string]interface{}); ok {
if attachments, ok := dataMap["attachments"].([]interface{}); ok {
for _, item := range attachments {
attachment := item.(map[string]interface{})
if filename, ok := attachment["fileName"].(string); ok {
if _, exists := filenamesToDeleteMap[filename]; exists {
endpoints = append(endpoints, fmt.Sprintf("https://api.servicetrade.com/api/attachment/%d", int64(attachment["id"].(float64))))
}
}
}
}
}
return endpoints
}

129
internal/menu/menu.go

@ -1,129 +0,0 @@
package menu
import (
"marmic/servicetrade-toolbox/internal/api"
"marmic/servicetrade-toolbox/internal/ui"
)
type MenuItem struct {
Name string
Handler func(*api.Session)
Submenu []MenuItem
}
func GetMainMenu() []MenuItem {
return []MenuItem{
{"Administration", HandleAdministration, nil},
{"Assets", HandleAssets, nil},
{"Companies", HandleCompanies, nil},
{"Contacts", HandleContacts, nil},
{"Contracts", HandleContracts, nil},
{"Generic Tools", HandleGenericTools, nil},
{"Invoices", HandleInvoices, nil},
{"Jobs", HandleJobs, nil},
{"Locations", HandleLocations, nil},
{"Notifications", HandleNotifications, nil},
{"Quotes", HandleQuotes, nil},
{"Services", HandleServices, nil},
{"Tags", HandleTags, nil},
{"Users", HandleUsers, nil},
}
}
func DisplayMenuAndGetChoice(menuItems []MenuItem, title string) int {
for {
displayMenuItems := make([]string, len(menuItems)+1)
for i, item := range menuItems {
displayMenuItems[i] = item.Name
}
displayMenuItems[len(menuItems)] = "Back/Exit"
ui.DisplayMenu(displayMenuItems, title)
choice, err := ui.GetUserChoice(len(displayMenuItems))
if err == nil {
return choice
}
ui.DisplayMessage("Invalid input. Please try again.")
ui.PressEnterToContinue()
}
}
// Placeholder functions for other main menu items
func HandleAdministration(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("Administration menu placeholder")
ui.PressEnterToContinue()
}
func HandleAssets(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("Assets menu placeholder")
ui.PressEnterToContinue()
}
func HandleCompanies(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("Companies menu placeholder")
ui.PressEnterToContinue()
}
func HandleContacts(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("Contacts menu placeholder")
ui.PressEnterToContinue()
}
func HandleContracts(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("Contracts menu placeholder")
ui.PressEnterToContinue()
}
func HandleGenericTools(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("Generic Tools menu placeholder")
ui.PressEnterToContinue()
}
func HandleInvoices(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("Invoices menu placeholder")
ui.PressEnterToContinue()
}
func HandleLocations(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("Locations menu placeholder")
ui.PressEnterToContinue()
}
func HandleNotifications(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("Notifications menu placeholder")
ui.PressEnterToContinue()
}
func HandleQuotes(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("Quotes menu placeholder")
ui.PressEnterToContinue()
}
func HandleServices(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("Services menu placeholder")
ui.PressEnterToContinue()
}
func HandleTags(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("Tags menu placeholder")
ui.PressEnterToContinue()
}
func HandleUsers(session *api.Session) {
ui.ClearScreen()
ui.DisplayMessage("Users menu placeholder")
ui.PressEnterToContinue()
}

36
internal/middleware/auth_middleware.go

@ -1,36 +0,0 @@
package middleware
import (
"context"
"marmic/servicetrade-toolbox/internal/api"
"net/http"
)
var SessionStore = api.NewSessionStore()
func AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie("PHPSESSID")
if err != nil {
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
sessionID := cookie.Value
session, exists := SessionStore.Get(sessionID)
if !exists {
session = api.NewSession()
session.Cookie = "PHPSESSID=" + sessionID
if err := session.ValidateSession(); err != nil {
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
SessionStore.Set(sessionID, session)
}
ctx := context.WithValue(r.Context(), "session", session)
next.ServeHTTP(w, r.WithContext(ctx))
})
}

0
internal/ui/ui.go → internal/utils/ui.go

Loading…
Cancel
Save