What is the proper way to style the error message for Global Message? - sap-commerce-cloud

I want to apply some script and styling for a specfic error message for the corresponding GlobalMessage class, and wanted to know the way to achieve this without disturbing other error messages or flash messages from this class.

Extend class de.hybris.platform.acceleratorstorefrontcommons.controllers.util.GlobalMessage like this:
class StylableGlobalMessage extends GlobalMessage {
private cssClass;
setCssClass...
getCssClass...
}
Create a new method to add this message to the model. Analogue to
de.hybris.platform.acceleratorstorefrontcommons.controllers.util.GlobalMessages#addMessage
final StylableGlobalMessage message = new StylableGlobalMessage();
message.setCode(messageKey);
message.setAttributes(attributes != null ? Arrays.asList(attributes) : Collections.emptyList());
message.setCssClass(cssClass);
List<GlobalMessage> currentMessages = (List<GlobalMessage>) model.getModelMap().get(messageHolder);
// Check if null etc.
currentMessages.add(message);
Introduce new attribute to file /mystorefront/web/webroot/WEB-INF/tags/desktop/common/globalMessages.tag like this:
<div class="alert neutral ${msg.cssClass}">
<spring:theme code="${msg.code}" arguments="${msg.attributes}"/>
</div>
Keep in mind to check the type of msg before accessing cssClass attribute. Or you replace every GlobalMessage with StylableGlobalMessage. Then you can omit the check.

Related

How to combine Blazor Component Modal Prompts so I only need to have one for all validations

I have defined a blazor component that handles error prompts. If I need to display an error prompt I do the following.
#if (NoCharacterName)
{
<PromptModalComponent OnModalChange="NoCharacterName_Response"
messageTitle="Warning!"
message="Please enter a name for your character"
Type="warning"
ConfirmButtonText="Continue"
NoCancelButton="True"
#ref="#modalPrompt"></PromptModalComponent>
}
#if (NoSexSelected)
{
<PromptModalComponent OnModalChange="NoSexSelected_Response"
messageTitle="Warning!"
message="Please select a sex for your character"
Type="warning"
ConfirmButtonText="Continue"
NoCancelButton="True"
#ref="#modalPrompt"></PromptModalComponent>
}
#if (NoBookInUse)
{
<PromptModalComponent OnModalChange="NoBookInUse_Response"
messageTitle="Warning!"
message="Please Select a book to use"
Type="warning"
ConfirmButtonText="Continue"
NoCancelButton="True"
#ref="#modalPrompt"></PromptModalComponent>
}
Can this be done and I only have one of the modal components listed? Therefore I can update the message, messageTitle, and other parameters without having to have a component for each possible warning?
Use a List<T> and create a foreach where you render each modal.
Example:
#foreach (var validationError in ValidationErrors)
{
<PromptModalComponent OnModalChange="#validationError.OnChangeEvent"
messageTitle="#validationError.Title"
message="#validationError.Message"
Type="#validationError.Type"
ConfirmButtonText="#validationError.ConfirmButtonText"
NoCancelButton="#validationError.HasCancel" />
}
Can't give an example of #ref="#modalPrompt", because I do not know how this object is used.
Although, my opinion this is not user friendly. I would create one modal to list all validation errors, which also simplifies your code. But only if modals are some requirement.
But if it is not required, use DataAnnotations and EditContext with the EditForm component containing DataAnnotationsValidator and ValidationSummary or ValidationMessage components and show these validation errors as the user edits the form.
You can also create custom validation using DataAnnotations and EditContext.
On top of this you can also create custom attributes inheriting the ValidationAttribute class to further automate your validation needs.

Get stream, System message customisation stream-chat

community
I implemented stream-chat & stream-chat-react getStream
Hi, I want to show the system message on some events
For Ex: User A added User B to the chat (Here user A and User B is the name of both user but I don't want to send those message as it is because I want if user A changes their name to USER X then those previous messages also updated.) I want guidance on how I can achieve this.
Stream is allowing me to send system messages with the addMemberToChannel event but I am not able to find how I can use it for my specific case.
Expected Output:
For your case, you will avoid saving hardcoded data in the message's text property.
First, you create a system message on adding a user to a channel like this:
channel.addMembers([userId], {
text: 'added_users',
mentioned_users: [userId],
});
With the addMembers method on a channel object, you can add members to a channel and also pass a message object.
The message object accepts the message text and the mentioned_users properties.
You can use added_users or any text that you want to keep as a standard message for adding-members-system-message. You'll see why I use "added_users" in a second.
The Channel component renders system messages using the EventComponent. This component displays the text of the system message, with the date and some added styles.
You can create a custom event message component for your added_users message. This component can look like this:
import { EventComponent } from 'stream-chat-react';
function CustomEventMessage(props) {
const { message } = props;
const { text, mentioned_users, user } = message;
if (text === 'added_users') {
const message = user?.name + ' added ' + mentioned_users[0].name;
return (
<div className="str-chat__message--system">
<div className="str-chat__message--system__text">
<div className="str-chat__message--system__line"></div>
<p>{message}</p>
<div className="str-chat__message--system__line"></div>
</div>
</div>
);
}
// use the default event component
return <EventComponent {...props} />;
}
The CustomEventMessage component above accepts a message object prop which has the:
text: system message text
mentioned_users: mentioned users in the message
user: user who triggered the message
Next, you check if the text is added_users. If it is, then you provide a custom UI and message, which consists of the name of the user who triggered the message and the mentioned user (who was added to the channel)
I also used classnames from Stream's stylesheets so that I don't have to build mine.
Next, you add this component to the Channel component:
<Channel MessageSystem={CustomEventMessage}>
// ...
</Channel>
The message will now read as "Person X added Person Y" as seen in the image below:
If the text is not added_users, you pass the props to the default EventComponent.
Since you're saving the id of the mentioned user and not hardcoding the text ("Person A added Person B"), you will also get updated details about the users, even when they update their information.

Orchard CMS front-end all possible content filtering by user permissions

Good day!
In my Orchard, I have several content types all with my custom part attached. This part defines to what users this content is available. For each logged user there is external service, which defines what content user can or cannot access. Now I need access restriction to apply everywhere where orchard display content lists, this includes results by specific tag from a tag cloud, or results listed from Taxonomy term. I seems can’t find any good way to do it except modifying TaxonomyServices code as well as TagCloud services, to join also my part and filter by it. Is this indeed the only way to do it or there are other solutions? I would like to avoid doing changes to built-in modules if possible but cannot find other way.
Thanks in advance.
I'm currently bumbling around with the same issue. One way I'm currently looking at is to hook into the content manager.
[OrchardSuppressDependency("Orchard.ContentManagement.DefaultContentManager")]
public class ModContentManager : DefaultContentManager, IContentManager
{
//private readonly Lazy<IShapeFactory> _shapeFactory;
private readonly IModAuthContext _modAuthContext;
public ModContentManager(IComponentContext context,
IRepository<ContentTypeRecord> contentTypeRepository,
IRepository<ContentItemRecord> contentItemRepository,
IRepository<ContentItemVersionRecord> contentItemVersionRepository,
IContentDefinitionManager contentDefinitionManager,
ICacheManager cacheManager,
Func<IContentManagerSession> contentManagerSession,
Lazy<IContentDisplay> contentDisplay,
Lazy<ISessionLocator> sessionLocator,
Lazy<IEnumerable<IContentHandler>> handlers,
Lazy<IEnumerable<IIdentityResolverSelector>> identityResolverSelectors,
Lazy<IEnumerable<ISqlStatementProvider>> sqlStatementProviders,
ShellSettings shellSettings,
ISignals signals,
//Lazy<IShapeFactory> shapeFactory,
IModAuthContext modAuthContext)
: base(context,
contentTypeRepository,
contentItemRepository,
contentItemVersionRepository,
contentDefinitionManager,
cacheManager,
contentManagerSession,
contentDisplay,
sessionLocator,
handlers,
identityResolverSelectors,
sqlStatementProviders,
shellSettings,
signals) {
//_shapeFactory = shapeFactory;
_modAuthContext = modAuthContext;
}
public new dynamic BuildDisplay(IContent content, string displayType = "", string groupId = "") {
// So you could do something like...
// var myPart = content.As<MyAuthoPart>();
// if(!myPart.IsUserAuthorized)...
// then display something else or display nothing (I think returning null works for this but
//don't quote me on that. Can always return a random empty shape)
// else return base.BuildDisplay(content, displayType, groupId);
// ever want to display a shape based on the name...
//dynamic shapes = _shapeFactory.Value;
}
}
}
Could also hook into the IAuthorizationServiceEventHandler, which is activated before in the main ItemController and do a check to see if you are rendering a projection or taxonomy list set a value to tell your content manager to perform checks else just let them through. Might help :)

Kentico 7 hide editable text if it's empty

I have an editable text web part on a page template. It has a custom HTML envelope before and after the text. How can I hide the whole thing, envelope included, if the editable text is empty?
I need to hide it because the envelope adds stylized markup that shouldn't be visible when there is no text.
Can it be done with a K# snippet on the Visible property? I'm unclear how interrogating a document's property works.
Thanks!
Try this as the "Visible" property:
{% (ViewMode != "LiveSite") || (CMSContext.CurrentDocument.editabletext != "") #%}
Change "editabletext" to whatever you have for your web part control ID.
I'm not familiar with Kentico but these solutions might help. They may not address your problem specifically but might aid in a solution.
CMSEditableImage Extension Method
I came up with a way to check this, I added an extension method for
the CMSEditableImage class that takes the CurrentPage PageInfo object
to check the value of the editable region, don't know if this is the
best way or not, but here's the code.
public static bool IsPopulated(this CMSEditableImage editableImage, PageInfo currentPage)
{
bool isPopulated = false;
string value = currentPage.EditableItems.EditableRegions[editableImage.ID.ToLower()].ToString();
if (!string.IsNullOrEmpty(value))
{
value = value.ToUpper();
isPopulated = (value == "<IMAGE><PROPERTY NAME=\"IMAGEPATH\"></PROPERTY></IMAGE>") ? false : true;
}
return isPopulated;
}
via http://devnet.kentico.com/Forums/f19/fp5/t4454/Empty-CMSEditableImage.aspx
JavaScript Method
The webcontainer needs an id, example:
<h2 id="webpart-header">Headline</h2>
Then I have a small javascript function that is attached in an
external js file:
/* Hide Webcontainer via javascript if empty*/
function hideLayer(element) {
elem = document.getElementById( element );
elem.style.display = "none";
}
Now in the wep part configuration, at no data behaviour, you uncheck the checkbox and call the js function by entering following
script in the no record found text: hideLayer("webpart-header");
Whereby webpart-header the id name of your container is. You could
also have a more complex <div> structure here.
via http://devnet.kentico.com/Forums/f22/fp3/t4180/Webcontainer-and-hide-if-no-data.aspx

Customizing search feature in Play's CRUD module

Edit: searching appears to work in a very basic manner, searching for whatever text is entered in all the String member fields of the relevant model, with no special search operators.
If there's any way to customize how the search works, I'd like to know. Right now it's looking like I'll just have to ignore the built-in search stuff and roll my own.
Since adding the notes field, it's started returning nothing instead of everything.
The only thing that was worked so far is entering "test" in the search box, which returns the record with "test" in the notes field. Searching for "notes:test" or "notes=test" doesn't work, nor does any attempt to search the agent or status fields. I've tried things like "1400" which is a value I've verified is present in the agent field via phpMyAdmin, and things like "0" or "VALID" for the status field, which is what all the records have.
model fields:
public class AgentShift extends Model {
public enum Status { VALID, RESCHEDULED, EXTENDED, DELETED } // REDUCED?
#Required #Min(1000) #Max(99999)
public int agent;
public Status status = Status.VALID;
#Required
#Columns(columns={#Column(name="start_time"),#Column(name="end_time")})
#Type(type="org.joda.time.contrib.hibernate.PersistentInterval")
public Interval scheduled;
#Type(type="org.joda.time.contrib.hibernate.PersistentLocalTimeAsTime")
public LocalTime agent_in;
#Type(type="org.joda.time.contrib.hibernate.PersistentLocalTimeAsTime")
public LocalTime agent_out;
public String notes;
}
modified crud list page:
#{extends 'main.html' /}
#{set title: 'Agent Shifts' /}
<div id="crudList" class="${type.name}">
<h2 id="crudListTitle">&{'crud.list.title', type.name}</h2>
<div id="crudListSearch">
#{crud.search /}
</div>
<div id="crudListTable">
#{crud.table fields:['id','agent','scheduled','status','notes'] }
#{crud.custom 'scheduled'}
#{if object.scheduled.getStart().toDateMidnight().equals(object.scheduled.getEnd().toDateMidnight())}
${org.joda.time.format.DateTimeFormat.forStyle("SS").printTo(out, object.scheduled.getStart())} to
${org.joda.time.format.DateTimeFormat.forStyle("-S").printTo(out, object.scheduled.getEnd())}
#{/if}
#{else}
${org.joda.time.format.DateTimeFormat.forStyle("SS").printTo(out, object.scheduled.getStart())} to
${org.joda.time.format.DateTimeFormat.forStyle("SS").printTo(out, object.scheduled.getEnd())}
#{/else}
#{/crud.custom}
*{
#{crud.custom 'entered_by'}
#{if object.entered_by}
${object.entered_by}
#{/if}
#{else} ?
#{/else}
#{/crud.custom}
#{crud.custom 'created'}
${org.joda.time.format.DateTimeFormat.forStyle("SS").printTo(out, object.created)}
#{/crud.custom}
}*
#{/crud.table}
</div>
<div id="crudListPagination">
#{crud.pagination /}
</div>
<p id="crudListAdd">
&{'crud.add', type.modelName}
</p>
</div>
Here you can see how to customize the CRUD pages, including how to show certain fields of the object in the screen.
The search strings are supposed to be in the format:
<field name>:<value>
For example:
name:Liam
That search would filter all objects whose name contains Liam. The field name must be a field displayed in the list page. I'm not sure if it works with #Lob, but usually that's not a field you want to display in the list page so it shouldn't be an issue.
I have to say that in Play 1.1 I had some issues with some columns, in which starting the search didn't work (it raised an error) and I couldn't solve it. It doesn't seem to happen in 1.2.1 (I have no idea if it is a fix or simply a change I did without noticing)
EDIT:
On the updated question, the list page seems right.
One bold idea: have you checked that the database has the proper columns? I remember I had some issues with Hibernate not playing fair when I changed some models and a few columns where not updated properly, causing odd behavior. It may be worth it to remove the table completely and let Play recreate it.
If that doesn't solve it most likely this is a Play bug in the CRUD controller, you would need to find the source.
My first concern would be the lack on a rel annotation on Interval, and the usage of LocalTime and the enum Status. It should not matter, but... I'm afraid I can only suggest you to do an incremental test to locale the issue:
remove everything except agent and notes, and try the search.
If it fails, raise a bug on Play's Lighthouse as it shouldn't
If it works, keep adding fields one at a time and retesting the search. This will be fast with Play, and you may detect the annotation/field causing the issue and report on Play's Lighthouse
You can use the elastic search module.
1) Define Controller:
#ElasticSearchController.For(ElasticSearchSampleModel.class)
public class ElasticSearchExample extends ElasticSearchController {
}
2) Define standard JPA model with #ElasticSearchable annotation:
#Entity
#ElasticSearchable
public class ElasticSearchSampleModel extends Model {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;
/** The field1. */
public String field1;
/** The field2. */
public String field2;
/**
* To String
*
* #see play.db.jpa.JPABase#toString()
*/
#Override
public String toString() {
return "ElasticSearchSampleModel [field1=" + this.field1 + ", field2=" + this.field2 + "]";
}
}
You can find more information at http://geeks.aretotally.in/play-framework-module-elastic-search-distributed-searching-with-json-http-rest-or-java.

Resources