Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-unused-imports": "^4.1.3",
"fake-indexeddb": "^6.0.0",
"fast-json-patch": "^3.1.1",
"fuse.js": "^7.0.0",
"humanize-duration": "^3.27.2",
"i18next": "^23.15.1",
Expand Down
48 changes: 46 additions & 2 deletions frontend/src/components/common/Resource/EditButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@
*/

import { Icon } from '@iconify/react';
import { compare } from 'fast-json-patch';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';
import { useLocation } from 'react-router-dom';
import { patch } from '../../../lib/k8s/api/v1/clusterRequests';
import { KubeObjectEndpoint } from '../../../lib/k8s/api/v2/KubeObjectEndpoint';
import { KubeObject } from '../../../lib/k8s/KubeObject';
import { KubeObjectInterface } from '../../../lib/k8s/KubeObject';
import { CallbackActionOptions, clusterAction } from '../../../redux/clusterActionSlice';
Expand Down Expand Up @@ -51,6 +54,10 @@ export default function EditButton(props: EditButtonProps) {
const dispatchHeadlampEditEvent = useEventCallback(HeadlampEventType.EDIT_RESOURCE);
const activityId = 'edit-' + item.metadata.uid;

// Store the original resource snapshot (firstDraft) for JSON Patch comparison
// This is set when the editor is opened
const originalResourceRef = React.useRef<any>(null);

function makeErrorMessage(err: any) {
const status: number = err.status;
switch (status) {
Expand All @@ -63,7 +70,41 @@ export default function EditButton(props: EditButtonProps) {

async function updateFunc(newItem: KubeObjectInterface) {
try {
await item.update(newItem);
if (!originalResourceRef.current) {
throw new Error('Original resource snapshot not found');
}

// Calculate JSON Patch: diff between original (when editor opened) and new (user edited)
const patches = compare(originalResourceRef.current, newItem);

if (patches.length === 0) {
// No changes detected
Activity.close(activityId);
return;
}

// Build the API URL
const apiInfo = item._class().apiEndpoint.apiInfo[0];
const endpoint: KubeObjectEndpoint = {
group: apiInfo.group,
version: apiInfo.version,
resource: apiInfo.resource,
};

const namespace = item.getNamespace();
const name = item.getName();
const urlParts = [KubeObjectEndpoint.toUrl(endpoint, namespace), name];
const url = urlParts.filter(Boolean).join('/');

// Use the patch function with JSON Patch content type
// Override the default 'application/merge-patch+json' to 'application/json-patch+json'
await patch(url, patches, true, {
cluster: item._clusterName,
headers: {
'Content-Type': 'application/json-patch+json',
},
});

Activity.close(activityId);
} catch (err) {
Activity.update(activityId, { minimized: false });
Expand Down Expand Up @@ -128,6 +169,9 @@ export default function EditButton(props: EditButtonProps) {
if (afterConfirm) {
afterConfirm();
}
const editableObject = item.getEditableObject();
originalResourceRef.current = editableObject;

Activity.launch({
id: activityId,
title: t('translation|Edit') + ': ' + item.metadata.name,
Expand All @@ -136,7 +180,7 @@ export default function EditButton(props: EditButtonProps) {
content: (
<EditorDialog
noDialog
item={item.getEditableObject()}
item={editableObject}
open
onClose={() => Activity.close(activityId)}
onSave={handleSave}
Expand Down
6 changes: 6 additions & 0 deletions plugins/headlamp-plugin/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions plugins/headlamp-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-unused-imports": "^4.1.3",
"fast-json-patch": "^3.1.1",
"fs-extra": "^11.2.0",
"fuse.js": "^7.0.0",
"humanize-duration": "^3.27.2",
Expand Down
24 changes: 10 additions & 14 deletions plugins/headlamp-plugin/template/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading