feat: G15Office job, widget settings and submissions admin, embed.js and the settings importer

- SyncG15Office files each submission as a G15Office task with its screenshot through a fetchguard client limited to the configured host; a River job with 3 attempts, PHP's messages on failure, nothing sent when unconfigured
- the replay of PHP's recorded G15Office exchange (classes/testdata) asserts the task JSON, headers and the screenshot part
- settings screen (cabana field types only), read-only submissions list, manage_settings permission and navigation
- embed.js served byte for byte at /plugins/golem15/feedback/assets/js/embed.js
- feedback:import-settings copies the WinterCMS settings row once
This commit is contained in:
Jakub Zych
2026-10-04 00:22:08 +02:00
parent 92e1b4e09c
commit af5d77c997
19 changed files with 2285 additions and 6 deletions

View File

@@ -0,0 +1,13 @@
// Package controllers holds the golem15.feedback admin controllers.
package controllers
import "git.golem15.com/golem15/summercms/modules/pact"
// PermissionManageSettings guards the widget settings and the submissions
// list (WinterCMS registers it for the developer role).
const PermissionManageSettings = "golem15.feedback.manage_settings"
// AdminControllers lists the plugin's admin controllers.
func AdminControllers() []pact.AdminController {
return []pact.AdminController{SubmissionsAdminController{}}
}

View File

@@ -0,0 +1,13 @@
list: ~/plugins/golem15/feedback/models/submission/columns.yaml
modelClass: Golem15\Feedback\Models\FeedbackSubmission
title: golem15.feedback::lang.submissions.list_title
noRecordsMessage: backend::lang.list.no_records
recordsPerPage: 20
showCheckboxes: false
defaultSort:
column: created_at
direction: desc
toolbar:
search:
prompt: backend::lang.list.search_prompt

View File

@@ -0,0 +1,36 @@
package controllers
import (
"git.golem15.com/golem15/sm-feedback-plugin/models"
"git.golem15.com/golem15/summercms/modules/pact"
)
// SubmissionsAdminController is the read-only list of the widget's
// submissions (golem15.feedback.submissions): no form, no create, no
// delete. The WinterCMS plugin had no such screen; operators read reports
// in G15Office, and this list shows what was received and whether it was
// filed (status, task id).
type SubmissionsAdminController struct{}
var (
_ pact.AdminController = SubmissionsAdminController{}
_ pact.AdminPermissioned = SubmissionsAdminController{}
_ pact.AdminRecordSource = SubmissionsAdminController{}
)
// ID is golem15.feedback.submissions.
func (SubmissionsAdminController) ID() string { return "golem15.feedback.submissions" }
// ModelName is the model's WinterCMS class name.
func (SubmissionsAdminController) ModelName() string { return models.Submission{}.MorphName() }
// ConfigDir holds config_list.yaml.
func (SubmissionsAdminController) ConfigDir() string { return "controllers/submissions" }
// RequiredPermissions is golem15.feedback.manage_settings.
func (SubmissionsAdminController) RequiredPermissions() []string {
return []string{PermissionManageSettings}
}
// NewRecord returns an empty submission.
func (SubmissionsAdminController) NewRecord() any { return &models.Submission{} }