Skip to content

WEB-714: Add submit button to user settings#3142

Open
DeathGun44 wants to merge 1 commit intoopenMF:devfrom
DeathGun44:WEB-714/enable-submit-to-user-settings
Open

WEB-714: Add submit button to user settings#3142
DeathGun44 wants to merge 1 commit intoopenMF:devfrom
DeathGun44:WEB-714/enable-submit-to-user-settings

Conversation

@DeathGun44
Copy link
Contributor

@DeathGun44 DeathGun44 commented Feb 13, 2026

Description

Replaced the silent auto-save behavior in User Settings with an explicit Submit button. Previously, the Main Configuration fields (Language, Date Format, Decimals to Display) were auto-saved on every dropdown change via valueChanges subscriptions with no user feedback. This change adds:

  • Submit button with dirty-state tracking — enabled only when the user modifies a field
  • Success feedback via AlertService ("Settings saved successfully.")
  • Proper cleanup via OnDestroy with takeUntil to prevent memory leaks

The submit button covers all previously working fields: Language, Date Format, and Decimals to Display.

Screenshots

image image

Checklist

  • If you have multiple commits please combine them into one commit by squashing them.
  • Read and understood the contribution guidelines at web-app/.github/CONTRIBUTING.md.

Summary by CodeRabbit

  • New Features

    • Added a Submit button in Settings that activates only when changes exist and saves all settings at once.
    • Unified change tracking so the form reliably detects edits and resets after saving.
    • Displays a localized success confirmation after settings are saved (new translation added).
  • Style

    • Submit button aligned to the right with added top spacing for clearer layout.

@coderabbitai
Copy link

coderabbitai bot commented Feb 13, 2026

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key(s) in object: 'pre_merge_checks'
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Walkthrough

Adds a Submit button and styles to the settings UI, consolidates form change-tracking into a merged valueChanges stream that sets hasChanges, adds submit() to persist settings via SettingsService, and shows a localized success alert via TranslateService + AlertService.

Changes

Cohort / File(s) Summary
Templates & styles
src/app/settings/settings.component.html, src/app/settings/settings.component.scss
Adds a .submit-actions container and a Submit button bound to submit(); button enabled only when hasChanges is true; right-aligned styling (display:flex; justify-content:flex-end; margin-top:16px).
Settings component logic
src/app/settings/settings.component.ts
Replaces per-field subscriptions with trackChanges() that merges valueChanges; introduces hasChanges flag and initialValues, hasFormChanged() helper, and submit() to save settings via SettingsService; injects AlertService and TranslateService; keeps destroy$ cleanup and updates lifecycle signature.
Translations
src/assets/translations/en-US.json
Adds translation entry for the settings success message (e.g., text.Settings saved successfullySettings saved successfully.) used by the success alert.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant Comp as SettingsComponent
    participant Service as SettingsService
    participant Trans as TranslateService
    participant Alert as AlertService

    rect rgba(210,230,255,0.5)
    User->>Comp: Click Submit
    end

    rect rgba(200,255,200,0.5)
    Comp->>Service: saveAllSettings(payload)
    Service-->>Comp: success
    end

    rect rgba(255,240,200,0.5)
    Comp->>Trans: translate("text.Settings saved successfully")
    Trans-->>Comp: localizedMessage
    Comp->>Alert: success(localizedMessage)
    Alert-->>Comp: ack
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'WEB-714: Add submit button to user settings' directly and clearly summarizes the main change—adding a submit button to the settings component.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

this.hasChanges = false;
this.alertService.alert({
type: 'Settings Update',
message: 'Settings saved successfully.'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to translate this message?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @IOhacker
I looked into this and found that none of the ~30 alertService.alert() calls across the codebase are currently translated — they're all hardcoded English.

I think a better approach would be a dedicated ticket to standardize alert i18n across the entire codebase. Should I open one? For this PR I can use the translation key with TranslateService.instant() so it's translation-ready, and the actual translated strings can be added when the broader i18n effort lands.

Alternatively, I can add the key to en-US.json now and leave the other 12 language files for the i18n ticket.

@DeathGun44
Copy link
Contributor Author

@IOhacker could you please take a look at my message when you have a moment! If it looks good i will proceed.

@IOhacker
Copy link
Contributor

IOhacker commented Mar 2, 2026

@DeathGun44 we will open a new PR, please complete this one.

@DeathGun44 DeathGun44 force-pushed the WEB-714/enable-submit-to-user-settings branch from 7c311c8 to d2d57e9 Compare March 2, 2026 17:33
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/settings/settings.component.ts`:
- Around line 127-137: The trackChanges subscription only sets hasChanges to
true and never resets it; capture an initial snapshot of the monitored fields
(language, dateFormat, datetimeFormat, decimalsToDisplay) when the form/data is
loaded, then on each change compare current values to that snapshot inside
trackChanges (use the same controls: this.language.value, this.dateFormat.value,
this.datetimeFormat.value, this.decimalsToDisplay.value) and set this.hasChanges
= true only if any value differs, otherwise set this.hasChanges = false so
reverting values clears the flag.
- Around line 141-144: The FormControl.value properties (language, dateFormat,
datetimeFormat, decimalsToDisplay) are typed as string | null and being passed
to non-nullable setters (settingsService.setLanguage, setDateFormat,
setDatetimeFormat, setDecimalToDisplay); update calls to coalesce nulls to safe
defaults (e.g., use nullish coalescing to fall back to the service getters like
settingsService.getLanguage(), getDateFormat(), getDatetimeFormat(),
getDecimalToDisplay()) or alternatively explicitly type the FormControls at
declaration (e.g., FormControl<string> or
FormControl<{name:string;code:string}>) so the .value is non-nullable before
calling those setters.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c311c8 and d2d57e9.

📒 Files selected for processing (4)
  • src/app/settings/settings.component.html
  • src/app/settings/settings.component.scss
  • src/app/settings/settings.component.ts
  • src/assets/translations/en-US.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/app/settings/settings.component.html

@DeathGun44 DeathGun44 force-pushed the WEB-714/enable-submit-to-user-settings branch from d2d57e9 to d73de6d Compare March 2, 2026 17:49
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/app/settings/settings.component.ts (1)

111-120: Tighten form state typing (any → explicit model types).

FormControl<any> on line 111 and initialValues.language: any on line 119 weaken compile-time guarantees. The SettingsService.setLanguage() signature shows the expected type is { name: string; code: string }, so align the form control and state model to this explicit type instead of using any.

♻️ Proposed refactor
+type LanguageOption = { name: string; code: string };
+
-  language = new FormControl<any>('');
+  language = new FormControl<LanguageOption | null>(null);
...
-  private initialValues: { language: any; dateFormat: string; datetimeFormat: string; decimals: string };
+  private initialValues: { language: LanguageOption | null; dateFormat: string; datetimeFormat: string; decimals: string };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/settings/settings.component.ts` around lines 111 - 120, The language
FormControl and initialValues.language are typed too loosely as any; change the
language FormControl generic to the explicit shape { name: string; code: string
} and update the initialValues type signature so initialValues.language: { name:
string; code: string } (keep other properties as-is), then fix any downstream
usages (e.g., places that call SettingsService.setLanguage or read
initialValues.language) to match the stronger type; update imports/types if
needed so the new object type is reused consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/app/settings/settings.component.ts`:
- Around line 111-120: The language FormControl and initialValues.language are
typed too loosely as any; change the language FormControl generic to the
explicit shape { name: string; code: string } and update the initialValues type
signature so initialValues.language: { name: string; code: string } (keep other
properties as-is), then fix any downstream usages (e.g., places that call
SettingsService.setLanguage or read initialValues.language) to match the
stronger type; update imports/types if needed so the new object type is reused
consistently.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d2d57e9 and d73de6d.

📒 Files selected for processing (4)
  • src/app/settings/settings.component.html
  • src/app/settings/settings.component.scss
  • src/app/settings/settings.component.ts
  • src/assets/translations/en-US.json

@DeathGun44 DeathGun44 force-pushed the WEB-714/enable-submit-to-user-settings branch from d73de6d to 1ede337 Compare March 2, 2026 17:57
@DeathGun44
Copy link
Contributor Author

@IOhacker Done!

Signed-off-by: DeathGun44 <krishnamewara841@gmail.com>
@DeathGun44 DeathGun44 force-pushed the WEB-714/enable-submit-to-user-settings branch from 1ede337 to 5a97323 Compare March 5, 2026 15:45
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/settings/settings.component.ts`:
- Around line 133-153: The form dirty-tracking and submit flow currently only
include dateFormat, datetimeFormat, and decimalsToDisplay (see trackChanges,
hasFormChanged, submit) while Language changes are persisted immediately via
LanguageSelectorComponent.setLanguage() calling settingsService.setLanguage(),
causing inconsistent behavior; fix by adding language into the same
initialValues/state, include its FormControl in merge(...) inside trackChanges,
add its comparison in hasFormChanged (compare (this.language.value ?? '') to
this.initialValues.language), and update submit() to call
settingsService.setLanguage(this.language.value ?? this.initialValues.language)
so language follows the unified save flow (or conversely, remove immediate
settingsService.setLanguage call from LanguageSelectorComponent.setLanguage and
delegate to parent submit if you prefer scoping the PR to exclude language).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 45427ba6-37e7-4db7-9b4f-e490f26f819b

📥 Commits

Reviewing files that changed from the base of the PR and between d73de6d and 5a97323.

📒 Files selected for processing (4)
  • src/app/settings/settings.component.html
  • src/app/settings/settings.component.scss
  • src/app/settings/settings.component.ts
  • src/assets/translations/en-US.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/assets/translations/en-US.json

Comment on lines +133 to +153
trackChanges(): void {
merge(this.dateFormat.valueChanges, this.datetimeFormat.valueChanges, this.decimalsToDisplay.valueChanges)
.pipe(takeUntil(this.destroy$))
.subscribe(() => {
this.hasChanges = this.hasFormChanged();
});
}

private hasFormChanged(): boolean {
return (
(this.dateFormat.value ?? '') !== this.initialValues.dateFormat ||
(this.datetimeFormat.value ?? '') !== this.initialValues.datetimeFormat ||
(this.decimalsToDisplay.value ?? '') !== this.initialValues.decimals
);
}

submit(): void {
this.settingsService.setDateFormat(this.dateFormat.value ?? this.initialValues.dateFormat);
this.settingsService.setDatetimeFormat(this.datetimeFormat.value ?? this.initialValues.datetimeFormat);
this.settingsService.setDecimalToDisplay(this.decimalsToDisplay.value ?? this.initialValues.decimals);
this.initialValues = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

❓ Verification inconclusive

Script executed:

#!/bin/bash
set -euo pipefail

echo "== Settings component: language wiring =="
rg -n -C3 "setLanguage|language|initialValues|trackChanges|submit\(" src/app/settings/settings.component.ts

echo
echo "== Language selector implementation =="
fd 'language-selector.component.ts$' src/app -x sh -c '
  echo "--- $1 ---"
  rg -n -C3 "SettingsService|setLanguage|valueChanges|FormControl|localStorage|Output|EventEmitter" "$1"
' sh

Repository: openMF/web-app


Repository: openMF/web-app
Exit code: 0

stdout:

== Settings component: language wiring ==
24-} from '@angular/material/expansion';
25-import { FileUploadComponent } from '../shared/file-upload/file-upload.component';
26-import { ThemePickerComponent } from '../shared/theme-picker/theme-picker.component';
27:import { LanguageSelectorComponent } from '../shared/language-selector/language-selector.component';
28-import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
29-
30-/**
--
112-  /** Decimals to Display Setting */
113-  decimalsToDisplay = new FormControl('');
114-
115:  private initialValues: {
116-    dateFormat: string;
117-    datetimeFormat: string;
118-    decimals: string;
119-  };
120-
121-  ngOnInit() {
122:    this.initialValues = {
123-      dateFormat: this.settingsService.dateFormat,
124-      datetimeFormat: this.settingsService.datetimeFormat,
125-      decimals: this.settingsService.decimals
126-    };
127:    this.dateFormat.patchValue(this.initialValues.dateFormat, { emitEvent: false });
128:    this.datetimeFormat.patchValue(this.initialValues.datetimeFormat, { emitEvent: false });
129:    this.decimalsToDisplay.patchValue(this.initialValues.decimals, { emitEvent: false });
130:    this.trackChanges();
131-  }
132-
133:  trackChanges(): void {
134-    merge(this.dateFormat.valueChanges, this.datetimeFormat.valueChanges, this.decimalsToDisplay.valueChanges)
135-      .pipe(takeUntil(this.destroy$))
136-      .subscribe(() => {
--
140-
141-  private hasFormChanged(): boolean {
142-    return (
143:      (this.dateFormat.value ?? '') !== this.initialValues.dateFormat ||
144:      (this.datetimeFormat.value ?? '') !== this.initialValues.datetimeFormat ||
145:      (this.decimalsToDisplay.value ?? '') !== this.initialValues.decimals
146-    );
147-  }
148-
149:  submit(): void {
150:    this.settingsService.setDateFormat(this.dateFormat.value ?? this.initialValues.dateFormat);
151:    this.settingsService.setDatetimeFormat(this.datetimeFormat.value ?? this.initialValues.datetimeFormat);
152:    this.settingsService.setDecimalToDisplay(this.decimalsToDisplay.value ?? this.initialValues.decimals);
153:    this.initialValues = {
154-      dateFormat: this.dateFormat.value ?? '',
155-      datetimeFormat: this.datetimeFormat.value ?? '',
156-      decimals: this.decimalsToDisplay.value ?? ''

== Language selector implementation ==
--- src/app/shared/language-selector/language-selector.component.ts ---
8-
9-/** Angular Imports */
10-import { Component, inject, Input } from '@angular/core';
11:import { UntypedFormControl, ReactiveFormsModule } from '@angular/forms';
12-
13-/** Custom Services */
14-import { TranslateService } from '@ngx-translate/core';
15:import { SettingsService } from 'app/settings/settings.service';
16-import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
17-
18-/**
--
31-})
32-export class LanguageSelectorComponent {
33-  private translateService = inject(TranslateService);
34:  private settingsService = inject(SettingsService);
35-
36-  /** Appearance of the form field (fill, outline). Defaults to 'fill'. */
37-  `@Input`() appearance: 'fill' | 'outline' = 'fill';
--
40-  `@Input`() showLabel: boolean = true;
41-
42-  /** Language selector form control. */
43:  languageSelector = new UntypedFormControl();
44-
45-  /**
46-   * Sets the language of the application in the selector on initial setup.
--
54-   * Sets a new language to be used by the application.
55-   * `@param` {string} language New language.
56-   */
57:  setLanguage() {
58-    this.translateService.use(this.languageSelector.value);
59:    this.settingsService.setLanguage({ name: '', code: this.languageSelector.value.substring(0, 2) });
60-  }
61-
62-  /**

Language is not included in the new submit-based save flow.

trackChanges() and submit() handle only dateFormat, datetimeFormat, and decimalsToDisplay. The Language setting is persisted through a separate mechanism in LanguageSelectorComponent.setLanguage(), which directly calls settingsService.setLanguage() without going through the parent component's dirty-check or submit flow.

This creates inconsistent behavior: Language changes persist immediately while other settings now require explicit submission. Either wire Language into the same dirty-check + submit path, or explicitly scope this PR to exclude Language changes from the unified save behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/settings/settings.component.ts` around lines 133 - 153, The form
dirty-tracking and submit flow currently only include dateFormat,
datetimeFormat, and decimalsToDisplay (see trackChanges, hasFormChanged, submit)
while Language changes are persisted immediately via
LanguageSelectorComponent.setLanguage() calling settingsService.setLanguage(),
causing inconsistent behavior; fix by adding language into the same
initialValues/state, include its FormControl in merge(...) inside trackChanges,
add its comparison in hasFormChanged (compare (this.language.value ?? '') to
this.initialValues.language), and update submit() to call
settingsService.setLanguage(this.language.value ?? this.initialValues.language)
so language follows the unified save flow (or conversely, remove immediate
settingsService.setLanguage call from LanguageSelectorComponent.setLanguage and
delegate to parent submit if you prefer scoping the PR to exclude language).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants