001// Licensed under the Apache License, Version 2.0 (the "License"); 002// you may not use this file except in compliance with the License. 003// You may obtain a copy of the License at 004// 005// http://www.apache.org/licenses/LICENSE-2.0 006// 007// Unless required by applicable law or agreed to in writing, software 008// distributed under the License is distributed on an "AS IS" BASIS, 009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 010// See the License for the specific language governing permissions and 011// limitations under the License. 012 013package org.apache.tapestry5.corelib.components; 014 015import org.apache.tapestry5.BindingConstants; 016import org.apache.tapestry5.MarkupWriter; 017import org.apache.tapestry5.alerts.Alert; 018import org.apache.tapestry5.alerts.AlertStorage; 019import org.apache.tapestry5.annotations.*; 020import org.apache.tapestry5.corelib.base.BaseClientElement; 021import org.apache.tapestry5.http.Link; 022import org.apache.tapestry5.http.services.Request; 023import org.apache.tapestry5.ioc.annotations.Inject; 024import org.apache.tapestry5.json.JSONObject; 025import org.apache.tapestry5.services.compatibility.DeprecationWarning; 026 027/** 028 * Renders out an empty {@code <div>} element and provides JavaScript initialization to make the element 029 * the container for alerts. After rendering markup (and initialization JavaScript), it 030 * {@linkplain org.apache.tapestry5.alerts.AlertStorage#dismissNonPersistent() removes all non-persistent alerts}. 031 * 032 * Alerts are created using the {@link org.apache.tapestry5.alerts.AlertManager} service. 033 * 034 * @tapestrydoc 035 * @since 5.3 036 */ 037@SupportsInformalParameters 038public class Alerts extends BaseClientElement 039{ 040 041 /** 042 * Allows the button used to dismiss all alerts to be customized (and localized). 043 * 044 * @deprecated Deprecated in Tapestry 5.4; override the {@code core-dismiss-label} message key in 045 * your application's message catalog. This parameter is now ignored. 046 */ 047 @Parameter(value = "message:core-dismiss-label", defaultPrefix = BindingConstants.LITERAL) 048 private String dismissText; 049 050 /** 051 * If set to true, then the "dismiss all" button will not be rendered on the client. 052 * 053 * @since 5.4 054 */ 055 @Parameter(value = "message:private-core-alerts-show-dismiss-all", defaultPrefix = BindingConstants.LITERAL) 056 private boolean showDismissAll; 057 058 @SessionState(create = false) 059 private AlertStorage storage; 060 061 @Inject 062 private DeprecationWarning deprecationWarning; 063 064 @Inject 065 private Request request; 066 067 void onPageLoaded() 068 { 069 deprecationWarning.ignoredComponentParameters(resources, "dismissText"); 070 } 071 072 boolean beginRender(MarkupWriter writer) 073 { 074 Link dismissLink = resources.createEventLink("dismiss"); 075 076 storeElement(writer.element("div", 077 "data-container-type", "alerts", 078 "data-show-dismiss-all", showDismissAll, 079 "data-dismiss-url", dismissLink)); 080 081 resources.renderInformalParameters(writer); 082 writer.end(); 083 084 addAlertsFromStorage(); 085 086 return false; 087 } 088 089 Object onDismiss(@RequestParameter(value = "id", allowBlank = true) Long alertId) 090 { 091 // If the alert was created inside an Ajax request and AlertStorage did not previously 092 // exist, it can be null when the dismiss event comes up from the client. 093 if (storage != null) 094 { 095 if (alertId != null) 096 { 097 storage.dismiss(alertId); 098 } else 099 { 100 storage.dismissAll(); 101 } 102 } 103 104 // See TAP5-1941 105 if (!request.isXHR()) 106 { 107 return true; 108 } 109 110 return new JSONObject(); 111 } 112 113 @HeartbeatDeferred 114 void addAlertsFromStorage() 115 { 116 if (storage == null) 117 { 118 return; 119 } 120 121 for (Alert alert : storage.getAlerts()) 122 { 123 javaScriptSupport.require("t5/core/alert").with(alert.toJSON()); 124 } 125 126 storage.dismissNonPersistent(); 127 } 128}