Innerbloom
@Innerbloom

Как копировать данные до обновления объекта в project-config.json?

У меня есть получение конфигов с других серверов в DataService
public getAllConfigs(): Observable<any> {
    return this.http.get(environment.apiHost + '/get-config');
  }
  public getConfigById(id: number): Observable<any> {
    return this.http.get(environment.apiHost + `/get-config/${id}`);
  }
  public updateConfigById(id: number, config: any): Observable<any> {
    return this.http.put(environment.apiHost + `/update-config/${id}`, config);
  }
  public updateConfigs(configUpdates: { id: number, config: any }[]): Observable<any> {
    return this.http.put(environment.apiHost + `/update-configs`, configUpdates);
  }


После этого я получаю эти данные и вывожу в таблицу Aggrid, выделении чекбоксами нескольких строк (конфигов), выполняею сравнение конфигураций и, если встречаются ключи с разными значениями, устанавливаею значение "mixed" - оно должно быть только визуально что б понимать что значения ключей разные. Это делается с использованием рекурсивных функций compareConfigs и compareObjects, которые обходят структуры объектов и сравнивают значения ключей.
@Injectable()
export class ConfigService {
    compareConfigs(configs: any[]): any {
        const commonKeys = new Set<string>();
        const resultConfig = {};

        configs.forEach(config => {
            const configData = config.config;
            if (configData) {
                for (const key of Object.keys(configData)) {
                    if (commonKeys.has(key)) {
                        const value = configData[key];
                        const existingValue = resultConfig[key];
                        if (typeof value === 'object' && !Array.isArray(value) &&
                            typeof existingValue === 'object' && !Array.isArray(existingValue)) {
                            resultConfig[key] = this.compareObjects([existingValue, value]);
                        } else if (existingValue !== value) {
                            resultConfig[key] = 'mixed';
                        }
                    } else {
                        commonKeys.add(key);
                        if (typeof configData[key] === 'object' && !Array.isArray(configData[key])) {
                            resultConfig[key] = this.compareObjects(configs.map(c => c.config[key]));
                        } else {
                            resultConfig[key] = configData[key];
                        }
                    }
                }
            }
        });
        return resultConfig;
    }

    compareObjects(objects: any[]): any {
        const commonKeys = new Set<string>();
        const resultObject = {};

        const valuesAreEqual = (value1: any, value2: any): boolean => {
            if (Array.isArray(value1) && Array.isArray(value2)) {
                return JSON.stringify(value1) === JSON.stringify(value2);
            } else if (typeof value1 === 'object' && typeof value2 === 'object') {
                return JSON.stringify(value1) === JSON.stringify(value2);
            }
            return value1 === value2;
        };

        objects.forEach(obj => {
            for (const key of Object.keys(obj || {})) {
                if (commonKeys.has(key)) {
                    const value = obj[key];
                    const existingValue = resultObject[key];
                    if (typeof value === 'object' && !Array.isArray(value) &&
                        typeof existingValue === 'object' && !Array.isArray(existingValue)) {
                        resultObject[key] = this.compareObjects([existingValue, value]);
                    } else if (existingValue !== 'mixed' && !valuesAreEqual(existingValue, value)) {
                        resultObject[key] = 'mixed';
                    }
                } else {
                    commonKeys.add(key);
                    if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
                        resultObject[key] = this.compareObjects(objects.map(o => o[key]));
                    } else {
                        resultObject[key] = obj[key];
                    }
                }
            }
        });
        return resultObject;
    }
}


вот компонент который открывает модальное окно
compareModalConfigs(selectedIds: number[]): void {
    if (selectedIds.length < 2) {
      return;
    }
    const selectedConfigs = selectedIds.map(id => this.rowData.find(item => item.id === id));
    const ids = selectedIds;
    const resultConfig = this.configService.compareConfigs(selectedConfigs);
    const dialogRef = this.dialog.open(ConfigModalComponent, {
      minWidth: '80vw',
      maxHeight: '70%',
      data: { config: { config: resultConfig, id: ids } },
    });

    dialogRef.afterClosed().subscribe(result => {
      console.log('CLOSE');
    });
  }


Ну и собственно сам компонент в котором происходит сохранение удаление изменение значений через json-editor

export class ConfigModalComponent implements OnInit {

   public configData: any;
   public editedConfig: any;
   public configId: number;
   public size = false;
   public deletedKeys: any;
   public dialogRef: MatDialogRef<ConfigModalComponent>;


    constructor(@Inject(MAT_DIALOG_DATA) public data: any,
              public modalComponent: MatDialogRef<ConfigModalComponent>,
              private dataService: DataService,
  ) {
      this.configData = data.config.config;
      this.configId = data.config.id;
      this.editedConfig = { ...this.configData };
  }

    ngOnInit(): void {
        if (this.configData) {
            this.editedConfig = { ...this.configData.config };
        } else {
            console.error('Received invalid data:', this.configData);
        }
    }

    onJsonEditorChange(updatedData: any) {
        this.editedConfig = updatedData;
        this.deletedKeys = {};

        for (const key of Object.keys(this.configData)) {
            if (!(key in this.editedConfig)) {
                this.deletedKeys[key] = this.configData[key];
                delete this.configData[key];
                delete this.editedConfig[key];
            }
        }

        for (const key of Object.keys(this.deletedKeys)) {
            if (typeof this.deletedKeys[key] === 'object') {
                delete this.configData[key];
                delete this.editedConfig[key];
            }
        }
    }

    saveConfig() {
        const configUpdates = [];
        const addedKeys = new Set<string>();

        const ids = Array.isArray(this.configId) ? this.configId : [this.configId];

        for (const id of ids) {
            const configUpdate = { id, config: {} };

            for (const key of Object.keys(this.editedConfig)) {
                if (this.editedConfig[key] !== 'mixed') {
                    if (typeof this.editedConfig[key] === 'object') {
                        const mixed = Object.values(this.editedConfig[key]).includes('mixed');
                        if (!mixed) {
                            configUpdate.config[key] = this.editedConfig[key];
                        }
                    } else {
                        configUpdate.config[key] = this.editedConfig[key];
                    }
                    addedKeys.add(key);
                }
            }

            for (const key of Object.keys(this.configData)) {
                if (!addedKeys.has(key) && this.configData[key] !== 'mixed') {
                    configUpdate.config[key] = this.configData[key];
                }
                addedKeys.add(key);
            }

            if (Object.keys(configUpdate.config).length > 0) {
                configUpdates.push(configUpdate);
            }
        }

        for (const key of Object.keys(this.deletedKeys)) {
            if (this.deletedKeys[key] && typeof this.deletedKeys[key] === 'object') {
                delete this.configData[key];
            } else {
                delete this.configData[key];
            }
        }


        if (configUpdates.length > 0) {
            this.dataService.updateConfigs(configUpdates).subscribe(
                (response) => {
                    console.log('Config updated:', response);
                    this.modalComponent.close({ saved: true });
                },
                (error) => {
                    console.error('Error updating config:', error);
                }
            );
        } else {
            this.modalComponent.close();
        }
    }
}


<div>
    <div fxLayoutAlign="space-between" fxLayout="row" fxLayoutGap="20px">
        <app-buttons-macos [component]="this"></app-buttons-macos>
    </div>
    <h3 style="text-align: center">{{ data.config.projectName }}</h3>
    <form>
        <json-editor [data]="configData" (change)="onJsonEditorChange($event)"></json-editor>
        <div style="margin-top: 15px" fxLayoutAlign="end end">
            <button mat-button (click)="saveConfig()">Save</button>
            <button mat-button type="button" (click)="modalComponent.close()">Cancel</button>
        </div>
    </form>
</div>


Тогда я меняю ключь в котором значение "mixed" на какое либо другое то оно сохраняется, но когда я меняю другой ключь со значением, а ключь со значением "mixed" не трогаю то он удаляется (то есть он не сохраняется у меня если его значение "mixed") подскажите как мне можно сделать так что б если я не трогаю mixed то сохранялись предыдущие значения ключа до формирования данных в сервисе ?
  • Вопрос задан
  • 53 просмотра
Пригласить эксперта
Ответы на вопрос 1
Innerbloom
@Innerbloom Автор вопроса
В общем решил вопрос, передал с родительского компонента оригинальные данные и теперь в место "mixed" подсталяют их
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы