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