CloudFlare DNS: inline edit (no modify button), Type dropdown fix, deploy

This commit is contained in:
master3395
2026-02-16 14:53:30 +01:00
parent dbc05728a7
commit c2f3f2b361
3 changed files with 156 additions and 12 deletions

View File

@@ -548,6 +548,23 @@
outline: 2px solid rgba(91, 95, 207, 0.3) !important;
outline-offset: 2px !important;
}
.editable-cell { vertical-align: middle; }
.cell-click { cursor: pointer; display: block; min-height: 1.5em; }
.cell-click:hover { background: var(--bg-hover, #f0f1ff); border-radius: 4px; }
.cell-value { max-width: 280px; display: inline-block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.value-cell { max-width: 300px; }
.inline-input, .inline-select, .inline-number {
width: 100%;
max-width: 100%;
padding: 0.25rem 0.5rem;
border: 1px solid var(--border-primary, #e2e8f0);
border-radius: 6px;
font-size: 0.875rem;
background: var(--bg-primary, #fff);
}
.inline-select { min-width: 90px; cursor: pointer; }
.inline-number { width: 70px; max-width: 80px; }
</style>
<div class="modern-container" ng-controller="addModifyDNSRecordsCloudFlare">
@@ -903,15 +920,32 @@
</thead>
<tbody>
<tr ng-repeat="record in records track by $index">
<td><strong ng-bind="record.name"></strong></td>
<td>
<span style="padding: 0.25rem 0.75rem; background: var(--bg-hover, #f0f1ff); color: #5b5fcf; border-radius: 4px; font-weight: 500; font-size: 0.75rem;">
{{ record.type }}
</span>
<td class="editable-cell">
<span ng-hide="isEditing(record, 'name')" ng-click="startEdit(record, 'name')" class="cell-click" title="{% trans 'Click to edit' %}"><strong ng-bind="record.name"></strong></span>
<input ng-show="isEditing(record, 'name')" type="text" class="inline-input" ng-model="record.name" ng-blur="saveInlineField(record, 'name')" ng-keypress="$event.keyCode === 13 && saveInlineField(record, 'name')">
</td>
<td class="editable-cell">
<select class="inline-select" ng-model="record.type" ng-options="t as t for t in getTypeOptions(record)" ng-change="saveInlineField(record, 'type')" title="{% trans 'Type' %}">
</select>
</td>
<td class="editable-cell">
<select class="inline-select" ng-model="record.ttlNum" ng-change="saveInlineField(record, 'ttl')" title="{% trans 'TTL' %}">
<option value="1">AUTO</option>
<option value="300">300</option>
<option value="600">600</option>
<option value="3600">3600</option>
<option value="7200">7200</option>
<option value="14400">14400</option>
<option value="86400">86400</option>
</select>
</td>
<td class="editable-cell value-cell">
<span ng-hide="isEditing(record, 'content')" ng-click="startEdit(record, 'content')" class="cell-click" title="{% trans 'Click to edit' %}"><span class="cell-value" ng-bind="record.content" title="{{ record.content }}"></span></span>
<input ng-show="isEditing(record, 'content')" type="text" class="inline-input" ng-model="record.content" ng-blur="saveInlineField(record, 'content')" ng-keypress="$event.keyCode === 13 && saveInlineField(record, 'content')">
</td>
<td class="editable-cell">
<input type="number" class="inline-number" ng-model="record.priority" ng-blur="saveInlineField(record, 'priority')" ng-keypress="$event.keyCode === 13 && saveInlineField(record, 'priority')" min="0" step="1" title="{% trans 'Priority' %}">
</td>
<td ng-bind="record.ttl"></td>
<td style="max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" ng-bind="record.content" title="{{ record.content }}"></td>
<td ng-bind="record.priority || '-'"></td>
<td>
<input class="proxy-toggle"
ng-click="enableProxy(record.name, record.proxy)"
@@ -920,10 +954,6 @@
type="checkbox">
</td>
<td style="text-align: center;">
<i class="fas fa-edit edit-icon"
style="color: #5b5fcf; cursor: pointer; margin-right: 10px;"
ng-click="openEditModal(record)"
title="{% trans 'Edit Record' %}"></i>
<i class="fas fa-trash delete-icon"
style="color: #ef4444; cursor: pointer;"
ng-click="deleteRecord(record.id)"

View File

@@ -1004,10 +1004,21 @@ app.controller('addModifyDNSRecordsCloudFlare', function ($scope, $http, $window
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function normalizeRecordForInline(record) {
record.ttlNum = record.ttl === 'AUTO' || record.ttl === 1 ? 1 : (parseInt(record.ttl, 10) || 3600);
record.priority = parseInt(record.priority, 10) || 0;
if (record.type != null && typeof record.type === 'string') {
record.type = record.type.toUpperCase().trim();
} else if (record.type == null || record.type === '') {
record.type = 'A';
}
}
function ListInitialDatas(response) {
if (response.data.fetchStatus === 1) {
$scope.records = JSON.parse(response.data.data);
$scope.records.forEach(normalizeRecordForInline);
$scope.currentRecords = false;
$scope.canNotFetchRecords = true;
@@ -1138,6 +1149,52 @@ app.controller('addModifyDNSRecordsCloudFlare', function ($scope, $http, $window
};
$scope.dnsTypeList = ['A', 'AAAA', 'CNAME', 'MX', 'TXT', 'NS', 'SOA', 'SRV', 'CAA', 'SPF', 'DNSKEY', 'CDNSKEY', 'HTTPS', 'SVCB', 'URI', 'LOC', 'NAPTR', 'SMIMEA', 'SSHFP', 'TLSA', 'PTR'];
$scope.getTypeOptions = function (record) {
var list = angular.copy($scope.dnsTypeList);
var t = record && record.type ? String(record.type).toUpperCase().trim() : '';
if (t && list.indexOf(t) === -1) {
list.unshift(t);
}
return list;
};
$scope.editingRecordId = null;
$scope.editingField = null;
$scope.isEditing = function (record, field) {
return $scope.editingRecordId === record.id && $scope.editingField === field;
};
$scope.startEdit = function (record, field) {
$scope.editingRecordId = record.id;
$scope.editingField = field;
};
$scope.saveInlineField = function (record, field) {
$scope.editingRecordId = null;
$scope.editingField = null;
var ttl = record.ttlNum !== undefined ? record.ttlNum : (record.ttl === 'AUTO' || record.ttl === 1 ? 1 : parseInt(record.ttl, 10) || 3600);
var url = "/dns/updateDNSRecordCloudFlare";
var data = {
selectedZone: $scope.selectedZone,
id: record.id,
name: record.name,
recordType: record.type,
content: record.content,
ttl: ttl,
priority: parseInt(record.priority, 10) || 0,
proxied: record.proxy
};
var config = { headers: { 'X-CSRFToken': getCookie('csrftoken') } };
$http.post(url, data, config).then(function (response) {
if (response.data.update_status === 1) {
new PNotify({ title: 'Success', text: 'Record updated.', type: 'success' });
populateCurrentRecords();
} else {
new PNotify({ title: 'Error', text: response.data.error_message || 'Update failed', type: 'error' });
}
}, function () {
new PNotify({ title: 'Error', text: 'Could not connect to server.', type: 'error' });
});
};
$scope.openEditModal = function (record) {
$scope.editRecord = {
id: record.id,

View File

@@ -1005,11 +1005,22 @@ app.controller('addModifyDNSRecordsCloudFlare', function ($scope, $http, $window
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function normalizeRecordForInline(record) {
record.ttlNum = record.ttl === 'AUTO' || record.ttl === 1 ? 1 : (parseInt(record.ttl, 10) || 3600);
record.priority = parseInt(record.priority, 10) || 0;
if (record.type != null && typeof record.type === 'string') {
record.type = record.type.toUpperCase().trim();
} else if (record.type == null || record.type === '') {
record.type = 'A';
}
}
function ListInitialDatas(response) {
$scope.loadingRecords = false;
if (response.data.fetchStatus === 1) {
$scope.records = JSON.parse(response.data.data);
$scope.records.forEach(normalizeRecordForInline);
$scope.currentRecords = false;
$scope.canNotFetchRecords = true;
@@ -1142,6 +1153,52 @@ app.controller('addModifyDNSRecordsCloudFlare', function ($scope, $http, $window
};
$scope.dnsTypeList = ['A', 'AAAA', 'CNAME', 'MX', 'TXT', 'NS', 'SOA', 'SRV', 'CAA', 'SPF', 'DNSKEY', 'CDNSKEY', 'HTTPS', 'SVCB', 'URI', 'LOC', 'NAPTR', 'SMIMEA', 'SSHFP', 'TLSA', 'PTR'];
$scope.getTypeOptions = function (record) {
var list = angular.copy($scope.dnsTypeList);
var t = record && record.type ? String(record.type).toUpperCase().trim() : '';
if (t && list.indexOf(t) === -1) {
list.unshift(t);
}
return list;
};
$scope.editingRecordId = null;
$scope.editingField = null;
$scope.isEditing = function (record, field) {
return $scope.editingRecordId === record.id && $scope.editingField === field;
};
$scope.startEdit = function (record, field) {
$scope.editingRecordId = record.id;
$scope.editingField = field;
};
$scope.saveInlineField = function (record, field) {
$scope.editingRecordId = null;
$scope.editingField = null;
var ttl = record.ttlNum !== undefined ? record.ttlNum : (record.ttl === 'AUTO' || record.ttl === 1 ? 1 : parseInt(record.ttl, 10) || 3600);
var url = "/dns/updateDNSRecordCloudFlare";
var data = {
selectedZone: $scope.selectedZone,
id: record.id,
name: record.name,
recordType: record.type,
content: record.content,
ttl: ttl,
priority: parseInt(record.priority, 10) || 0,
proxied: record.proxy
};
var config = { headers: { 'X-CSRFToken': getCookie('csrftoken') } };
$http.post(url, data, config).then(function (response) {
if (response.data.update_status === 1) {
new PNotify({ title: 'Success', text: 'Record updated.', type: 'success' });
populateCurrentRecords();
} else {
new PNotify({ title: 'Error', text: response.data.error_message || 'Update failed', type: 'error' });
}
}, function () {
new PNotify({ title: 'Error', text: 'Could not connect to server.', type: 'error' });
});
};
$scope.openEditModal = function (record) {
$scope.editRecord = {
id: record.id,