Добавить по умолчанию диалоговое окно с подтверждением сохранения изменений

https://www.cuba-platform.ru/discuss/t/kak-zaprosit-podtverzhdenie-polzovatelya-pri-sohranenii-zapisi-posle-redaktirovaniya/3301

close(WINDOW_COMMIT_AND_CLOSE_ACTION)

2019-07-19%2016%2020%2041

А не могли бы пояснить, в чём состоит ваша идея? Диалог подтверждения работает для всех редакторов из коробки.

Значит что-то сломалось. Использую ваш учебник Руководство по разработке приложений Версия 7.0. При удалении записи выводится окно с запросом подтверждения действия. При создании новой записи и редактировании существующей ничего не выводится, запись сохраняется в любом случае при нажатии кнопки “ОК”. Это работает/не работает в любом Edit экране. В случае создания новой записи это может быть допустимо, но в случае редактирования, считаю что обязательно необходимо запросить у пользователя подтверждения действия, вдруг он случайно что-то изменил в записи.

Использую версию платформы 7.0.9, пробовал 7.0.8 и 7.0.7 - везде одно и то же.

2019-07-22-10-16-44

А для чего выводить подтверждение сохранения? Стандартный диалог предупреждает о том, что несохранённые изменения могут потеряться.

Для кнопки OK вы можете показать такой диалог сами, если ваши системы всегда должны запрашивать подтверждение. Я редко вижу, чтобы любое сохранение требовало подтверждения, это прямо какой-то удар по usability.

2 симпатии

Не понял про стандартный диалог. Где он?

Не любое, а после редактирования существующей записи, раз уж экранные формы не имеют режима/переключения чтения/редактирования, а всегда стразу открываются в режиме редактирования (при наличии прав), то предполагаю, что пользователь может не нарочно что-то изменить в форме. Если у пользователя будет спрашиваться подтверждение сохранения изменений, он будет понимать что что-то изменил. Как альтернативу вижу разные режимы открытия формы - “чтение”/“редактирование”, но не нашел такого поведения в стандартном приложении.

Действие “view” недавно добавили в планы по разработке: https://github.com/cuba-platform/cuba/issues/2270

2 симпатии

Как обычно строятся все приложения у нас - все экранные формы по умолчанию открываются в режиме чтения. Если пользователю необходимо внести изменения в данные, он нажимает кнопку “Изменить” или “Редактировать”, затем целенаправленно и осознано вносит изменения в запись базы данных и затем нажимает кнопку “Сохранить”.

Это позволяет предотвратить непреднамеренные изменения данных, когда наименование контрагента вдруг изменилось потому, что у тёти Клавы на клаву мобила упала. :slight_smile:

Да, это не на Кубе…

1 симпатия

Спасибо, учтем.

Вижу добавили “Enable editing”.

Дано:

  • Таблица основных сущностей Order и таблица подчинённых сущностей Item. Связь “один-ко-многим”.
  • Экранная форма для просмотра таблицы Order, экранная форма для редактирования Order в которую встроена таблица Item, экранная форма для редактирования Item. Все табличные формы/представления имеют действие “view”, кроме обычных. Все формы редактирования сущностей имеют действие “enableEditing”.

Действия:

  • Открываем Order в режиме просмотра действием view.
  • В форме Order открываем в режиме просмотра Item.
  • Разрешаем редактирование Item.
  • Вносим какие-то изменения в Item и нажимаем “Сохранить”.

Результат:

java.lang.IllegalStateException: Range is class

ERROR com.haulmont.cuba.web.log.AppLog - Exception in com.haulmont.cuba.web.widgets.CubaButton:
com.vaadin.server.ServerRpcManager$RpcInvocationException: Unable to invoke method click in com.vaadin.shared.ui.button.ButtonServerRpc
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:157) ~[vaadin-server-8.9.2-27-cuba.jar:8.9.2-27-cuba]
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:115) ~[vaadin-server-8.9.2-27-cuba.jar:8.9.2-27-cuba]
at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:431) ~[vaadin-server-8.9.2-27-cuba.jar:8.9.2-27-cuba]
at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:396) ~[vaadin-server-8.9.2-27-cuba.jar:8.9.2-27-cuba]
at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:260) ~[vaadin-server-8.9.2-27-cuba.jar:8.9.2-27-cuba]
at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:82) ~[vaadin-server-8.9.2-27-cuba.jar:8.9.2-27-cuba]
at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[vaadin-server-8.9.2-27-cuba.jar:8.9.2-27-cuba]
at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1580) ~[vaadin-server-8.9.2-27-cuba.jar:8.9.2-27-cuba]
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:425) ~[vaadin-server-8.9.2-27-cuba.jar:8.9.2-27-cuba]
at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:329) ~[cuba-web-7.2.15.jar:7.2.15]
at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:215) ~[cuba-web-7.2.15.jar:7.2.15]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[servlet-api.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[catalina.jar:9.0.38]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.38]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-websocket.jar:9.0.38]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.38]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.38]
at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) ~[spring-web-5.2.16.RELEASE.jar:5.2.16.RELEASE]
at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) ~[spring-web-5.2.16.RELEASE.jar:5.2.16.RELEASE]
at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:93) ~[cuba-web-7.2.15.jar:7.2.15]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.38]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.38]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[catalina.jar:9.0.38]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[catalina.jar:9.0.38]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[catalina.jar:9.0.38]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[catalina.jar:9.0.38]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[catalina.jar:9.0.38]
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690) ~[catalina.jar:9.0.38]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[catalina.jar:9.0.38]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[catalina.jar:9.0.38]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-coyote.jar:9.0.38]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-coyote.jar:9.0.38]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-coyote.jar:9.0.38]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) ~[tomcat-coyote.jar:9.0.38]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-coyote.jar:9.0.38]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-util.jar:9.0.38]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: java.lang.reflect.InvocationTargetException: null
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:153) ~[vaadin-server-8.9.2-27-cuba.jar:8.9.2-27-cuba]
… 38 common frames omitted
Caused by: java.lang.IllegalStateException: Range is class
at com.haulmont.chile.core.model.impl.ClassRange.asDatatype(ClassRange.java:39) ~[cuba-global-7.2.15.jar:7.2.15]
at com.haulmont.cuba.web.gui.components.WebTextField.convertToModel(WebTextField.java:173) ~[cuba-web-7.2.15.jar:7.2.15]
at com.haulmont.cuba.web.gui.components.WebTextField.convertToModel(WebTextField.java:52) ~[cuba-web-7.2.15.jar:7.2.15]
at com.haulmont.cuba.web.gui.components.WebV8AbstractField.validate(WebV8AbstractField.java:198) ~[cuba-web-7.2.15.jar:7.2.15]
at com.haulmont.cuba.gui.screen.ScreenValidation.validate(ScreenValidation.java:100) ~[cuba-gui-7.2.15.jar:7.2.15]
at com.haulmont.cuba.gui.screen.ScreenValidation.lambda$validateUiComponents$0(ScreenValidation.java:93) ~[cuba-gui-7.2.15.jar:7.2.15]
at com.haulmont.cuba.gui.ComponentsHelper.lambda$traverseValidatable$1(ComponentsHelper.java:96) ~[cuba-gui-7.2.15.jar:7.2.15]
at com.haulmont.cuba.gui.ComponentsHelper.lambda$traverseComponents$0(ComponentsHelper.java:79) ~[cuba-gui-7.2.15.jar:7.2.15]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ~[na:na]
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na]
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655) ~[na:na]
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658) ~[na:na]
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274) ~[na:na]
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497) ~[na:na]
at com.haulmont.cuba.gui.ComponentsHelper.traverseComponents(ComponentsHelper.java:78) ~[cuba-gui-7.2.15.jar:7.2.15]
at com.haulmont.cuba.gui.ComponentsHelper.lambda$traverseComponents$0(ComponentsHelper.java:82) ~[cuba-gui-7.2.15.jar:7.2.15]
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655) ~[na:na]
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658) ~[na:na]
at com.haulmont.cuba.gui.ComponentsHelper.traverseComponents(ComponentsHelper.java:78) ~[cuba-gui-7.2.15.jar:7.2.15]
at com.haulmont.cuba.gui.ComponentsHelper.lambda$traverseComponents$0(ComponentsHelper.java:82) ~[cuba-gui-7.2.15.jar:7.2.15]
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655) ~[na:na]
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658) ~[na:na]
at com.haulmont.cuba.gui.ComponentsHelper.traverseComponents(ComponentsHelper.java:78) ~[cuba-gui-7.2.15.jar:7.2.15]
at com.haulmont.cuba.gui.ComponentsHelper.traverseValidatable(ComponentsHelper.java:94) ~[cuba-gui-7.2.15.jar:7.2.15]
at com.haulmont.cuba.gui.screen.ScreenValidation.validateUiComponents(ScreenValidation.java:92) ~[cuba-gui-7.2.15.jar:7.2.15]
at com.haulmont.cuba.gui.screen.StandardEditor.validateUiComponents(StandardEditor.java:543) ~[cuba-gui-7.2.15.jar:7.2.15]
at com.haulmont.cuba.gui.screen.StandardEditor.validateScreen(StandardEditor.java:528) ~[cuba-gui-7.2.15.jar:7.2.15]
at com.haulmont.cuba.gui.screen.StandardEditor.commitChanges(StandardEditor.java:414) ~[cuba-gui-7.2.15.jar:7.2.15]
at com.haulmont.cuba.gui.screen.StandardEditor.closeWithCommit(StandardEditor.java:600) ~[cuba-gui-7.2.15.jar:7.2.15]
at com.haulmont.cuba.gui.screen.StandardEditor.commitAndClose(StandardEditor.java:566) ~[cuba-gui-7.2.15.jar:7.2.15]
at com.haulmont.bali.events.EventHub.publish(EventHub.java:170) ~[cuba-global-7.2.15.jar:7.2.15]
at com.haulmont.cuba.gui.components.actions.BaseAction.actionPerform(BaseAction.java:222) ~[cuba-gui-7.2.15.jar:7.2.15]
at com.haulmont.cuba.web.gui.components.WebButton.buttonClicked(WebButton.java:67) ~[cuba-web-7.2.15.jar:7.2.15]
at com.haulmont.cuba.web.widgets.CubaButton.fireClick(CubaButton.java:76) ~[cuba-web-widgets-7.2.15.jar:na]
at com.vaadin.ui.Button$1.click(Button.java:57) ~[vaadin-server-8.9.2-27-cuba.jar:8.9.2-27-cuba]
… 43 common frames omitted

Т.е. если основная запись в режиме чтения, а подчинённая редактируется, при попытке сохранить её получаем эксепшен.

Спасибо за сообщение о проблеме.
Какое поведение вы ожидаете в таком случае? Запрещать переход в режим редактирования у Item если владелец Owner в режиме чтения?

Ну, наверное, “да”. Самое очевидное решение. И, мне кажется, это самое простое в реализации.

P.S. Студия предлагает на выбор названия action в этих кнопках, но в списках всё время какая-то ересь не по теме, правильно заполнить значение можно только вписав название акции руками.

Завел тикет: https://github.com/Haulmont/jmix-ui/issues/670

По выбору actions в Студии - в последних версиях Jmix Studio это работает нормально.