Skip to content

Commit 6e6f5ef

Browse files
baozhoutaoclaude
andauthored
fix(plugin-form,i18n): form edit saves send If-Match and surface 409 conflicts instead of silently overwriting (#3060)
Every form variant (ObjectForm/ModalForm/DrawerForm/TabbedForm/SplitForm/ WizardForm) wrote records back with an unguarded dataSource.update — two racing editors both got a 200 and the later save silently erased the earlier one. The server already honours If-Match (409 CONCURRENT_UPDATE) and the DataSource contract forwards opts.ifMatch; the forms were the only link not sending it. New shared useOccSave (occSave.tsx): the edit save carries ifMatch = the updated_at the form read via findOne; a 409 opens a conflict dialog whose exits are "Keep editing" (nothing written, form and draft stay open) and "Overwrite" (retry re-keyed to the server's currentVersion). Records without a string updated_at degrade to the old unguarded write. Dialog copy added to all ten locales under form.conflict*. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 9eb932b commit 6e6f5ef

18 files changed

Lines changed: 577 additions & 14 deletions

File tree

packages/i18n/src/locales/ar.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ const ar = {
113113
discardMessage: "لديك تغييرات غير محفوظة. إذا أغلقت هذا النموذج الآن، ستفقد تعديلاتك.",
114114
keepEditing: "متابعة التحرير",
115115
discard: "تجاهل",
116+
conflictTitle: "تعارض في الحفظ",
117+
conflictMessage: "قام شخص آخر بتغيير هذا السجل أثناء تحريرك. الكتابة فوقه ستستبدل تغييراته بتغييراتك.",
118+
conflictLatestVersion: "وقت حفظه: {{time}}",
119+
conflictOverwrite: "الكتابة فوقه",
116120
addItem: "إضافة عنصر",
117121
removeItem: "إزالة عنصر",
118122
fieldRequired: "هذا الحقل مطلوب",

packages/i18n/src/locales/de.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ const de = {
113113
discardMessage: "Sie haben ungespeicherte Änderungen. Wenn Sie dieses Formular jetzt schließen, gehen Ihre Bearbeitungen verloren.",
114114
keepEditing: "Weiter bearbeiten",
115115
discard: "Verwerfen",
116+
conflictTitle: "Speicherkonflikt",
117+
conflictMessage: "Dieser Datensatz wurde während Ihrer Bearbeitung von jemand anderem geändert. Beim Überschreiben werden dessen Änderungen durch Ihre ersetzt.",
118+
conflictLatestVersion: "Deren Speicherung: {{time}}",
119+
conflictOverwrite: "Überschreiben",
116120
addItem: "Element hinzufügen",
117121
removeItem: "Element entfernen",
118122
fieldRequired: "Dieses Feld ist erforderlich",

packages/i18n/src/locales/en.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ const en = {
126126
discardMessage: 'You have unsaved changes. If you close this form now, your edits will be lost.',
127127
keepEditing: 'Keep editing',
128128
discard: 'Discard',
129+
conflictTitle: 'Save conflict',
130+
conflictMessage: 'This record was changed by someone else while you were editing. Overwriting will replace their changes with yours.',
131+
conflictLatestVersion: 'Their save: {{time}}',
132+
conflictOverwrite: 'Overwrite',
129133
stepOf: 'Step {{current}} of {{total}}',
130134
createTitle: 'Create {{object}}',
131135
editTitle: 'Edit {{object}}',

packages/i18n/src/locales/es.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ const es = {
113113
discardMessage: "Tiene cambios sin guardar. Si cierra este formulario ahora, sus ediciones se perderán.",
114114
keepEditing: "Seguir editando",
115115
discard: "Descartar",
116+
conflictTitle: "Conflicto al guardar",
117+
conflictMessage: "Otra persona modificó este registro mientras lo editaba. Sobrescribir reemplazará sus cambios por los suyos.",
118+
conflictLatestVersion: "Su guardado: {{time}}",
119+
conflictOverwrite: "Sobrescribir",
116120
addItem: "Añadir elemento",
117121
removeItem: "Eliminar elemento",
118122
fieldRequired: "Este campo es obligatorio",

packages/i18n/src/locales/fr.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ const fr = {
113113
discardMessage: "Vous avez des modifications non enregistrées. Si vous fermez ce formulaire maintenant, vos modifications seront perdues.",
114114
keepEditing: "Continuer l'édition",
115115
discard: "Abandonner",
116+
conflictTitle: "Conflit d'enregistrement",
117+
conflictMessage: "Cet enregistrement a été modifié par quelqu'un d'autre pendant votre édition. L'écrasement remplacera ses modifications par les vôtres.",
118+
conflictLatestVersion: "Son enregistrement : {{time}}",
119+
conflictOverwrite: "Écraser",
116120
addItem: "Ajouter un élément",
117121
removeItem: "Supprimer un élément",
118122
fieldRequired: "Ce champ est obligatoire",

packages/i18n/src/locales/ja.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ const ja = {
113113
discardMessage: "保存されていない変更があります。このままフォームを閉じると編集内容は失われます。",
114114
keepEditing: "編集を続ける",
115115
discard: "破棄",
116+
conflictTitle: "保存の競合",
117+
conflictMessage: "編集中にこのレコードが他のユーザーによって変更されました。上書きすると、相手の変更はあなたの内容で置き換えられます。",
118+
conflictLatestVersion: "相手の保存時刻: {{time}}",
119+
conflictOverwrite: "上書き",
116120
addItem: "項目を追加",
117121
removeItem: "項目を削除",
118122
fieldRequired: "この項目は必須です",

packages/i18n/src/locales/ko.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ const ko = {
113113
discardMessage: "저장하지 않은 변경 내용이 있습니다. 지금 이 양식을 닫으면 편집 내용이 사라집니다.",
114114
keepEditing: "계속 편집",
115115
discard: "버리기",
116+
conflictTitle: "저장 충돌",
117+
conflictMessage: "편집하는 동안 다른 사용자가 이 레코드를 변경했습니다. 덮어쓰면 상대방의 변경 내용이 내 내용으로 대체됩니다.",
118+
conflictLatestVersion: "상대방 저장 시각: {{time}}",
119+
conflictOverwrite: "덮어쓰기",
116120
addItem: "항목 추가",
117121
removeItem: "항목 제거",
118122
fieldRequired: "이 필드는 필수입니다",

packages/i18n/src/locales/pt.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ const pt = {
113113
discardMessage: "Você tem alterações não salvas. Se fechar este formulário agora, suas edições serão perdidas.",
114114
keepEditing: "Continuar editando",
115115
discard: "Descartar",
116+
conflictTitle: "Conflito ao salvar",
117+
conflictMessage: "Outra pessoa alterou este registro enquanto você editava. Sobrescrever substituirá as alterações dela pelas suas.",
118+
conflictLatestVersion: "Salvamento dela: {{time}}",
119+
conflictOverwrite: "Sobrescrever",
116120
addItem: "Adicionar item",
117121
removeItem: "Remover item",
118122
fieldRequired: "Este campo é obrigatório",

packages/i18n/src/locales/ru.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ const ru = {
113113
discardMessage: "Есть несохранённые изменения. Если закрыть форму сейчас, правки будут потеряны.",
114114
keepEditing: "Продолжить редактирование",
115115
discard: "Отменить",
116+
conflictTitle: "Конфликт сохранения",
117+
conflictMessage: "Пока вы редактировали, эту запись изменил другой пользователь. Перезапись заменит его изменения вашими.",
118+
conflictLatestVersion: "Его сохранение: {{time}}",
119+
conflictOverwrite: "Перезаписать",
116120
addItem: "Добавить элемент",
117121
removeItem: "Удалить элемент",
118122
fieldRequired: "Это поле обязательно",

packages/i18n/src/locales/zh.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ const zh = {
125125
discardMessage: '您有未保存的更改。如果现在关闭此表单,您的编辑将会丢失。',
126126
keepEditing: '继续编辑',
127127
discard: '放弃',
128+
conflictTitle: '保存冲突',
129+
conflictMessage: '您编辑期间,这条记录已被其他人修改。覆盖保存将用您的内容替换对方的修改。',
130+
conflictLatestVersion: '对方保存时间:{{time}}',
131+
conflictOverwrite: '覆盖保存',
128132
stepOf: '第{{current}}步,共{{total}}步',
129133
createTitle: '新建{{object}}',
130134
editTitle: '编辑{{object}}',

0 commit comments

Comments
 (0)