fix(admin): use basePath for API fetches when urlPrefix is set (#9197)

* fix(admin): use basePath for API fetches when urlPrefix is set

* fix(admin): drop duplicate iam-utils script on Groups page

* fix(admin): route topics page fetches through basePath

The Topics page missed two fetch() calls that still used root-relative
URLs, so create-topic and view-details still broke when -urlPrefix was
set.

---------

Co-authored-by: Maksim Babkou <maksim.babkou@innovatrics.com>
Co-authored-by: Chris Lu <chris.lu@gmail.com>
This commit is contained in:
authored and GitHub committed 2026-04-23 11:55:07 -07:00
1 parent 749430dceb
commit 0fcd5173be
12 files changed
+148 -148

No files matched your search

+7 -8
View File
@@ -231,7 +231,6 @@ templ Groups(data dash.GroupsPageData) {
</div>
</div>
<script src="/static/js/iam-utils.js"></script>
<script>
// Groups page JavaScript
let currentGroupName = '';
@@ -243,7 +242,7 @@ templ Groups(data dash.GroupsPageData) {
return;
}
try {
const response = await fetch('/api/groups', {
const response = await fetch(basePath('/api/groups'), {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: name })
@@ -269,7 +268,7 @@ templ Groups(data dash.GroupsPageData) {
async function refreshGroupDetails(requestedName) {
try {
const response = await fetch('/api/groups/' + encodeURIComponent(requestedName));
const response = await fetch(basePath('/api/groups/' + encodeURIComponent(requestedName)));
if (!response.ok) throw new Error('Failed to fetch group');
if (requestedName !== currentGroupName) return; // stale response
const group = await response.json();
@@ -339,7 +338,7 @@ templ Groups(data dash.GroupsPageData) {
const username = document.getElementById('addMemberSelect').value;
if (!username) return;
try {
const response = await fetch('/api/groups/' + encodeURIComponent(currentGroupName) + '/members', {
const response = await fetch(basePath('/api/groups/' + encodeURIComponent(currentGroupName) + '/members'), {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: username })
@@ -358,7 +357,7 @@ templ Groups(data dash.GroupsPageData) {
async function removeMember(username) {
try {
const response = await fetch('/api/groups/' + encodeURIComponent(currentGroupName) + '/members/' + encodeURIComponent(username), {
const response = await fetch(basePath('/api/groups/' + encodeURIComponent(currentGroupName) + '/members/' + encodeURIComponent(username)), {
method: 'DELETE'
});
if (response.ok) {
@@ -377,7 +376,7 @@ templ Groups(data dash.GroupsPageData) {
const policyName = document.getElementById('attachPolicySelect').value;
if (!policyName) return;
try {
const response = await fetch('/api/groups/' + encodeURIComponent(currentGroupName) + '/policies', {
const response = await fetch(basePath('/api/groups/' + encodeURIComponent(currentGroupName) + '/policies'), {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ policy_name: policyName })
@@ -396,7 +395,7 @@ templ Groups(data dash.GroupsPageData) {
async function detachPolicy(policyName) {
try {
const response = await fetch('/api/groups/' + encodeURIComponent(currentGroupName) + '/policies/' + encodeURIComponent(policyName), {
const response = await fetch(basePath('/api/groups/' + encodeURIComponent(currentGroupName) + '/policies/' + encodeURIComponent(policyName)), {
method: 'DELETE'
});
if (response.ok) {
@@ -414,7 +413,7 @@ templ Groups(data dash.GroupsPageData) {
async function toggleGroupStatus() {
const enabled = document.getElementById('groupEnabledSwitch').checked;
try {
const response = await fetch('/api/groups/' + encodeURIComponent(currentGroupName) + '/status', {
const response = await fetch(basePath('/api/groups/' + encodeURIComponent(currentGroupName) + '/status'), {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ enabled: enabled })
+17 -17
View File
@@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.977
// templ: version: v0.3.1001
package app
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@@ -41,7 +41,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalGroups))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/groups.templ`, Line: 38, Col: 72}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/groups.templ`, Line: 38, Col: 72}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
@@ -54,7 +54,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.ActiveGroups))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/groups.templ`, Line: 57, Col: 73}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/groups.templ`, Line: 57, Col: 73}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
@@ -82,7 +82,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(group.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/groups.templ`, Line: 96, Col: 63}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/groups.templ`, Line: 96, Col: 63}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
@@ -95,7 +95,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", group.MemberCount))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/groups.templ`, Line: 99, Col: 109}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/groups.templ`, Line: 99, Col: 109}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
@@ -108,7 +108,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", group.PolicyCount))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/groups.templ`, Line: 102, Col: 114}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/groups.templ`, Line: 102, Col: 114}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
@@ -136,7 +136,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(group.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/groups.templ`, Line: 113, Col: 79}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/groups.templ`, Line: 113, Col: 79}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
@@ -149,7 +149,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs("View group " + group.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/groups.templ`, Line: 115, Col: 90}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/groups.templ`, Line: 115, Col: 90}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
@@ -162,7 +162,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs("View " + group.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/groups.templ`, Line: 116, Col: 79}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/groups.templ`, Line: 116, Col: 79}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
@@ -175,7 +175,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(group.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/groups.templ`, Line: 120, Col: 79}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/groups.templ`, Line: 120, Col: 79}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
@@ -188,7 +188,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs("Delete group " + group.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/groups.templ`, Line: 122, Col: 92}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/groups.templ`, Line: 122, Col: 92}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
@@ -201,7 +201,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs("Delete " + group.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/groups.templ`, Line: 123, Col: 81}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/groups.templ`, Line: 123, Col: 81}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
@@ -229,7 +229,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(user)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/groups.templ`, Line: 189, Col: 67}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/groups.templ`, Line: 189, Col: 67}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
@@ -242,7 +242,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(user)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/groups.templ`, Line: 189, Col: 74}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/groups.templ`, Line: 189, Col: 74}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil {
@@ -265,7 +265,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(policy)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/groups.templ`, Line: 206, Col: 69}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/groups.templ`, Line: 206, Col: 69}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil {
@@ -278,7 +278,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
var templ_7745c5c3_Var16 string
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(policy)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/groups.templ`, Line: 206, Col: 78}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/groups.templ`, Line: 206, Col: 78}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
if templ_7745c5c3_Err != nil {
@@ -289,7 +289,7 @@ func Groups(data dash.GroupsPageData) templ.Component {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</select> <button class=\"btn btn-outline-primary\" type=\"button\" onclick=\"attachPolicyToGroup()\"><i class=\"fas fa-plus\"></i> Attach</button></div></div><div id=\"policiesList\"></div></div><!-- Settings Tab --><div class=\"tab-pane fade\" id=\"settingsPane\" role=\"tabpanel\"><div class=\"form-check form-switch mb-3\"><input class=\"form-check-input\" type=\"checkbox\" id=\"groupEnabledSwitch\" checked onchange=\"toggleGroupStatus()\"> <label class=\"form-check-label\" for=\"groupEnabledSwitch\">Group Enabled</label></div></div></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Close</button></div></div></div></div></div><script src=\"/static/js/iam-utils.js\"></script><script>\n // Groups page JavaScript\n let currentGroupName = '';\n\n async function createGroup() {\n const name = document.getElementById('groupName').value.trim();\n if (!name) {\n showAlert('Group name is required', 'error');\n return;\n }\n try {\n const response = await fetch('/api/groups', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name: name })\n });\n if (response.ok) {\n showAlert('Group created successfully', 'success');\n setTimeout(() => window.location.reload(), 1000);\n } else {\n const error = await response.json().catch(() => ({}));\n showAlert('Failed to create group: ' + (error.error || 'Unknown error'), 'error');\n }\n } catch (error) {\n showAlert('Failed to create group: ' + error.message, 'error');\n }\n }\n\n async function viewGroup(name) {\n currentGroupName = name;\n document.getElementById('viewGroupTitle').textContent = 'Group: ' + name;\n await refreshGroupDetails(name);\n new bootstrap.Modal(document.getElementById('viewGroupModal')).show();\n }\n\n async function refreshGroupDetails(requestedName) {\n try {\n const response = await fetch('/api/groups/' + encodeURIComponent(requestedName));\n if (!response.ok) throw new Error('Failed to fetch group');\n if (requestedName !== currentGroupName) return; // stale response\n const group = await response.json();\n\n // Render members using DOM APIs to prevent XSS\n const membersList = document.getElementById('membersList');\n membersList.innerHTML = '';\n const membersTable = document.createElement('table');\n membersTable.className = 'table table-sm';\n const membersTbody = document.createElement('tbody');\n if (group.members && group.members.length > 0) {\n for (const member of group.members) {\n const tr = membersTbody.insertRow();\n const td1 = tr.insertCell();\n td1.textContent = member;\n const td2 = tr.insertCell();\n const btn = document.createElement('button');\n btn.className = 'btn btn-sm btn-outline-danger';\n btn.onclick = () => removeMember(member);\n btn.innerHTML = '<i class=\"fas fa-times\"></i>';\n td2.appendChild(btn);\n }\n } else {\n const tr = membersTbody.insertRow();\n const td = tr.insertCell();\n td.className = 'text-muted';\n td.textContent = 'No members';\n }\n membersTable.appendChild(membersTbody);\n membersList.appendChild(membersTable);\n\n // Render policies using DOM APIs to prevent XSS\n const policiesList = document.getElementById('policiesList');\n policiesList.innerHTML = '';\n const policiesTable = document.createElement('table');\n policiesTable.className = 'table table-sm';\n const policiesTbody = document.createElement('tbody');\n if (group.policy_names && group.policy_names.length > 0) {\n for (const policy of group.policy_names) {\n const tr = policiesTbody.insertRow();\n const td1 = tr.insertCell();\n td1.textContent = policy;\n const td2 = tr.insertCell();\n const btn = document.createElement('button');\n btn.classNLine truncated
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</select> <button class=\"btn btn-outline-primary\" type=\"button\" onclick=\"attachPolicyToGroup()\"><i class=\"fas fa-plus\"></i> Attach</button></div></div><div id=\"policiesList\"></div></div><!-- Settings Tab --><div class=\"tab-pane fade\" id=\"settingsPane\" role=\"tabpanel\"><div class=\"form-check form-switch mb-3\"><input class=\"form-check-input\" type=\"checkbox\" id=\"groupEnabledSwitch\" checked onchange=\"toggleGroupStatus()\"> <label class=\"form-check-label\" for=\"groupEnabledSwitch\">Group Enabled</label></div></div></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Close</button></div></div></div></div></div><script>\n // Groups page JavaScript\n let currentGroupName = '';\n\n async function createGroup() {\n const name = document.getElementById('groupName').value.trim();\n if (!name) {\n showAlert('Group name is required', 'error');\n return;\n }\n try {\n const response = await fetch(basePath('/api/groups'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name: name })\n });\n if (response.ok) {\n showAlert('Group created successfully', 'success');\n setTimeout(() => window.location.reload(), 1000);\n } else {\n const error = await response.json().catch(() => ({}));\n showAlert('Failed to create group: ' + (error.error || 'Unknown error'), 'error');\n }\n } catch (error) {\n showAlert('Failed to create group: ' + error.message, 'error');\n }\n }\n\n async function viewGroup(name) {\n currentGroupName = name;\n document.getElementById('viewGroupTitle').textContent = 'Group: ' + name;\n await refreshGroupDetails(name);\n new bootstrap.Modal(document.getElementById('viewGroupModal')).show();\n }\n\n async function refreshGroupDetails(requestedName) {\n try {\n const response = await fetch(basePath('/api/groups/' + encodeURIComponent(requestedName)));\n if (!response.ok) throw new Error('Failed to fetch group');\n if (requestedName !== currentGroupName) return; // stale response\n const group = await response.json();\n\n // Render members using DOM APIs to prevent XSS\n const membersList = document.getElementById('membersList');\n membersList.innerHTML = '';\n const membersTable = document.createElement('table');\n membersTable.className = 'table table-sm';\n const membersTbody = document.createElement('tbody');\n if (group.members && group.members.length > 0) {\n for (const member of group.members) {\n const tr = membersTbody.insertRow();\n const td1 = tr.insertCell();\n td1.textContent = member;\n const td2 = tr.insertCell();\n const btn = document.createElement('button');\n btn.className = 'btn btn-sm btn-outline-danger';\n btn.onclick = () => removeMember(member);\n btn.innerHTML = '<i class=\"fas fa-times\"></i>';\n td2.appendChild(btn);\n }\n } else {\n const tr = membersTbody.insertRow();\n const td = tr.insertCell();\n td.className = 'text-muted';\n td.textContent = 'No members';\n }\n membersTable.appendChild(membersTbody);\n membersList.appendChild(membersTable);\n\n // Render policies using DOM APIs to prevent XSS\n const policiesList = document.getElementById('policiesList');\n policiesList.innerHTML = '';\n const policiesTable = document.createElement('table');\n policiesTable.className = 'table table-sm';\n const policiesTbody = document.createElement('tbody');\n if (group.policy_names && group.policy_names.length > 0) {\n for (const policy of group.policy_names) {\n const tr = policiesTbody.insertRow();\n const td1 = tr.insertCell();\n td1.textContent = policy;\n const td2 = tr.insertCell();\n const btn = document.createElement('button');\n btn.className = 'btn btn-sm btn-outlineLine truncated
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
+18 -17
View File
@@ -504,6 +504,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
const STATUS_ACTIVE = 'Active';
const STATUS_INACTIVE = 'Inactive';
// Use basePath() from admin.js for -urlPrefix; it is loaded in the layout footer before DOMContentLoaded fires.
document.addEventListener('DOMContentLoaded', function() {
// Event delegation for user action buttons
@@ -591,7 +592,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
// Load buckets
async function loadBuckets() {
try {
const response = await fetch('/api/s3/buckets');
const response = await fetch(basePath('/api/s3/buckets'));
if (response.ok) {
const data = await response.json();
availableBuckets = (data.buckets || []).map(bucket => ({ name: bucket.name, type: 's3' }));
@@ -605,7 +606,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
availableBuckets = [];
}
try {
const response = await fetch('/api/s3tables/buckets');
const response = await fetch(basePath('/api/s3tables/buckets'));
if (response.ok) {
const data = await response.json();
const tableBuckets = (data.buckets || data.tableBuckets || []).map(bucket => ({ name: bucket.name, type: 's3tables' }));
@@ -623,7 +624,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
// Load policies
async function loadPolicies() {
try {
const response = await fetch('/api/object-store/policies');
const response = await fetch(basePath('/api/object-store/policies'));
if (response.ok) {
const data = await response.json();
const policies = data.policies || [];
@@ -910,7 +911,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
async function showUserDetails(username) {
try {
const encodedUsername = encodeURIComponent(username);
const response = await fetch(`/api/users/${encodedUsername}`);
const response = await fetch(basePath(`/api/users/${encodedUsername}`));
if (response.ok) {
const user = await response.json();
document.getElementById('userDetailsContent').innerHTML = createUserDetailsContent(user);
@@ -929,7 +930,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
async function editUser(username) {
try {
const encodedUsername = encodeURIComponent(username);
const response = await fetch(`/api/users/${encodedUsername}`);
const response = await fetch(basePath(`/api/users/${encodedUsername}`));
if (response.ok) {
const user = await response.json();
@@ -1008,7 +1009,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
async function manageAccessKeys(username) {
try {
const encodedUsername = encodeURIComponent(username);
const response = await fetch(`/api/users/${encodedUsername}`);
const response = await fetch(basePath(`/api/users/${encodedUsername}`));
if (response.ok) {
const user = await response.json();
document.getElementById('accessKeysUsername').textContent = username;
@@ -1029,7 +1030,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
showDeleteConfirm(username, async function() {
try {
const encodedUsername = encodeURIComponent(username);
const response = await fetch(`/api/users/${encodedUsername}`, {
const response = await fetch(basePath(`/api/users/${encodedUsername}`), {
method: 'DELETE'
});
@@ -1074,7 +1075,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
};
try {
const response = await fetch('/api/users', {
const response = await fetch(basePath('/api/users'), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -1118,13 +1119,13 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
try {
// Fetch all groups
const groupsResp = await fetch('/api/groups');
const groupsResp = await fetch(basePath('/api/groups'));
if (!groupsResp.ok) return;
const groupsData = await groupsResp.json();
const allGroups = groupsData.groups || [];
// Fetch user details to get current groups
const userResp = await fetch(`/api/users/${encodeURIComponent(username)}`);
const userResp = await fetch(basePath(`/api/users/${encodeURIComponent(username)}`));
if (!userResp.ok) return;
const user = await userResp.json();
const userGroups = user.groups || [];
@@ -1172,7 +1173,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
if (!groupName) return;
try {
const response = await fetch(`/api/groups/${encodeURIComponent(groupName)}/members`, {
const response = await fetch(basePath(`/api/groups/${encodeURIComponent(groupName)}/members`), {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: username })
@@ -1192,7 +1193,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
async function removeUserFromGroupInEdit(groupName) {
const username = document.getElementById('editUsername').value;
try {
const response = await fetch(`/api/groups/${encodeURIComponent(groupName)}/members/${encodeURIComponent(username)}`, {
const response = await fetch(basePath(`/api/groups/${encodeURIComponent(groupName)}/members/${encodeURIComponent(username)}`), {
method: 'DELETE'
});
if (response.ok) {
@@ -1237,7 +1238,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
try {
const encodedUsername = encodeURIComponent(username);
const response = await fetch(`/api/users/${encodedUsername}`, {
const response = await fetch(basePath(`/api/users/${encodedUsername}`), {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
@@ -1374,7 +1375,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
async function refreshAccessKeysList(username) {
try {
const encodedUsername = encodeURIComponent(username);
const response = await fetch(`/api/users/${encodedUsername}`);
const response = await fetch(basePath(`/api/users/${encodedUsername}`));
if (response.ok) {
const user = await response.json();
document.getElementById('accessKeysContent').innerHTML = createAccessKeysContent(user);
@@ -1387,7 +1388,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
// Update access key status
async function updateAccessKeyStatus(username, accessKey, status) {
try {
const response = await fetch(`/api/users/${encodeURIComponent(username)}/access-keys/${encodeURIComponent(accessKey)}/status`, {
const response = await fetch(basePath(`/api/users/${encodeURIComponent(username)}/access-keys/${encodeURIComponent(accessKey)}/status`), {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
@@ -1473,7 +1474,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
try {
const encodedUsername = encodeURIComponent(username);
const response = await fetch(`/api/users/${encodedUsername}/access-keys`, {
const response = await fetch(basePath(`/api/users/${encodedUsername}/access-keys`), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -1514,7 +1515,7 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) {
try {
const encodedUsername = encodeURIComponent(username);
const encodedAccessKey = encodeURIComponent(accessKey);
const response = await fetch(`/api/users/${encodedUsername}/access-keys/${encodedAccessKey}`, {
const response = await fetch(basePath(`/api/users/${encodedUsername}/access-keys/${encodedAccessKey}`), {
method: 'DELETE'
});
+13 -13
View File
@@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.977
// templ: version: v0.3.1001
package app
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@@ -41,7 +41,7 @@ func ObjectStoreUsers(data dash.ObjectStoreUsersData) templ.Component {
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalUsers))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/object_store_users.templ`, Line: 38, Col: 71}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 38, Col: 71}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
@@ -54,7 +54,7 @@ func ObjectStoreUsers(data dash.ObjectStoreUsersData) templ.Component {
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", len(data.Users)))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/object_store_users.templ`, Line: 58, Col: 71}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 58, Col: 71}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
@@ -67,7 +67,7 @@ func ObjectStoreUsers(data dash.ObjectStoreUsersData) templ.Component {
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("15:04"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/object_store_users.templ`, Line: 78, Col: 69}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 78, Col: 69}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
@@ -85,7 +85,7 @@ func ObjectStoreUsers(data dash.ObjectStoreUsersData) templ.Component {
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/object_store_users.templ`, Line: 127, Col: 74}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 127, Col: 74}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
@@ -108,7 +108,7 @@ func ObjectStoreUsers(data dash.ObjectStoreUsersData) templ.Component {
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(user.Email)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/object_store_users.templ`, Line: 133, Col: 59}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 133, Col: 59}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
@@ -121,7 +121,7 @@ func ObjectStoreUsers(data dash.ObjectStoreUsersData) templ.Component {
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(user.AccessKey)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/object_store_users.templ`, Line: 135, Col: 88}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 135, Col: 88}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
@@ -134,7 +134,7 @@ func ObjectStoreUsers(data dash.ObjectStoreUsersData) templ.Component {
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/object_store_users.templ`, Line: 140, Col: 121}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 140, Col: 121}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
@@ -152,7 +152,7 @@ func ObjectStoreUsers(data dash.ObjectStoreUsersData) templ.Component {
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/object_store_users.templ`, Line: 145, Col: 117}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 145, Col: 117}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
@@ -171,7 +171,7 @@ func ObjectStoreUsers(data dash.ObjectStoreUsersData) templ.Component {
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/object_store_users.templ`, Line: 151, Col: 126}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 151, Col: 126}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
@@ -190,7 +190,7 @@ func ObjectStoreUsers(data dash.ObjectStoreUsersData) templ.Component {
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/object_store_users.templ`, Line: 157, Col: 119}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 157, Col: 119}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
@@ -219,7 +219,7 @@ func ObjectStoreUsers(data dash.ObjectStoreUsersData) templ.Component {
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("2006-01-02 15:04:05"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/object_store_users.templ`, Line: 189, Col: 81}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 189, Col: 81}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
@@ -240,7 +240,7 @@ func ObjectStoreUsers(data dash.ObjectStoreUsersData) templ.Component {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</div><div class=\"mb-3\"><label for=\"email\" class=\"form-label\">Email</label> <input type=\"email\" class=\"form-control\" id=\"email\" name=\"email\"></div><div class=\"mb-3\"><label for=\"actions\" class=\"form-label\">Permissions</label> <select multiple class=\"form-control\" id=\"actions\" name=\"actions\" size=\"10\"><option value=\"Admin\">Admin (Full Access)</option> <option value=\"Read\">Read</option> <option value=\"Write\">Write</option> <option value=\"List\">List</option> <option value=\"Tagging\">Tagging</option> <optgroup label=\"Object Lock Permissions\"><option value=\"BypassGovernanceRetention\">Bypass Governance Retention</option> <option value=\"GetObjectRetention\">Get Object Retention</option> <option value=\"PutObjectRetention\">Put Object Retention</option> <option value=\"GetObjectLegalHold\">Get Object Legal Hold</option> <option value=\"PutObjectLegalHold\">Put Object Legal Hold</option> <option value=\"GetBucketObjectLockConfiguration\">Get Bucket Object Lock Configuration</option> <option value=\"PutBucketObjectLockConfiguration\">Put Bucket Object Lock Configuration</option></optgroup> <optgroup label=\"S3 Tables Permissions\"><option value=\"S3TablesAdmin\">S3 Tables Admin (Full Access)</option> <option value=\"CreateTableBucket\">Create Table Bucket</option> <option value=\"GetTableBucket\">Get Table Bucket</option> <option value=\"ListTableBuckets\">List Table Buckets</option> <option value=\"DeleteTableBucket\">Delete Table Bucket</option> <option value=\"PutTableBucketPolicy\">Put Table Bucket Policy</option> <option value=\"GetTableBucketPolicy\">Get Table Bucket Policy</option> <option value=\"DeleteTableBucketPolicy\">Delete Table Bucket Policy</option> <option value=\"CreateNamespace\">Create Namespace</option> <option value=\"GetNamespace\">Get Namespace</option> <option value=\"ListNamespaces\">List Namespaces</option> <option value=\"DeleteNamespace\">Delete Namespace</option> <option value=\"CreateTable\">Create Table</option> <option value=\"GetTable\">Get Table</option> <option value=\"ListTables\">List Tables</option> <option value=\"DeleteTable\">Delete Table</option> <option value=\"PutTablePolicy\">Put Table Policy</option> <option value=\"GetTablePolicy\">Get Table Policy</option> <option value=\"DeleteTablePolicy\">Delete Table Policy</option> <option value=\"TagResource\">Tag Resource</option> <option value=\"ListTagsForResource\">List Tags</option> <option value=\"UntagResource\">Untag Resource</option></optgroup></select> <small class=\"form-text text-muted\">Hold Ctrl/Cmd to select multiple permissions</small></div><div class=\"mb-3\"><label class=\"form-label\">Bucket Scope</label> <small class=\"form-text text-muted d-block mb-2\">Apply selected permissions to specific buckets or all buckets</small><div class=\"form-check mb-2\"><input class=\"form-check-input\" type=\"radio\" name=\"bucketScope\" id=\"allBuckets\" value=\"all\" checked onchange=\"toggleBucketList()\"> <label class=\"form-check-label\" for=\"allBuckets\">All Buckets</label></div><div class=\"form-check mb-2\"><input class=\"form-check-input\" type=\"radio\" name=\"bucketScope\" id=\"specificBuckets\" value=\"specific\" onchange=\"toggleBucketList()\"> <label class=\"form-check-label\" for=\"specificBuckets\">Specific Buckets</label></div><div id=\"bucketSelectionList\" class=\"mt-2\" style=\"display: none;\"><select multiple class=\"form-select\" id=\"selectedBuckets\" size=\"5\"><!-- Options loaded dynamically --></select> <small class=\"form-text text-muted\">Hold Ctrl/Cmd to select multiple buckets</small></div></div><div class=\"mb-3\"><label for=\"policies\" class=\"form-label\">Attached Policies</label> <select multiple class=\"form-control\" id=\"policies\" name=\"policies\" size=\"5\"><!-- Options loaded dynamically --></select> <small class=\"form-text text-muted\">Hold Ctrl/Cmd to select multiple policies</small></div><div class=\"mb-3 form-check\"><input type=\"checkbox\" class=\"form-check-input\" id=\"generateKey\" name=\"generateKey\" checked> <label class=\"form-check-label\" for=\"generateKey\">Generate access key automatically</label></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"handleCreateUser()\">Create User</button></div></div></div></div><!-- Edit User Modal --><div class=\"modal fade\" id=\"editUserModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-user-edit me-2\"></i>Edit User</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\"><form id=\"editUserForm\"><input type=\"hidden\" id=\"editUsername\" name=\"username\"><div class=\"mb-3\"Line truncated
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</div><div class=\"mb-3\"><label for=\"email\" class=\"form-label\">Email</label> <input type=\"email\" class=\"form-control\" id=\"email\" name=\"email\"></div><div class=\"mb-3\"><label for=\"actions\" class=\"form-label\">Permissions</label> <select multiple class=\"form-control\" id=\"actions\" name=\"actions\" size=\"10\"><option value=\"Admin\">Admin (Full Access)</option> <option value=\"Read\">Read</option> <option value=\"Write\">Write</option> <option value=\"List\">List</option> <option value=\"Tagging\">Tagging</option> <optgroup label=\"Object Lock Permissions\"><option value=\"BypassGovernanceRetention\">Bypass Governance Retention</option> <option value=\"GetObjectRetention\">Get Object Retention</option> <option value=\"PutObjectRetention\">Put Object Retention</option> <option value=\"GetObjectLegalHold\">Get Object Legal Hold</option> <option value=\"PutObjectLegalHold\">Put Object Legal Hold</option> <option value=\"GetBucketObjectLockConfiguration\">Get Bucket Object Lock Configuration</option> <option value=\"PutBucketObjectLockConfiguration\">Put Bucket Object Lock Configuration</option></optgroup> <optgroup label=\"S3 Tables Permissions\"><option value=\"S3TablesAdmin\">S3 Tables Admin (Full Access)</option> <option value=\"CreateTableBucket\">Create Table Bucket</option> <option value=\"GetTableBucket\">Get Table Bucket</option> <option value=\"ListTableBuckets\">List Table Buckets</option> <option value=\"DeleteTableBucket\">Delete Table Bucket</option> <option value=\"PutTableBucketPolicy\">Put Table Bucket Policy</option> <option value=\"GetTableBucketPolicy\">Get Table Bucket Policy</option> <option value=\"DeleteTableBucketPolicy\">Delete Table Bucket Policy</option> <option value=\"CreateNamespace\">Create Namespace</option> <option value=\"GetNamespace\">Get Namespace</option> <option value=\"ListNamespaces\">List Namespaces</option> <option value=\"DeleteNamespace\">Delete Namespace</option> <option value=\"CreateTable\">Create Table</option> <option value=\"GetTable\">Get Table</option> <option value=\"ListTables\">List Tables</option> <option value=\"DeleteTable\">Delete Table</option> <option value=\"PutTablePolicy\">Put Table Policy</option> <option value=\"GetTablePolicy\">Get Table Policy</option> <option value=\"DeleteTablePolicy\">Delete Table Policy</option> <option value=\"TagResource\">Tag Resource</option> <option value=\"ListTagsForResource\">List Tags</option> <option value=\"UntagResource\">Untag Resource</option></optgroup></select> <small class=\"form-text text-muted\">Hold Ctrl/Cmd to select multiple permissions</small></div><div class=\"mb-3\"><label class=\"form-label\">Bucket Scope</label> <small class=\"form-text text-muted d-block mb-2\">Apply selected permissions to specific buckets or all buckets</small><div class=\"form-check mb-2\"><input class=\"form-check-input\" type=\"radio\" name=\"bucketScope\" id=\"allBuckets\" value=\"all\" checked onchange=\"toggleBucketList()\"> <label class=\"form-check-label\" for=\"allBuckets\">All Buckets</label></div><div class=\"form-check mb-2\"><input class=\"form-check-input\" type=\"radio\" name=\"bucketScope\" id=\"specificBuckets\" value=\"specific\" onchange=\"toggleBucketList()\"> <label class=\"form-check-label\" for=\"specificBuckets\">Specific Buckets</label></div><div id=\"bucketSelectionList\" class=\"mt-2\" style=\"display: none;\"><select multiple class=\"form-select\" id=\"selectedBuckets\" size=\"5\"><!-- Options loaded dynamically --></select> <small class=\"form-text text-muted\">Hold Ctrl/Cmd to select multiple buckets</small></div></div><div class=\"mb-3\"><label for=\"policies\" class=\"form-label\">Attached Policies</label> <select multiple class=\"form-control\" id=\"policies\" name=\"policies\" size=\"5\"><!-- Options loaded dynamically --></select> <small class=\"form-text text-muted\">Hold Ctrl/Cmd to select multiple policies</small></div><div class=\"mb-3 form-check\"><input type=\"checkbox\" class=\"form-check-input\" id=\"generateKey\" name=\"generateKey\" checked> <label class=\"form-check-label\" for=\"generateKey\">Generate access key automatically</label></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"handleCreateUser()\">Create User</button></div></div></div></div><!-- Edit User Modal --><div class=\"modal fade\" id=\"editUserModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-user-edit me-2\"></i>Edit User</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\"><form id=\"editUserForm\"><input type=\"hidden\" id=\"editUsername\" name=\"username\"><div class=\"mb-3\"Line truncated
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
+5 -5
View File
@@ -368,7 +368,7 @@ templ Policies(data dash.PoliciesData) {
document: policyDocument
};
fetch('/api/object-store/policies', {
fetch(basePath('/api/object-store/policies'), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -408,7 +408,7 @@ templ Policies(data dash.PoliciesData) {
`;
// Fetch policy data
fetch('/api/object-store/policies/' + encodeURIComponent(policyName))
fetch(basePath('/api/object-store/policies/' + encodeURIComponent(policyName)))
.then(response => {
if (!response.ok) {
throw new Error('Policy not found');
@@ -494,7 +494,7 @@ templ Policies(data dash.PoliciesData) {
document.getElementById('editPolicyDocument').value = 'Loading...';
// Fetch policy data
fetch('/api/object-store/policies/' + encodeURIComponent(policyName))
fetch(basePath('/api/object-store/policies/' + encodeURIComponent(policyName)))
.then(response => {
if (!response.ok) {
throw new Error('Policy not found');
@@ -534,7 +534,7 @@ templ Policies(data dash.PoliciesData) {
document: policyDocument
};
fetch('/api/object-store/policies/' + encodeURIComponent(policyName), {
fetch(basePath('/api/object-store/policies/' + encodeURIComponent(policyName)), {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
@@ -636,7 +636,7 @@ templ Policies(data dash.PoliciesData) {
function deletePolicy(policyName) {
showDeleteConfirm(policyName, function() {
fetch('/api/object-store/policies/' + encodeURIComponent(policyName), {
fetch(basePath('/api/object-store/policies/' + encodeURIComponent(policyName)), {
method: 'DELETE'
})
.then(response => response.json())
+13 -13
View File
@@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.977
// templ: version: v0.3.1001
package app
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@@ -41,7 +41,7 @@ func Policies(data dash.PoliciesData) templ.Component {
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalPolicies))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/policies.templ`, Line: 34, Col: 74}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/policies.templ`, Line: 34, Col: 74}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
@@ -54,7 +54,7 @@ func Policies(data dash.PoliciesData) templ.Component {
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalPolicies))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/policies.templ`, Line: 54, Col: 74}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/policies.templ`, Line: 54, Col: 74}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
@@ -67,7 +67,7 @@ func Policies(data dash.PoliciesData) templ.Component {
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("15:04"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/policies.templ`, Line: 74, Col: 69}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/policies.templ`, Line: 74, Col: 69}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
@@ -85,7 +85,7 @@ func Policies(data dash.PoliciesData) templ.Component {
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(policy.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/policies.templ`, Line: 123, Col: 68}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/policies.templ`, Line: 123, Col: 68}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
@@ -98,7 +98,7 @@ func Policies(data dash.PoliciesData) templ.Component {
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(policy.Document.Version)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/policies.templ`, Line: 126, Col: 100}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/policies.templ`, Line: 126, Col: 100}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
@@ -111,7 +111,7 @@ func Policies(data dash.PoliciesData) templ.Component {
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d statements", len(policy.Document.Statement)))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/policies.templ`, Line: 129, Col: 142}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/policies.templ`, Line: 129, Col: 142}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
@@ -124,7 +124,7 @@ func Policies(data dash.PoliciesData) templ.Component {
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(policy.CreatedAt.Format("2006-01-02 15:04"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/policies.templ`, Line: 132, Col: 118}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/policies.templ`, Line: 132, Col: 118}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
@@ -137,7 +137,7 @@ func Policies(data dash.PoliciesData) templ.Component {
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(policy.UpdatedAt.Format("2006-01-02 15:04"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/policies.templ`, Line: 135, Col: 118}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/policies.templ`, Line: 135, Col: 118}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
@@ -150,7 +150,7 @@ func Policies(data dash.PoliciesData) templ.Component {
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(policy.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/policies.templ`, Line: 139, Col: 168}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/policies.templ`, Line: 139, Col: 168}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
@@ -163,7 +163,7 @@ func Policies(data dash.PoliciesData) templ.Component {
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(policy.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/policies.templ`, Line: 142, Col: 171}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/policies.templ`, Line: 142, Col: 171}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
@@ -176,7 +176,7 @@ func Policies(data dash.PoliciesData) templ.Component {
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(policy.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/policies.templ`, Line: 145, Col: 174}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/policies.templ`, Line: 145, Col: 174}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
@@ -193,7 +193,7 @@ func Policies(data dash.PoliciesData) templ.Component {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</tbody></table></div></div></div></div></div></div><!-- Create Policy Modal --><div class=\"modal fade\" id=\"createPolicyModal\" tabindex=\"-1\" aria-labelledby=\"createPolicyModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog modal-lg\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"createPolicyModalLabel\"><i class=\"fas fa-shield-alt me-2\"></i>Create IAM Policy</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><div class=\"modal-body\"><form id=\"createPolicyForm\"><div class=\"mb-3\"><label for=\"policyName\" class=\"form-label\">Policy Name</label> <input type=\"text\" class=\"form-control\" id=\"policyName\" name=\"name\" required placeholder=\"e.g., S3ReadOnlyPolicy\"><div class=\"form-text\">Enter a unique name for this policy (alphanumeric and underscores only)</div></div><div class=\"mb-3\"><label for=\"policyDocument\" class=\"form-label\">Policy Document</label> <textarea class=\"form-control\" id=\"policyDocument\" name=\"document\" rows=\"15\" required placeholder=\"Enter IAM policy JSON document...\"></textarea><div class=\"form-text\">Enter the policy document in AWS IAM JSON format</div></div><div class=\"mb-3\"><div class=\"row\"><div class=\"col-md-6\"><button type=\"button\" class=\"btn btn-outline-info btn-sm\" onclick=\"insertSamplePolicy()\"><i class=\"fas fa-file-alt me-1\"></i>Use Sample Policy</button></div><div class=\"col-md-6 text-end\"><button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" onclick=\"validatePolicyDocument()\"><i class=\"fas fa-check me-1\"></i>Validate JSON</button></div></div></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"createPolicy()\"><i class=\"fas fa-plus me-1\"></i>Create Policy</button></div></div></div></div><!-- View Policy Modal --><div class=\"modal fade\" id=\"viewPolicyModal\" tabindex=\"-1\" aria-labelledby=\"viewPolicyModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog modal-lg\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"viewPolicyModalLabel\"><i class=\"fas fa-eye me-2\"></i>View IAM Policy</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><div class=\"modal-body\"><div id=\"viewPolicyContent\"><div class=\"text-center\"><div class=\"spinner-border\" role=\"status\"><span class=\"visually-hidden\">Loading...</span></div><p class=\"mt-2\">Loading policy...</p></div></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Close</button> <button type=\"button\" class=\"btn btn-primary\" id=\"editFromViewBtn\"><i class=\"fas fa-edit me-1\"></i>Edit Policy</button></div></div></div></div><!-- Edit Policy Modal --><div class=\"modal fade\" id=\"editPolicyModal\" tabindex=\"-1\" aria-labelledby=\"editPolicyModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog modal-lg\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"editPolicyModalLabel\"><i class=\"fas fa-edit me-2\"></i>Edit IAM Policy</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><div class=\"modal-body\"><form id=\"editPolicyForm\"><div class=\"mb-3\"><label for=\"editPolicyName\" class=\"form-label\">Policy Name</label> <input type=\"text\" class=\"form-control\" id=\"editPolicyName\" name=\"name\" readonly><div class=\"form-text\">Policy name cannot be changed</div></div><div class=\"mb-3\"><label for=\"editPolicyDocument\" class=\"form-label\">Policy Document</label> <textarea class=\"form-control\" id=\"editPolicyDocument\" name=\"document\" rows=\"15\" required></textarea><div class=\"form-text\">Edit the policy document in AWS IAM JSON format</div></div><div class=\"mb-3\"><div class=\"row\"><div class=\"col-md-6\"><button type=\"button\" class=\"btn btn-outline-info btn-sm\" onclick=\"insertSamplePolicyEdit()\"><i class=\"fas fa-file-alt me-1\"></i>Reset to Sample</button></div><div class=\"col-md-6 text-end\"><button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" onclick=\"validateEditPolicyDocument()\"><i class=\"fas fa-check me-1\"></i>Validate JSON</button></div></div></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"updatePolicy()\"><i class=\"fas fa-save me-1\"></i>Save Changes</button></div></div></div></div><!-- JavaScript for Policy Management --><script>\n // Current policy being viewed/edited\n let currentPolicy = null;\n \n // Event listeners for policy actions\n document.adLine truncated
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</tbody></table></div></div></div></div></div></div><!-- Create Policy Modal --><div class=\"modal fade\" id=\"createPolicyModal\" tabindex=\"-1\" aria-labelledby=\"createPolicyModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog modal-lg\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"createPolicyModalLabel\"><i class=\"fas fa-shield-alt me-2\"></i>Create IAM Policy</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><div class=\"modal-body\"><form id=\"createPolicyForm\"><div class=\"mb-3\"><label for=\"policyName\" class=\"form-label\">Policy Name</label> <input type=\"text\" class=\"form-control\" id=\"policyName\" name=\"name\" required placeholder=\"e.g., S3ReadOnlyPolicy\"><div class=\"form-text\">Enter a unique name for this policy (alphanumeric and underscores only)</div></div><div class=\"mb-3\"><label for=\"policyDocument\" class=\"form-label\">Policy Document</label> <textarea class=\"form-control\" id=\"policyDocument\" name=\"document\" rows=\"15\" required placeholder=\"Enter IAM policy JSON document...\"></textarea><div class=\"form-text\">Enter the policy document in AWS IAM JSON format</div></div><div class=\"mb-3\"><div class=\"row\"><div class=\"col-md-6\"><button type=\"button\" class=\"btn btn-outline-info btn-sm\" onclick=\"insertSamplePolicy()\"><i class=\"fas fa-file-alt me-1\"></i>Use Sample Policy</button></div><div class=\"col-md-6 text-end\"><button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" onclick=\"validatePolicyDocument()\"><i class=\"fas fa-check me-1\"></i>Validate JSON</button></div></div></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"createPolicy()\"><i class=\"fas fa-plus me-1\"></i>Create Policy</button></div></div></div></div><!-- View Policy Modal --><div class=\"modal fade\" id=\"viewPolicyModal\" tabindex=\"-1\" aria-labelledby=\"viewPolicyModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog modal-lg\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"viewPolicyModalLabel\"><i class=\"fas fa-eye me-2\"></i>View IAM Policy</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><div class=\"modal-body\"><div id=\"viewPolicyContent\"><div class=\"text-center\"><div class=\"spinner-border\" role=\"status\"><span class=\"visually-hidden\">Loading...</span></div><p class=\"mt-2\">Loading policy...</p></div></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Close</button> <button type=\"button\" class=\"btn btn-primary\" id=\"editFromViewBtn\"><i class=\"fas fa-edit me-1\"></i>Edit Policy</button></div></div></div></div><!-- Edit Policy Modal --><div class=\"modal fade\" id=\"editPolicyModal\" tabindex=\"-1\" aria-labelledby=\"editPolicyModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog modal-lg\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"editPolicyModalLabel\"><i class=\"fas fa-edit me-2\"></i>Edit IAM Policy</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><div class=\"modal-body\"><form id=\"editPolicyForm\"><div class=\"mb-3\"><label for=\"editPolicyName\" class=\"form-label\">Policy Name</label> <input type=\"text\" class=\"form-control\" id=\"editPolicyName\" name=\"name\" readonly><div class=\"form-text\">Policy name cannot be changed</div></div><div class=\"mb-3\"><label for=\"editPolicyDocument\" class=\"form-label\">Policy Document</label> <textarea class=\"form-control\" id=\"editPolicyDocument\" name=\"document\" rows=\"15\" required></textarea><div class=\"form-text\">Edit the policy document in AWS IAM JSON format</div></div><div class=\"mb-3\"><div class=\"row\"><div class=\"col-md-6\"><button type=\"button\" class=\"btn btn-outline-info btn-sm\" onclick=\"insertSamplePolicyEdit()\"><i class=\"fas fa-file-alt me-1\"></i>Reset to Sample</button></div><div class=\"col-md-6 text-end\"><button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" onclick=\"validateEditPolicyDocument()\"><i class=\"fas fa-check me-1\"></i>Validate JSON</button></div></div></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"updatePolicy()\"><i class=\"fas fa-save me-1\"></i>Save Changes</button></div></div></div></div><!-- JavaScript for Policy Management --><script>\n // Current policy being viewed/edited\n let currentPolicy = null;\n \n // Event listeners for policy actions\n document.adLine truncated
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
+8 -8
View File
@@ -712,7 +712,7 @@ templ S3Buckets(data dash.S3BucketsData) {
// Only fetch if not already populated
if (ownerSelect.options.length <= 1) {
try {
const response = await fetch('/api/users');
const response = await fetch(basePath('/api/users'));
const data = await response.json();
const users = data.users || [];
@@ -756,7 +756,7 @@ templ S3Buckets(data dash.S3BucketsData) {
return;
}
fetch('/api/s3/buckets', {
fetch(basePath('/api/s3/buckets'), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -846,7 +846,7 @@ templ S3Buckets(data dash.S3BucketsData) {
quota_enabled: enabled
};
fetch(`/api/s3/buckets/${bucketName}/quota`, {
fetch(basePath(`/api/s3/buckets/${bucketName}/quota`), {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
@@ -897,7 +897,7 @@ templ S3Buckets(data dash.S3BucketsData) {
// Fetch users if not cached
try {
if (!cachedUsers) {
const response = await fetch('/api/users');
const response = await fetch(basePath('/api/users'));
const data = await response.json();
cachedUsers = data.users || [];
}
@@ -941,7 +941,7 @@ templ S3Buckets(data dash.S3BucketsData) {
const owner = document.getElementById('bucketOwnerSelect').value;
const data = { owner: owner };
fetch(`/api/s3/buckets/${bucketName}/owner`, {
fetch(basePath(`/api/s3/buckets/${bucketName}/owner`), {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
@@ -988,7 +988,7 @@ templ S3Buckets(data dash.S3BucketsData) {
detailsModalInstance.show();
// Fetch bucket details
fetch('/api/s3/buckets/' + bucketName)
fetch(basePath('/api/s3/buckets/' + bucketName))
.then(response => response.json())
.then(data => {
if (data.error) {
@@ -1017,7 +1017,7 @@ templ S3Buckets(data dash.S3BucketsData) {
const bucketName = document.getElementById('deleteBucketModal').dataset.bucketName;
if (!bucketName) return;
fetch(`/api/s3/buckets/${bucketName}`, {
fetch(basePath(`/api/s3/buckets/${bucketName}`), {
method: 'DELETE'
})
.then(response => response.json())
@@ -1172,7 +1172,7 @@ function displayBucketDetails(data) {
}
// Fetch all buckets from the API (not just the current page)
fetch('/api/s3/buckets')
fetch(basePath('/api/s3/buckets'))
.then(response => response.json())
.then(data => {
if (data.error) {
+34 -34
View File
@@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.977
// templ: version: v0.3.1001
package app
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@@ -81,7 +81,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalBuckets))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 42, Col: 73}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 42, Col: 73}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
@@ -94,7 +94,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(data.TotalSize))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 62, Col: 64}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 62, Col: 64}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
@@ -107,7 +107,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("15:04:05"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 83, Col: 72}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 83, Col: 72}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
@@ -165,7 +165,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var5 templ.SafeURL
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinURLErrs(dash.PUrl(ctx, fmt.Sprintf("/files?path=/buckets/%s", bucket.Name)))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 160, Col: 124}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 160, Col: 124}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
@@ -178,7 +178,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(bucket.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 163, Col: 64}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 163, Col: 64}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
@@ -196,7 +196,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(bucket.Owner)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 169, Col: 101}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 169, Col: 101}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
@@ -219,7 +219,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(bucket.CreatedAt.Format("2006-01-02 15:04"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 175, Col: 92}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 175, Col: 92}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
@@ -232,7 +232,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(bucket.LogicalSize))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 177, Col: 85}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 177, Col: 85}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
@@ -250,7 +250,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1fx overhead", float64(bucket.PhysicalSize)/float64(bucket.LogicalSize)))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 180, Col: 144}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 180, Col: 144}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
@@ -268,7 +268,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(bucket.PhysicalSize))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 184, Col: 81}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 184, Col: 81}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
@@ -295,7 +295,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var12).String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 1, Col: 0}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 1, Col: 0}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
@@ -308,7 +308,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(bucket.Quota))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 189, Col: 86}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 189, Col: 86}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil {
@@ -326,7 +326,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f%% used", float64(bucket.LogicalSize)/float64(bucket.Quota)*100))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 193, Col: 146}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 193, Col: 146}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil {
@@ -384,7 +384,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var16 string
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(bucket.ObjectLockMode)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 223, Col: 82}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 223, Col: 82}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
if templ_7745c5c3_Err != nil {
@@ -397,7 +397,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var17 string
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d days", bucket.ObjectLockDuration))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 223, Col: 138}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 223, Col: 138}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
if templ_7745c5c3_Err != nil {
@@ -420,7 +420,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var18 templ.SafeURL
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinURLErrs(dash.PUrl(ctx, fmt.Sprintf("/files?path=/buckets/%s", bucket.Name)))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 232, Col: 128}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 232, Col: 128}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
if templ_7745c5c3_Err != nil {
@@ -433,7 +433,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var19 string
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(bucket.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 239, Col: 89}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 239, Col: 89}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
if templ_7745c5c3_Err != nil {
@@ -446,7 +446,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var20 string
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(bucket.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 245, Col: 89}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 245, Col: 89}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
if templ_7745c5c3_Err != nil {
@@ -459,7 +459,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var21 string
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(bucket.Owner)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 246, Col: 92}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 246, Col: 92}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
if templ_7745c5c3_Err != nil {
@@ -472,7 +472,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var22 string
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(bucket.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 252, Col: 89}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 252, Col: 89}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
if templ_7745c5c3_Err != nil {
@@ -485,7 +485,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var23 string
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", getQuotaInMB(bucket.Quota)))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 253, Col: 125}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 253, Col: 125}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
if templ_7745c5c3_Err != nil {
@@ -498,7 +498,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var24 string
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%t", bucket.QuotaEnabled))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 254, Col: 118}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 254, Col: 118}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
if templ_7745c5c3_Err != nil {
@@ -511,7 +511,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var25 string
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(bucket.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 260, Col: 89}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 260, Col: 89}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
if templ_7745c5c3_Err != nil {
@@ -540,7 +540,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var26 string
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", (data.CurrentPage-1)*data.PageSize+1))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 292, Col: 101}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 292, Col: 101}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
if templ_7745c5c3_Err != nil {
@@ -553,7 +553,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var27 string
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", minInt(data.CurrentPage*data.PageSize, data.TotalBuckets)))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 292, Col: 185}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 292, Col: 185}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
if templ_7745c5c3_Err != nil {
@@ -566,7 +566,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var28 string
templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalBuckets))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 292, Col: 229}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 292, Col: 229}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
if templ_7745c5c3_Err != nil {
@@ -584,7 +584,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var29 string
templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.CurrentPage-1))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 299, Col: 142}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 299, Col: 142}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
if templ_7745c5c3_Err != nil {
@@ -613,7 +613,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var30 string
templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", i))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 315, Col: 97}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 315, Col: 97}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
if templ_7745c5c3_Err != nil {
@@ -631,7 +631,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var31 string
templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", i))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 319, Col: 129}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 319, Col: 129}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31))
if templ_7745c5c3_Err != nil {
@@ -644,7 +644,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var32 string
templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", i))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 319, Col: 152}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 319, Col: 152}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32))
if templ_7745c5c3_Err != nil {
@@ -668,7 +668,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var33 string
templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.CurrentPage+1))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 327, Col: 142}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 327, Col: 142}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33))
if templ_7745c5c3_Err != nil {
@@ -696,13 +696,13 @@ func S3Buckets(data dash.S3BucketsData) templ.Component {
var templ_7745c5c3_Var34 string
templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("2006-01-02 15:04:05"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/s3_buckets.templ`, Line: 352, Col: 81}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 352, Col: 81}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "</small></div></div></div><!-- Create Bucket Modal --><div class=\"modal fade\" id=\"createBucketModal\" tabindex=\"-1\" aria-labelledby=\"createBucketModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"createBucketModalLabel\"><i class=\"fas fa-plus me-2\"></i>Create New S3 Bucket</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><form id=\"createBucketForm\"><div class=\"modal-body\"><div class=\"mb-3\"><label for=\"bucketName\" class=\"form-label\">Bucket Name</label> <input type=\"text\" class=\"form-control\" id=\"bucketName\" name=\"name\" placeholder=\"my-bucket-name\" required pattern=\"[a-z0-9.-]+\" title=\"Bucket name must contain only lowercase letters, numbers, dots, and hyphens\"><div class=\"form-text\">Bucket names must be between 3 and 63 characters, contain only lowercase letters, numbers, dots, and hyphens.</div></div><div class=\"mb-3\"><label for=\"bucketOwner\" class=\"form-label\">Owner (Optional)</label> <select class=\"form-select\" id=\"bucketOwner\" name=\"owner\"><option value=\"\">No owner (admin-only access)</option><!-- Options will be populated dynamically when modal opens --></select><div class=\"form-text\">The S3 identity that owns this bucket. Non-admin users can only access buckets they own.</div></div><div class=\"mb-3\"><div class=\"form-check\"><input class=\"form-check-input\" type=\"checkbox\" id=\"enableQuota\" name=\"quota_enabled\"> <label class=\"form-check-label\" for=\"enableQuota\">Enable Storage Quota</label></div></div><div class=\"mb-3\" id=\"quotaSettings\" style=\"display: none;\"><div class=\"row\"><div class=\"col-md-8\"><label for=\"quotaSize\" class=\"form-label\">Quota Size</label> <input type=\"number\" class=\"form-control\" id=\"quotaSize\" name=\"quota_size\" placeholder=\"1024\" min=\"1\" step=\"1\"></div><div class=\"col-md-4\"><label for=\"quotaUnit\" class=\"form-label\">Unit</label> <select class=\"form-select\" id=\"quotaUnit\" name=\"quota_unit\"><option value=\"MB\" selected>MB</option> <option value=\"GB\">GB</option> <option value=\"TB\">TB</option></select></div></div><div class=\"form-text\">Set the maximum storage size for this bucket.</div></div><div class=\"mb-3\"><div class=\"form-check\"><input class=\"form-check-input\" type=\"checkbox\" id=\"enableVersioning\" name=\"versioning_enabled\"> <label class=\"form-check-label\" for=\"enableVersioning\">Enable Object Versioning</label></div><div class=\"form-text\">Keep multiple versions of objects in this bucket.</div></div><div class=\"mb-3\"><div class=\"form-check\"><input class=\"form-check-input\" type=\"checkbox\" id=\"enableObjectLock\" name=\"object_lock_enabled\"> <label class=\"form-check-label\" for=\"enableObjectLock\">Enable Object Lock</label></div><div class=\"form-text\">Prevent objects from being deleted or overwritten for a specified period. Automatically enables versioning.</div></div><div class=\"mb-3\" id=\"objectLockSettings\" style=\"display: none;\"><div class=\"row\"><div class=\"col-md-6\"><label for=\"objectLockMode\" class=\"form-label\">Object Lock Mode</label> <select class=\"form-select\" id=\"objectLockMode\" name=\"object_lock_mode\"><option value=\"GOVERNANCE\" selected>Governance</option> <option value=\"COMPLIANCE\">Compliance</option></select><div class=\"form-text\">Governance allows override with special permissions, Compliance is immutable.</div></div><div class=\"col-md-6\"><div class=\"form-check mb-3\"><input class=\"form-check-input\" type=\"checkbox\" id=\"setDefaultRetention\" name=\"set_default_retention\"> <label class=\"form-check-label\" for=\"setDefaultRetention\">Set Default Retention</label><div class=\"form-text\">Apply default retention to all new objects in this bucket.</div></div><div id=\"defaultRetentionSettings\" style=\"display: none;\"><label for=\"objectLockDuration\" class=\"form-label\">Default Retention (days)</label> <input type=\"number\" class=\"form-control\" id=\"objectLockDuration\" name=\"object_lock_duration\" placeholder=\"30\" min=\"1\" max=\"36500\" step=\"1\"><div class=\"form-text\">Default retention period for new objects (1-36500 days).</div></div></div></div></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"submit\" class=\"btn btn-primary\"><i class=\"fas fa-plus me-1\"></i>Create Bucket</button></div></form></div></div></div><!-- Delete Confirmation Modal --><div class=\"modal fade\" id=\"deleteBucketModal\" tabindex=\"-1\" aria-labelledby=\"deleteBucketModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"deleteBucketModalLabel\"><i class=\"fas fa-exclamation-triangle me-2 text-Line truncated
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "</small></div></div></div><!-- Create Bucket Modal --><div class=\"modal fade\" id=\"createBucketModal\" tabindex=\"-1\" aria-labelledby=\"createBucketModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"createBucketModalLabel\"><i class=\"fas fa-plus me-2\"></i>Create New S3 Bucket</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><form id=\"createBucketForm\"><div class=\"modal-body\"><div class=\"mb-3\"><label for=\"bucketName\" class=\"form-label\">Bucket Name</label> <input type=\"text\" class=\"form-control\" id=\"bucketName\" name=\"name\" placeholder=\"my-bucket-name\" required pattern=\"[a-z0-9.-]+\" title=\"Bucket name must contain only lowercase letters, numbers, dots, and hyphens\"><div class=\"form-text\">Bucket names must be between 3 and 63 characters, contain only lowercase letters, numbers, dots, and hyphens.</div></div><div class=\"mb-3\"><label for=\"bucketOwner\" class=\"form-label\">Owner (Optional)</label> <select class=\"form-select\" id=\"bucketOwner\" name=\"owner\"><option value=\"\">No owner (admin-only access)</option><!-- Options will be populated dynamically when modal opens --></select><div class=\"form-text\">The S3 identity that owns this bucket. Non-admin users can only access buckets they own.</div></div><div class=\"mb-3\"><div class=\"form-check\"><input class=\"form-check-input\" type=\"checkbox\" id=\"enableQuota\" name=\"quota_enabled\"> <label class=\"form-check-label\" for=\"enableQuota\">Enable Storage Quota</label></div></div><div class=\"mb-3\" id=\"quotaSettings\" style=\"display: none;\"><div class=\"row\"><div class=\"col-md-8\"><label for=\"quotaSize\" class=\"form-label\">Quota Size</label> <input type=\"number\" class=\"form-control\" id=\"quotaSize\" name=\"quota_size\" placeholder=\"1024\" min=\"1\" step=\"1\"></div><div class=\"col-md-4\"><label for=\"quotaUnit\" class=\"form-label\">Unit</label> <select class=\"form-select\" id=\"quotaUnit\" name=\"quota_unit\"><option value=\"MB\" selected>MB</option> <option value=\"GB\">GB</option> <option value=\"TB\">TB</option></select></div></div><div class=\"form-text\">Set the maximum storage size for this bucket.</div></div><div class=\"mb-3\"><div class=\"form-check\"><input class=\"form-check-input\" type=\"checkbox\" id=\"enableVersioning\" name=\"versioning_enabled\"> <label class=\"form-check-label\" for=\"enableVersioning\">Enable Object Versioning</label></div><div class=\"form-text\">Keep multiple versions of objects in this bucket.</div></div><div class=\"mb-3\"><div class=\"form-check\"><input class=\"form-check-input\" type=\"checkbox\" id=\"enableObjectLock\" name=\"object_lock_enabled\"> <label class=\"form-check-label\" for=\"enableObjectLock\">Enable Object Lock</label></div><div class=\"form-text\">Prevent objects from being deleted or overwritten for a specified period. Automatically enables versioning.</div></div><div class=\"mb-3\" id=\"objectLockSettings\" style=\"display: none;\"><div class=\"row\"><div class=\"col-md-6\"><label for=\"objectLockMode\" class=\"form-label\">Object Lock Mode</label> <select class=\"form-select\" id=\"objectLockMode\" name=\"object_lock_mode\"><option value=\"GOVERNANCE\" selected>Governance</option> <option value=\"COMPLIANCE\">Compliance</option></select><div class=\"form-text\">Governance allows override with special permissions, Compliance is immutable.</div></div><div class=\"col-md-6\"><div class=\"form-check mb-3\"><input class=\"form-check-input\" type=\"checkbox\" id=\"setDefaultRetention\" name=\"set_default_retention\"> <label class=\"form-check-label\" for=\"setDefaultRetention\">Set Default Retention</label><div class=\"form-text\">Apply default retention to all new objects in this bucket.</div></div><div id=\"defaultRetentionSettings\" style=\"display: none;\"><label for=\"objectLockDuration\" class=\"form-label\">Default Retention (days)</label> <input type=\"number\" class=\"form-control\" id=\"objectLockDuration\" name=\"object_lock_duration\" placeholder=\"30\" min=\"1\" max=\"36500\" step=\"1\"><div class=\"form-text\">Default retention period for new objects (1-36500 days).</div></div></div></div></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"submit\" class=\"btn btn-primary\"><i class=\"fas fa-plus me-1\"></i>Create Bucket</button></div></form></div></div></div><!-- Delete Confirmation Modal --><div class=\"modal fade\" id=\"deleteBucketModal\" tabindex=\"-1\" aria-labelledby=\"deleteBucketModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"deleteBucketModalLabel\"><i class=\"fas fa-exclamation-triangle me-2 text-Line truncated
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
+4 -4
View File
@@ -336,7 +336,7 @@ templ ServiceAccounts(data dash.ServiceAccountsData) {
async function showSADetails(id) {
try {
const encodedId = encodeURIComponent(id);
const response = await fetch(`/api/service-accounts/${encodedId}`);
const response = await fetch(basePath(`/api/service-accounts/${encodedId}`));
if (response.ok) {
const sa = await response.json();
document.getElementById('saDetailsContent').innerHTML = createSADetailsContent(sa);
@@ -355,7 +355,7 @@ templ ServiceAccounts(data dash.ServiceAccountsData) {
const newStatus = currentStatus === 'Active' ? 'Inactive' : 'Active';
try {
const encodedId = encodeURIComponent(id);
const response = await fetch(`/api/service-accounts/${encodedId}`, {
const response = await fetch(basePath(`/api/service-accounts/${encodedId}`), {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ status: newStatus })
@@ -378,7 +378,7 @@ templ ServiceAccounts(data dash.ServiceAccountsData) {
showDeleteConfirm(id, async function() {
try {
const encodedId = encodeURIComponent(id);
const response = await fetch(`/api/service-accounts/${encodedId}`, {
const response = await fetch(basePath(`/api/service-accounts/${encodedId}`), {
method: 'DELETE'
});
@@ -427,7 +427,7 @@ templ ServiceAccounts(data dash.ServiceAccountsData) {
}
try {
const response = await fetch('/api/service-accounts', {
const response = await fetch(basePath('/api/service-accounts'), {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(saData)
+16 -16
View File
@@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.977
// templ: version: v0.3.1001
package app
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@@ -41,7 +41,7 @@ func ServiceAccounts(data dash.ServiceAccountsData) templ.Component {
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalAccounts))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/service_accounts.templ`, Line: 38, Col: 74}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/service_accounts.templ`, Line: 38, Col: 74}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
@@ -54,7 +54,7 @@ func ServiceAccounts(data dash.ServiceAccountsData) templ.Component {
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.ActiveAccounts))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/service_accounts.templ`, Line: 58, Col: 75}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/service_accounts.templ`, Line: 58, Col: 75}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
@@ -67,7 +67,7 @@ func ServiceAccounts(data dash.ServiceAccountsData) templ.Component {
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("15:04"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/service_accounts.templ`, Line: 78, Col: 69}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/service_accounts.templ`, Line: 78, Col: 69}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
@@ -85,7 +85,7 @@ func ServiceAccounts(data dash.ServiceAccountsData) templ.Component {
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(sa.ID)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/service_accounts.templ`, Line: 118, Col: 64}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/service_accounts.templ`, Line: 118, Col: 64}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
@@ -98,7 +98,7 @@ func ServiceAccounts(data dash.ServiceAccountsData) templ.Component {
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(sa.ParentUser)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/service_accounts.templ`, Line: 123, Col: 62}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/service_accounts.templ`, Line: 123, Col: 62}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
@@ -111,7 +111,7 @@ func ServiceAccounts(data dash.ServiceAccountsData) templ.Component {
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(sa.AccessKeyId)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/service_accounts.templ`, Line: 126, Col: 88}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/service_accounts.templ`, Line: 126, Col: 88}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
@@ -139,7 +139,7 @@ func ServiceAccounts(data dash.ServiceAccountsData) templ.Component {
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(sa.CreateDate.Format("2006-01-02"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/service_accounts.templ`, Line: 135, Col: 83}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/service_accounts.templ`, Line: 135, Col: 83}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
@@ -152,7 +152,7 @@ func ServiceAccounts(data dash.ServiceAccountsData) templ.Component {
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(sa.ID)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/service_accounts.templ`, Line: 139, Col: 108}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/service_accounts.templ`, Line: 139, Col: 108}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
@@ -165,7 +165,7 @@ func ServiceAccounts(data dash.ServiceAccountsData) templ.Component {
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(sa.ID)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/service_accounts.templ`, Line: 143, Col: 109}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/service_accounts.templ`, Line: 143, Col: 109}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
@@ -178,7 +178,7 @@ func ServiceAccounts(data dash.ServiceAccountsData) templ.Component {
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(sa.Status)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/service_accounts.templ`, Line: 143, Col: 143}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/service_accounts.templ`, Line: 143, Col: 143}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
@@ -206,7 +206,7 @@ func ServiceAccounts(data dash.ServiceAccountsData) templ.Component {
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(sa.ID)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/service_accounts.templ`, Line: 151, Col: 102}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/service_accounts.templ`, Line: 151, Col: 102}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
@@ -230,7 +230,7 @@ func ServiceAccounts(data dash.ServiceAccountsData) templ.Component {
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("2006-01-02 15:04:05"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/service_accounts.templ`, Line: 182, Col: 81}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/service_accounts.templ`, Line: 182, Col: 81}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
@@ -248,7 +248,7 @@ func ServiceAccounts(data dash.ServiceAccountsData) templ.Component {
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(user)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/service_accounts.templ`, Line: 205, Col: 56}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/service_accounts.templ`, Line: 205, Col: 56}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil {
@@ -261,7 +261,7 @@ func ServiceAccounts(data dash.ServiceAccountsData) templ.Component {
var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(user)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/service_accounts.templ`, Line: 205, Col: 65}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/service_accounts.templ`, Line: 205, Col: 65}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil {
@@ -272,7 +272,7 @@ func ServiceAccounts(data dash.ServiceAccountsData) templ.Component {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</select> <small class=\"form-text text-muted\">The service account will inherit permissions from this user</small></div><div class=\"mb-3\"><label for=\"description\" class=\"form-label\">Description</label> <textarea class=\"form-control\" id=\"description\" name=\"description\" rows=\"2\" placeholder=\"What is this service account used for?\"></textarea></div><div class=\"mb-3\"><label for=\"expiration\" class=\"form-label\">Expiration (optional)</label> <input type=\"datetime-local\" class=\"form-control\" id=\"expiration\" name=\"expiration\"> <small class=\"form-text text-muted\">Leave empty for no expiration</small></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"handleCreateServiceAccount()\">Create</button></div></div></div></div><!-- Service Account Details Modal --><div class=\"modal fade\" id=\"saDetailsModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog modal-lg\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-robot me-2\"></i>Service Account Details</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\" id=\"saDetailsContent\"><!-- Content will be loaded dynamically --></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Close</button></div></div></div></div><!-- Credentials Display Modal --><div class=\"modal fade\" id=\"credentialsModal\" tabindex=\"-1\" role=\"dialog\" data-bs-backdrop=\"static\" data-bs-keyboard=\"false\"><div class=\"modal-dialog modal-lg\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header bg-success text-white\"><h5 class=\"modal-title\"><i class=\"fas fa-check-circle me-2\"></i>Service Account Created Successfully</h5></div><div class=\"modal-body\"><div class=\"alert alert-warning\"><i class=\"fas fa-exclamation-triangle me-2\"></i> <strong>Important:</strong> This is the only time you will see the secret access key. Please save it securely.</div><div class=\"mb-4\"><h6 class=\"text-muted mb-3\">AWS CLI Configuration</h6><p class=\"text-muted small\">Use these credentials to configure AWS CLI or SDKs:</p><div class=\"mb-3\"><label class=\"form-label fw-bold\">AWS_ACCESS_KEY_ID</label><div class=\"input-group\"><input type=\"text\" class=\"form-control font-monospace\" id=\"displayAccessKey\" readonly> <button class=\"btn btn-outline-secondary\" type=\"button\" onclick=\"copyCredentialToClipboard(this, 'displayAccessKey')\"><i class=\"fas fa-copy\"></i> Copy</button></div></div><div class=\"mb-3\"><label class=\"form-label fw-bold\">AWS_SECRET_ACCESS_KEY</label><div class=\"input-group\"><input type=\"text\" class=\"form-control font-monospace\" id=\"displaySecretKey\" readonly> <button class=\"btn btn-outline-secondary\" type=\"button\" onclick=\"copyCredentialToClipboard(this, 'displaySecretKey')\"><i class=\"fas fa-copy\"></i> Copy</button></div></div></div><div class=\"bg-light p-3 rounded\"><h6 class=\"text-muted mb-2\">Example AWS CLI Usage:</h6><div class=\"font-monospace small\"><div>export AWS_ACCESS_KEY_ID=<span id=\"exampleAccessKey\"></span></div><div>export AWS_SECRET_ACCESS_KEY=<span id=\"exampleSecretKey\"></span></div><div>export AWS_ENDPOINT_URL=http://localhost:8333</div><div class=\"mt-2\"># List buckets</div><div>aws s3 ls</div><div class=\"mt-2\"># Upload a file</div><div>aws s3 cp myfile.txt s3://mybucket/</div></div></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-primary\" onclick=\"closeCredentialsModal()\"><i class=\"fas fa-check me-1\"></i>I have saved the credentials</button></div></div></div></div><!-- JavaScript for service account management --><script>\n document.addEventListener('DOMContentLoaded', function() {\n document.addEventListener('click', function(e) {\n const button = e.target.closest('[data-action]');\n if (!button) return;\n \n const action = button.getAttribute('data-action');\n const saId = button.getAttribute('data-sa-id');\n \n switch (action) {\n case 'show-sa-details':\n showSADetails(saId);\n break;\n case 'toggle-sa-status':\n toggleSAStatus(saId, button.getAttribute('data-current-status'));\n break;\n case 'delete-sa':\n deleteSA(saId);\n break;\n }\n });\n });\n\n async function showSADetails(id) {\n try {\n const encodedId = encodeURIComponent(id);\n Line truncated
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</select> <small class=\"form-text text-muted\">The service account will inherit permissions from this user</small></div><div class=\"mb-3\"><label for=\"description\" class=\"form-label\">Description</label> <textarea class=\"form-control\" id=\"description\" name=\"description\" rows=\"2\" placeholder=\"What is this service account used for?\"></textarea></div><div class=\"mb-3\"><label for=\"expiration\" class=\"form-label\">Expiration (optional)</label> <input type=\"datetime-local\" class=\"form-control\" id=\"expiration\" name=\"expiration\"> <small class=\"form-text text-muted\">Leave empty for no expiration</small></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"handleCreateServiceAccount()\">Create</button></div></div></div></div><!-- Service Account Details Modal --><div class=\"modal fade\" id=\"saDetailsModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog modal-lg\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-robot me-2\"></i>Service Account Details</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\" id=\"saDetailsContent\"><!-- Content will be loaded dynamically --></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Close</button></div></div></div></div><!-- Credentials Display Modal --><div class=\"modal fade\" id=\"credentialsModal\" tabindex=\"-1\" role=\"dialog\" data-bs-backdrop=\"static\" data-bs-keyboard=\"false\"><div class=\"modal-dialog modal-lg\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header bg-success text-white\"><h5 class=\"modal-title\"><i class=\"fas fa-check-circle me-2\"></i>Service Account Created Successfully</h5></div><div class=\"modal-body\"><div class=\"alert alert-warning\"><i class=\"fas fa-exclamation-triangle me-2\"></i> <strong>Important:</strong> This is the only time you will see the secret access key. Please save it securely.</div><div class=\"mb-4\"><h6 class=\"text-muted mb-3\">AWS CLI Configuration</h6><p class=\"text-muted small\">Use these credentials to configure AWS CLI or SDKs:</p><div class=\"mb-3\"><label class=\"form-label fw-bold\">AWS_ACCESS_KEY_ID</label><div class=\"input-group\"><input type=\"text\" class=\"form-control font-monospace\" id=\"displayAccessKey\" readonly> <button class=\"btn btn-outline-secondary\" type=\"button\" onclick=\"copyCredentialToClipboard(this, 'displayAccessKey')\"><i class=\"fas fa-copy\"></i> Copy</button></div></div><div class=\"mb-3\"><label class=\"form-label fw-bold\">AWS_SECRET_ACCESS_KEY</label><div class=\"input-group\"><input type=\"text\" class=\"form-control font-monospace\" id=\"displaySecretKey\" readonly> <button class=\"btn btn-outline-secondary\" type=\"button\" onclick=\"copyCredentialToClipboard(this, 'displaySecretKey')\"><i class=\"fas fa-copy\"></i> Copy</button></div></div></div><div class=\"bg-light p-3 rounded\"><h6 class=\"text-muted mb-2\">Example AWS CLI Usage:</h6><div class=\"font-monospace small\"><div>export AWS_ACCESS_KEY_ID=<span id=\"exampleAccessKey\"></span></div><div>export AWS_SECRET_ACCESS_KEY=<span id=\"exampleSecretKey\"></span></div><div>export AWS_ENDPOINT_URL=http://localhost:8333</div><div class=\"mt-2\"># List buckets</div><div>aws s3 ls</div><div class=\"mt-2\"># Upload a file</div><div>aws s3 cp myfile.txt s3://mybucket/</div></div></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-primary\" onclick=\"closeCredentialsModal()\"><i class=\"fas fa-check me-1\"></i>I have saved the credentials</button></div></div></div></div><!-- JavaScript for service account management --><script>\n document.addEventListener('DOMContentLoaded', function() {\n document.addEventListener('click', function(e) {\n const button = e.target.closest('[data-action]');\n if (!button) return;\n \n const action = button.getAttribute('data-action');\n const saId = button.getAttribute('data-sa-id');\n \n switch (action) {\n case 'show-sa-details':\n showSADetails(saId);\n break;\n case 'toggle-sa-status':\n toggleSAStatus(saId, button.getAttribute('data-current-status'));\n break;\n case 'delete-sa':\n deleteSA(saId);\n break;\n }\n });\n });\n\n async function showSADetails(id) {\n try {\n const encodedId = encodeURIComponent(id);\n Line truncated
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
+2 -2
View File
@@ -273,7 +273,7 @@ templ Topics(data dash.TopicsData) {
};
// Create the topic
fetch('/api/mq/topics/create', {
fetch(basePath('/api/mq/topics/create'), {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@@ -354,7 +354,7 @@ templ Topics(data dash.TopicsData) {
var detailsRow = document.getElementById('details-' + topicName.replace(/\./g, '_'));
var contentDiv = detailsRow.querySelector('.topic-details-content');
fetch('/admin/topics/' + encodeURIComponent(topicName) + '/details')
fetch(basePath('/admin/topics/' + encodeURIComponent(topicName) + '/details'))
.then(response => response.json())
.then(data => {
var html = '<div class="row">';
+11 -11
View File
@@ -40,7 +40,7 @@ func Topics(data dash.TopicsData) templ.Component {
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("2006-01-02 15:04:05"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/topics.templ`, Line: 13, Col: 107}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/topics.templ`, Line: 13, Col: 107}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
@@ -53,7 +53,7 @@ func Topics(data dash.TopicsData) templ.Component {
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalTopics))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/topics.templ`, Line: 22, Col: 93}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/topics.templ`, Line: 22, Col: 93}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
@@ -66,7 +66,7 @@ func Topics(data dash.TopicsData) templ.Component {
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", len(data.Topics)))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/topics.templ`, Line: 30, Col: 90}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/topics.templ`, Line: 30, Col: 90}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
@@ -94,7 +94,7 @@ func Topics(data dash.TopicsData) templ.Component {
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(topic.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/topics.templ`, Line: 70, Col: 93}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/topics.templ`, Line: 70, Col: 93}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
@@ -113,7 +113,7 @@ func Topics(data dash.TopicsData) templ.Component {
return topic.Name[:idx]
}())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/topics.templ`, Line: 78, Col: 55}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/topics.templ`, Line: 78, Col: 55}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
@@ -132,7 +132,7 @@ func Topics(data dash.TopicsData) templ.Component {
return topic.Name[idx+1:]
}())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/topics.templ`, Line: 87, Col: 55}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/topics.templ`, Line: 87, Col: 55}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
@@ -145,7 +145,7 @@ func Topics(data dash.TopicsData) templ.Component {
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", topic.Partitions))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/topics.templ`, Line: 90, Col: 116}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/topics.templ`, Line: 90, Col: 116}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
@@ -163,7 +163,7 @@ func Topics(data dash.TopicsData) templ.Component {
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d %s", topic.Retention.DisplayValue, topic.Retention.DisplayUnit))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/topics.templ`, Line: 96, Col: 140}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/topics.templ`, Line: 96, Col: 140}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
@@ -186,7 +186,7 @@ func Topics(data dash.TopicsData) templ.Component {
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(topic.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/topics.templ`, Line: 105, Col: 160}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/topics.templ`, Line: 105, Col: 160}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
@@ -199,7 +199,7 @@ func Topics(data dash.TopicsData) templ.Component {
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("details-%s", strings.ReplaceAll(topic.Name, ".", "_")))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `weed/admin/view/app/topics.templ`, Line: 110, Col: 146}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/topics.templ`, Line: 110, Col: 146}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
@@ -215,7 +215,7 @@ func Topics(data dash.TopicsData) templ.Component {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</div></div></div></div></div><!-- Create Topic Modal --><div class=\"modal fade\" id=\"createTopicModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog modal-lg\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-plus me-2\"></i>Create New Topic</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\"><form id=\"createTopicForm\"><div class=\"row\"><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"topicNamespace\" class=\"form-label\">Namespace *</label> <input type=\"text\" class=\"form-control\" id=\"topicNamespace\" name=\"namespace\" required placeholder=\"e.g., default\"></div></div><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"topicName\" class=\"form-label\">Topic Name *</label> <input type=\"text\" class=\"form-control\" id=\"topicName\" name=\"name\" required placeholder=\"e.g., user-events\"></div></div></div><div class=\"row\"><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"partitionCount\" class=\"form-label\">Partition Count *</label> <input type=\"number\" class=\"form-control\" id=\"partitionCount\" name=\"partitionCount\" required min=\"1\" max=\"100\" value=\"6\"></div></div></div><!-- Retention Configuration --><div class=\"card mt-3\"><div class=\"card-header\"><h6 class=\"mb-0\"><i class=\"fas fa-clock me-2\"></i>Retention Policy</h6></div><div class=\"card-body\"><div class=\"form-check mb-3\"><input class=\"form-check-input\" type=\"checkbox\" id=\"enableRetention\" name=\"enableRetention\" onchange=\"toggleRetentionFields()\"> <label class=\"form-check-label\" for=\"enableRetention\">Enable data retention</label></div><div id=\"retentionFields\" style=\"display: none;\"><div class=\"row\"><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"retentionValue\" class=\"form-label\">Retention Duration</label> <input type=\"number\" class=\"form-control\" id=\"retentionValue\" name=\"retentionValue\" min=\"1\" value=\"7\"></div></div><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"retentionUnit\" class=\"form-label\">Unit</label> <select class=\"form-control\" id=\"retentionUnit\" name=\"retentionUnit\"><option value=\"hours\">Hours</option> <option value=\"days\" selected>Days</option></select></div></div></div><div class=\"alert alert-info\"><i class=\"fas fa-info-circle me-2\"></i> Data older than this duration will be automatically purged to save storage space.</div></div></div></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"createTopic()\"><i class=\"fas fa-plus me-1\"></i>Create Topic</button></div></div></div></div><script type=\"text/javascript\">\n // Topic management functions\n function showCreateTopicModal() {\n var modal = new bootstrap.Modal(document.getElementById('createTopicModal'));\n modal.show();\n }\n\n function toggleRetentionFields() {\n var enableRetention = document.getElementById('enableRetention').checked;\n var retentionFields = document.getElementById('retentionFields');\n \n if (enableRetention) {\n retentionFields.style.display = 'block';\n } else {\n retentionFields.style.display = 'none';\n }\n }\n\n function createTopic() {\n var form = document.getElementById('createTopicForm');\n var formData = new FormData(form);\n \n if (!form.checkValidity()) {\n form.classList.add('was-validated');\n return;\n }\n \n var namespace = formData.get('namespace');\n var name = formData.get('name');\n var partitionCount = formData.get('partitionCount');\n var enableRetention = formData.get('enableRetention');\n var retentionValue = enableRetention === 'on' ? parseInt(formData.get('retentionValue')) : 0;\n var retentionUnit = enableRetention === 'on' ? formData.get('retentionUnit') : 'hours';\n \n // Convert retention to seconds\n var retentionSeconds = 0;\n if (enableRetention === 'on' && retentionValue > 0) {\n if (retentionUnit === 'hours') {\n retentionSeconds = retentionValue * 3600;\n } else if (retentionUnit === 'days') {\n retentionSeconds = retentionValue * 86400;\n }\n }\n \n var topicData = {\n namespace: namespace,\n name: name,\n partition_count: parseInt(partitionCount),\n retention: {\n enabled: enableRetentLine truncated
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</div></div></div></div></div><!-- Create Topic Modal --><div class=\"modal fade\" id=\"createTopicModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog modal-lg\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-plus me-2\"></i>Create New Topic</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\"><form id=\"createTopicForm\"><div class=\"row\"><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"topicNamespace\" class=\"form-label\">Namespace *</label> <input type=\"text\" class=\"form-control\" id=\"topicNamespace\" name=\"namespace\" required placeholder=\"e.g., default\"></div></div><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"topicName\" class=\"form-label\">Topic Name *</label> <input type=\"text\" class=\"form-control\" id=\"topicName\" name=\"name\" required placeholder=\"e.g., user-events\"></div></div></div><div class=\"row\"><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"partitionCount\" class=\"form-label\">Partition Count *</label> <input type=\"number\" class=\"form-control\" id=\"partitionCount\" name=\"partitionCount\" required min=\"1\" max=\"100\" value=\"6\"></div></div></div><!-- Retention Configuration --><div class=\"card mt-3\"><div class=\"card-header\"><h6 class=\"mb-0\"><i class=\"fas fa-clock me-2\"></i>Retention Policy</h6></div><div class=\"card-body\"><div class=\"form-check mb-3\"><input class=\"form-check-input\" type=\"checkbox\" id=\"enableRetention\" name=\"enableRetention\" onchange=\"toggleRetentionFields()\"> <label class=\"form-check-label\" for=\"enableRetention\">Enable data retention</label></div><div id=\"retentionFields\" style=\"display: none;\"><div class=\"row\"><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"retentionValue\" class=\"form-label\">Retention Duration</label> <input type=\"number\" class=\"form-control\" id=\"retentionValue\" name=\"retentionValue\" min=\"1\" value=\"7\"></div></div><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"retentionUnit\" class=\"form-label\">Unit</label> <select class=\"form-control\" id=\"retentionUnit\" name=\"retentionUnit\"><option value=\"hours\">Hours</option> <option value=\"days\" selected>Days</option></select></div></div></div><div class=\"alert alert-info\"><i class=\"fas fa-info-circle me-2\"></i> Data older than this duration will be automatically purged to save storage space.</div></div></div></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"createTopic()\"><i class=\"fas fa-plus me-1\"></i>Create Topic</button></div></div></div></div><script type=\"text/javascript\">\n // Topic management functions\n function showCreateTopicModal() {\n var modal = new bootstrap.Modal(document.getElementById('createTopicModal'));\n modal.show();\n }\n\n function toggleRetentionFields() {\n var enableRetention = document.getElementById('enableRetention').checked;\n var retentionFields = document.getElementById('retentionFields');\n \n if (enableRetention) {\n retentionFields.style.display = 'block';\n } else {\n retentionFields.style.display = 'none';\n }\n }\n\n function createTopic() {\n var form = document.getElementById('createTopicForm');\n var formData = new FormData(form);\n \n if (!form.checkValidity()) {\n form.classList.add('was-validated');\n return;\n }\n \n var namespace = formData.get('namespace');\n var name = formData.get('name');\n var partitionCount = formData.get('partitionCount');\n var enableRetention = formData.get('enableRetention');\n var retentionValue = enableRetention === 'on' ? parseInt(formData.get('retentionValue')) : 0;\n var retentionUnit = enableRetention === 'on' ? formData.get('retentionUnit') : 'hours';\n \n // Convert retention to seconds\n var retentionSeconds = 0;\n if (enableRetention === 'on' && retentionValue > 0) {\n if (retentionUnit === 'hours') {\n retentionSeconds = retentionValue * 3600;\n } else if (retentionUnit === 'days') {\n retentionSeconds = retentionValue * 86400;\n }\n }\n \n var topicData = {\n namespace: namespace,\n name: name,\n partition_count: parseInt(partitionCount),\n retention: {\n enabled: enableRetentLine truncated
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}