mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2026-02-17 20:16:48 +01:00
CloudFlare DNS: inline edit (no modify button), Type dropdown fix, deploy
This commit is contained in:
@@ -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)"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user