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.Link; 017import org.apache.tapestry5.MarkupWriter; 018import org.apache.tapestry5.alerts.Alert; 019import org.apache.tapestry5.alerts.AlertStorage; 020import org.apache.tapestry5.annotations.*; 021import org.apache.tapestry5.corelib.base.BaseClientElement; 022import org.apache.tapestry5.ioc.annotations.Inject; 023import org.apache.tapestry5.json.JSONObject; 024import org.apache.tapestry5.services.Request; 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 * <p/> 032 * Alerts are created using the {@link org.apache.tapestry5.alerts.AlertManager} service. 033 * 034 * @tapestrydoc 035 * @since 5.3 036 */ 037@SupportsInformalParameters 038@Import(stack = "core") 039public class Alerts extends BaseClientElement 040{ 041 042 /** 043 * Allows the button used to dismiss all alerts to be customized (and localized). 044 * 045 * @deprecated Deprecated in Tapestry 5.4; override the {@code core-dismiss-label} message key in 046 * your application's message catalog. This parameter is now ignored. 047 */ 048 @Parameter(value = "message:core-dismiss-label", defaultPrefix = BindingConstants.LITERAL) 049 private String dismissText; 050 051 /** 052 * If set to true, then the "dismiss all" button will not be rendered on the client. 053 * 054 * @since 5.4 055 */ 056 @Parameter(value = "message:private-core-alerts-show-dismiss-all", defaultPrefix = BindingConstants.LITERAL) 057 private boolean showDismissAll; 058 059 @SessionState(create = false) 060 private AlertStorage storage; 061 062 @Inject 063 private DeprecationWarning deprecationWarning; 064 065 @Inject 066 private Request request; 067 068 void onPageLoaded() 069 { 070 deprecationWarning.ignoredComponentParameters(resources, "dismissText"); 071 } 072 073 boolean beginRender(MarkupWriter writer) 074 { 075 Link dismissLink = resources.createEventLink("dismiss"); 076 077 storeElement(writer.element("div", 078 "data-container-type", "alerts", 079 "data-show-dismiss-all", showDismissAll, 080 "data-dismiss-url", dismissLink)); 081 082 resources.renderInformalParameters(writer); 083 writer.end(); 084 085 addAlertsFromStorage(); 086 087 return false; 088 } 089 090 Object onDismiss(@RequestParameter(value = "id", allowBlank = true) Long alertId) 091 { 092 // If the alert was created inside an Ajax request and AlertStorage did not previously 093 // exist, it can be null when the dismiss event comes up from the client. 094 if (storage != null) 095 { 096 if (alertId != null) 097 { 098 storage.dismiss(alertId); 099 } else 100 { 101 storage.dismissAll(); 102 } 103 } 104 105 // See TAP5-1941 106 if (!request.isXHR()) 107 { 108 return true; 109 } 110 111 return new JSONObject(); 112 } 113 114 @HeartbeatDeferred 115 void addAlertsFromStorage() 116 { 117 if (storage == null) 118 { 119 return; 120 } 121 122 for (Alert alert : storage.getAlerts()) 123 { 124 javaScriptSupport.require("t5/core/alert").with(alert.toJSON()); 125 } 126 127 storage.dismissNonPersistent(); 128 } 129}