Static resource is not getting loaded - lwc

I have uploaded the static resource as a "public" content type. I have used the static resource in the LWC and reference that LWC in Community, but those static resource is not getting loaded in the community.
How can i reference the static resource in lwc which is used in static resource?
Code for LWC JS
`import CARD_IMG from '#salesforce/resourceUrl/reviewbuy';
export default class BrolliSummary extends OmniscriptBaseMixin(LightningElement) {
cardImage = CARD_IMG+'/images/Mastercard.png';
visaImage = CARD_IMG+'/images/Visax.png';
amerImage = CARD_IMG+'/images/American Express.png';
}`

Related

Can we customize mapping file names in Wiremock?

I am recording the application through Wiremock using JAVA DSL, Do we have the option to customize the mapping file names? instead of getting the filename which is generated from wiremock..
Example: searchpanel_arrivalairport_th-72f9b8b7-076f-4102-b6a8-aa38710fde1b.json (Generated form wiremock using java )
I am expecting the above file name with my desired naming convention like
seacrpanel_airport_LGW.json
Custom filenames can be added by customizing StubMappingJsonRecorder.
I added CustomStubMappingJsonRecorder and override writeToMappingAndBodyFile method.
if(fileName!=null && !fileName.equals("")){
mappingFileName=fileName+"-mapping.json";
bodyFileName=fileName+"-body.json";
}else {
mappingFileName = UniqueFilenameGenerator.generate(request.getUrl(),
"mapping", filed);
bodyFileName = UniqueFilenameGenerator.generate(request.getUrl(), "body",
fileId, ContentTypes.determineFileExtension(request.getUrl(),
response.getHeaders().getContentTypeHeader(), body));
}
There's no easy way to do this at the moment. It is however possible. As #santhiya-ps says you need to write your own implementation of RequestListener, probably using StubMappingJsonRecorder as a template.
You can't extend it and override writeToMappingAndBodyFile as that method is private, but that is the method you probably want to change.
import com.github.tomakehurst.wiremock.common.*;
import com.github.tomakehurst.wiremock.core.*;
import com.github.tomakehurst.wiremock.http.*;
import java.util.List;
import static com.github.tomakehurst.wiremock.core.WireMockApp.*;
class NameTemplateStubMappingJsonRecorder implements RequestListener {
private final FileSource mappingsFileSource;
private final FileSource filesFileSource;
private final Admin admin;
private final List<CaseInsensitiveKey> headersToMatch;
private final IdGenerator idGenerator = new VeryShortIdGenerator();
public NameTemplateStubMappingJsonRecorder(Admin admin) {
this.mappingsFileSource = admin.getOptions().filesRoot().child(MAPPINGS_ROOT);
this.filesFileSource = admin.getOptions().filesRoot().child(FILES_ROOT);
this.admin = admin;
this.headersToMatch = admin.getOptions().matchingHeaders();
}
#Override
public void requestReceived(Request request, Response response) {
// TODO copy StubMappingJsonRecorder changing as required...
}
}
You can then register your RequestListener as so:
WireMockServer wireMockServer = new WireMockServer();
wireMockServer.addMockServiceRequestListener(
new NameTemplateStubMappingJsonRecorder(wireMockServer)
);
wireMockServer.start();
So long as you still store the mapping files in the expected directory (stored in FileSource mappingsFileSource above, which will be ${rootDir}/mappings, where rootDir is configured as explained in Configuration - File Locations) they should be loaded successfully as all files with extension json in that dir are loaded as mappings.
It would be much easier if StubMappingJsonRecorder took a strategy for generating these names - it might be worth creating an issue on the WireMock repo asking for an easier way to do this. I'd suggest getting an agreement on a basic design before raising a PR though.

Use Open XML SDK to read an Excel Chart Template (*.crtx)

I'm trying to read the colors used in an Excel Chart Template (mychart.crtx). But I can't figure out how to open the file using the Open XML toolkit. It doesn't appear to be possible using SDK Tool.
Can it be done?
This is indeed not possible with the Open XML SDK, because it only provides the WordprocessingDocument (for .docx etc.), SpreadsheetDocument (for .xlsx etc.), and PresentationDocument (for .pptx etc.) classes for opening Word, Excel, and PowerPoint documents and templates.
However, Office documents and your Excel Chart Templates (.crtx) are all based on the Open Packaging Conventions (OPC). You can use the classes provided in the System.IO.Packaging namespace to work with any OPC-based document, including those Excel Chart Templates.
The following picture shows the structure of a sample ChartTemplate.crtx that I created for testing purposes. I used the Open XML Package Editor for Modern Visual Studios to inspect that package.
Using the System.IO.Packaging classes, the Package class represents whole packages (e.g., ChartTemplate.crtx). The PackagePart class represents XML and other files contained in a package. Each PackagePart has a URI (e.g., /chart/chart.xml, /chart/charts/colors1.xml), a content type, and zero or more relationships to other parts.
The following code snippet opens the sample Package, gets the PackagePart, loads the root XML element from the part and makes certain assertions to demonstrate what it got.
[Fact]
public void LoadRootElement_Chart_SuccessfullyLoaded()
{
using Package package = Package.Open("Resources\\ChartTemplate.crtx", FileMode.Open, FileAccess.Read);
PackagePart packagePart = package.GetPart(new Uri("/chart/chart.xml", UriKind.Relative));
XElement rootElement = LoadRootElement(packagePart);
Assert.Equal(C.chartSpace, rootElement.Name);
Assert.NotEmpty(rootElement.Elements(C.chart).Elements(C.title));
Assert.NotEmpty(rootElement.Elements(C.chart).Elements(C.plotArea));
Assert.NotEmpty(rootElement.Elements(C.chart).Elements(C.legend));
}
The LoadRootElement() method is straightforward:
private static XElement LoadRootElement(PackagePart packagePart)
{
using Stream stream = packagePart.GetStream(FileMode.Open, FileAccess.Read);
return XElement.Load(stream);
}
And I've created a helper class C to provide the required XML namespace and names for use with the XElement class, which, like XNamespace and XName, is defined in the System.Xml.Linq namespace.
private static class C
{
public static readonly XNamespace c = "http://schemas.openxmlformats.org/drawingml/2006/chart";
public static readonly XName chart = c + "chart";
public static readonly XName chartSpace = c + "chartSpace";
public static readonly XName lang = c + "lang";
public static readonly XName legend = c + "legend";
public static readonly XName plotArea = c + "plotArea";
public static readonly XName title = c + "title";
public static readonly XName val = "val";
}
As always, the full source code can be found in my CodeSnippets GitHub repository. Look for the ChartTemplateTests class.

How to access to an URL selector at a component level

Scenario: (AEM 6.3.2) I'm requesting a page with the selector "test1", like this:
http://localhost:4502/content/myapp/home.test1.html
This page have a parsys where I have drop a component "slider", so the component's path is: "/content/myapp/home/jcr:content/parsys/slider"
At the "slider" component level, how can I access to the "test1" selector?
I've tried different ways (SlingModel, WCMUsePojo, the "request" HTL Global Object...), but always get the same problem: the "request" I can access is the GET request of the component (GET "/content/myapp/home/jcr:content/parsys/slider.html") where the selector is not present.
You should use the method SlingHttpServletRequest##getPathInfo inherited from HttpServletRequest
In your example, if you make a request to:
http://localhost:4502/content/myapp/home.test1.html
Then in your component's Class (Use/SlingModel) you can call request.getPathInfo() which will return: /content/myapp/home.test1.html
Then you can parse that path using: com.day.cq.commons.PathInfo
Here is an example sling model:
package com.mycom.core.models;
import com.day.cq.commons.PathInfo;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.Self;
#Model(adaptables = SlingHttpServletRequest.class,
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class SampleModel {
#Self
SlingHttpServletRequest request;
public PathInfo getPathInfo() {
return new PathInfo(request.getPathInfo());
}
}
then in your HTML you can do:
<sly data-sly-use.sample="com.mycom.core.models.SampleModel"/>
<div>${sample.pathInfo.selectors # join=', '}</div>
An that will output: (based on your example path)
<div>test1</div>
Just checked the exact same component/code on another AEM instance (same version) and it's working... will check what can be causing the wrong behavior, but I guess the problem is solved!

How do I get a selector from a sling Resource

I have two Sling Models:
#Model(adaptables = {SlingHttpServletRequest.class, Resource.class}, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class VideoGridItem {
#SlingObject
private Resource resource;
#SlingObject
private SlingHttpServletRequest slingHttpServletRequest;
#PostConstruct
public void initVideoGridItem() {
String[] selectors = slingHttpServletRequest.getRequestPathInfo().getSelectors();
insideGrid = selectors == null || selectors.length == 0 ? false : Arrays.stream(selectors).anyMatch("grid"::equals);
url = URLUtils.addHTMLIfPage(resource.getResourceResolver(), linkUrl);
}
}
and
#Model(adaptables = SlingHttpServletRequest.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class VideoListing {
private List<String> videoResourcePaths;
#PostConstruct
final void init() {
}
}
I call the VideoGridItem component (technically the resource which references the model) from the video-listing component using HTL:
<sly data-sly-list.videoResourcePath="${model.videoResourcePaths}">
<sly data-sly-resource="${videoResourcePath # wcmmode='disabled', addSelectors='grid'}" data-sly-unwrap="true"></sly>
</sly>
Now, when I debug the code, inside initVideoGridItem, slingHttpServletRequest is null. Fair enough, this resource isn't being directly requested, but I still need to be able to access the selector "grid". Is there a way I can do this from the VideoGridItem.resource?
Use the #org.apache.sling.models.annotations.injectorspecific.Self annotation instead of #SlingObject for the resource and slingHttpServletRequest fields. The self injector will inject the adaptable object itself (i.e. the Sling request) as well as objects that are adaptable from the same (the resource).
Assuming you always need the selector value for your component to function, you should remove Resource.class from the list of adaptable types in your #Model annotation. This will prevent your model class from being adapted from a Resource object, which will cause the slingHttpServletRequest field to be null and your #PostConstruct method will throw a NullPointerException.
Sorry I didn't reply sooner, but I found my defect and moved on. The issue was that I was creating a VideoGridItem by adapting it from a resource in another place in the code and of course Sling couldn't inject a request. I am now accounting for the null request and my code is working well. Thanks for your answer!

What is the right way to get Page object via Sling Model annotation

I have a property with the path to required page in a content file
...
<some_block
...
sling:resourceType="some_path_to_some_component"
somePage="some_path_to_page"
.../>
...
suitable HTL component some-component.html
<div data-sly-use.some_model="org.example.SomeModel">
...
</div>
and model class SomeModel.java
package org.example;
...
import com.day.cq.wcm.api.Page;
...
#Model(adaptables = { SlingHttpServletRequest.class, Resource.class },
defaultInjectionStrategy = DefaultInjectionStrategy.REQUIRED)
public class RelatedContentBlock {
#ValueMapValue
private Page somePage;
...
}
I easily can get the required Page object using #Inject and #Via annotations, but why can't I grab it with the #ValueMapValue annotation? I tried to use all the possible variants including via attribute and so on. And yes, I can get it from the pageManager, but what's wrong with #ValueMapValue?
Thanks in advance!
The documentation that you linked of the #ValueMapValue annotation has the answer you are looking for:
Annotation to be used on either methods, fields or constructor parameter to let Sling Models inject a value from the ValueMap of the current resource.
The important part is:
inject a value from the ValueMap
A Page is not a ValueMap. Therefore, this annotation can not be used to inject a page.
This annotation is mainly used to inject page properties. Because page properties (or resource properties for that matter) are stored in a ValueMap. That is why you can use the #ValueMapValue annotation to inject the jcr:title of a page:
#ValueMapValue(name = "jcr:title")
private String title;
This is equivalent to (pseudo code):
final ValueMap pageProperites = Page.getProperties();
final String title = pageProperties.get("jcr:title", "" /* default */);