Theming on Multi-Site scenario? - spartacus-storefront

We're trying to implement Spartacus on an existing Project and now facing the issue to provide different styles for each existing base site (for example "electronics", "appearal"). So distinguished by the URL we can access each base sites content (electronics.local:4200 and appearal.local:4200 are served by the same app but have different content).
How to configure different styles like in the accelerator by setting the theme property in CMS (backoffice) for each basesite in Spartacus?
Thanks in advance!

With some kind help from the spartacus slack channel I've came to a solution that is quiet solid but not linked directly to the theme property of a base site from CMS (backoffice). It is just retrieving current BaseSite and according to that adds a class to cx-storefront tag in app.component.
app.component.ts:
export class AppComponent {
public $activeSite: Observable<string> = this.baseSiteService.getActive();
constructor(
private baseSiteService: BaseSiteService
) {
}
}
app.component.html:
<ng-container *ngIf="$activeSite | async as activeSite">
<cx-storefront [ngClass]="activeSite"></cx-storefront>
</ng-container>
Now I've got a css-class equal to current BaseSite UID in the cx-storefront dom element and am able to apply my styles accordingly:
<cx-storefront class="electronics stop-navigating" _ngcontent-ipq-c296="" ng-reflect-ng-class="electronics" tabindex="0">

Related

How to build web component with styling library using vite and vue 3?

I am able to build vue web component and load it in other pages, but I can't find document how to correctly include a UI framework. It seems the web component is under shadowDOM and import css using style tag won't work.
(Add the CDN link in the template and style is applied)
Any hint on any framework, Vuetify or Ant Design or Tailwind CSS will be appreciated.
Similar question: Vuetify build as Web component style not showing
Using custom elements without Shadow DOM is trivial. Just add like the way you do traditionally. However, with Shadow DOM, things are tricky. Only inheritable CSS styles pass through the Shadow DOM. Everything else is blocked. No straight forward integration with existing design systems (Vuetify, Ant, etc.) is not directly possible if that library is only exposing global CSS.
If the design system or a component library is exposing styles i.e. css files for individual components, then you can that with some effort.
The best solution is to use constructable stylesheet. You can use a bundler like Webpack to load the stylesheet for individual component (if and only if it is provided) as a string and feed it to the stylesheet constructor method as illustrated here.
// Read SCSS file as a raw CSS text using Webpack/Rollup/Parcel
import styleText from './my-component.scss';
const sheet = new CSSStyleSheet();sheet.replaceSync(styleText);
// Use the sheet inside the web component constructor
shadowRoot.adoptedStyleSheets = [sheet];
However, Firefox and Safari are yet to implement it.
If you need a fallback, then there are ways that are not so clean. Approach is same. Import the CSS/SCSS as a string and using the template literal, add it to the element's inner style tag.
import styleText from 'ant/button.css';
class FancyComponent extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = `
<!-- Styles are scoped -->
<style>
${styleText}
</style>
<div>
<p>Hello World</p>
</div>
`;
}
}
customElements.define('fancy-comp', FacyComponent);
This all relies on the assumption that ant/material/veutify is exposing styles as individual files instead of one global file.
Alternately, the browsers have started supporting the link tag inside the Shadow DOM. But again it is really useful if you have styles for individual components. Read more about that here.

Cannot map custom js to my custom template in bigcommerce shopica theme with stencil

I 've added custom page and js for it in stencil bigcommerce.
It works fine locally but when I push it on bigcommerce, it does not work well.
I have added custom template template/pages/custom/page/custom-layout.html and I've added custom js for it in assets/js/custom/custom.js.
I've configured some loading settings in assets/js/app.js as follows:
const customClasses = {
'pages\\custom\\page\\custom-layout': () => import('./custom/custom')
}
It works locally; but, on a server, it does not at all.
Your customClasses object should use forward slashes like so:
"pages/custom/page/custom-layout": () => import("./custom/custom")
You should also make sure that your custom.js file is extending the PageManager class like so:
import PageManager from "../page-manager";
export default class CustomClass extends PageManager {
constructor(context) {
super(context);
// other constructor code here
}
onReady() {
// your code for the onReady event here
}
// ... any other code
}
If this is done properly your custom JS class will be injected to the page. However, once you bundle and upload your theme, you must also make sure to apply your custom template to the page, as the config.stencil.json file is not packaged with your theme. This can be done from within the BigCommerce control panel by going to Storefront > Web Pages > [Your page] and changing the Template Layout File accordingly.

How to extend the Spartacus PLP page

In Spartacus PLP page, I am trying to extend PLP page.
Below is module and ts code
ConfigModule.withConfig({
cmsComponents: {
CMSProductGridComponent: {
component: ProductsGridComponent
}
}
} as CmsConfig)
In ts file
export class ProductsGridComponent extends ProductGridItemComponent{}
Issue
The OOTB search call is not happening. When I comment the override in module file OOTB search API is happening. Is there any mistake for extend PLP page ?
Can any help on this?
Look at the CategoryPageMetaResolver. It seems you might have to override the hasProductListComponent check:
You need to create a service that extends CategoryPageMetaResolver.
Override hasProductListComponent so that it will identify your
ProductsGridComponent as a 'ProductListComponent'.
Provide the service in a module -
{provide:CategoryPageMetaResolver,useClass:MyCategoryPageMetaResolver}.

Razor Pages Default Page in aspnetcore 2

By default a Razor Page app goes to Home/Index
Is there a way to change this to Home/App?
This is quite easy in MVC, but Razor pages using a different routing setup and thus MVC routing does not apply.
I would think it would be in options somewhere, but I don't see it:
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions.AuthorizeFolder("/Account/Manage");
options.Conventions.AuthorizePage("/Account/Logout");
options. ??SetDefaultPage??
});
I have tried this:
options.Conventions.AddPageRoute("/App", "");
But now two default routes are found and an error is generated:
AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied:
Page: /App
Page: /Index
It's possible to resolve this error by removing Pages/Index.cshtml from the project, but I wanted to keep that page as well.
In my case the ambiguity was caused by Pages/Index.cshtml left in project.
This worked:
options.Conventions.AddPageRoute("/App", "");
remove or rename Pages/Index.cshtml
Pretty sure it isn't possible. The docs say the runtime controls the search for Index as the default. I couldn't find where that happens in the current release, but IndexFileName is a static in the new internal PageRouteModelFactory class added to the upcoming release:
private static readonly string IndexFileName = "Index" + RazorViewEngine.ViewExtension;
It doesn't seem like it would be difficult to just add a config property to RazorPagesOptions, though. The ASP.NET guys are pretty responsive, I'd open a request as a GitHub issue and hope for the best.
I solved the issue by using Microsoft.AspNetCore.Rewrite:
Then adding code to replace the default Index action, in my case with Portfolio:
var options = new RewriteOptions()
.AddRedirect("^", "portfolio"); // Replace default index page with portfolio
More detailed article about rewrite options - https://learn.microsoft.com/en-us/aspnet/core/fundamentals/url-rewriting?tabs=aspnetcore2x
Another way is to simply redirect from the Index OnGet method, like so:
public class IndexModel : PageModel
{
public IActionResult OnGet()
{
return Redirect("/Welcome");
}
}
Notice that I have change the return type of the OnGet method.

kendo ui editorfor imagebrowser returns 403

I'm new to web development and I'm trying to implement the Kendo UI editor with an image browser to insert into the document on an MVC 4.5 page. the editor is working fine, however, when i click the insert image button i gt a 403 forbidden popup message.
I've created a custom image browser controller pointing to ~/Content/images.
and in my view, i am using the custom browser controller within my code
#(Html.Kendo().EditorFor(m => m.QuestionText)
.Encode(false)
.HtmlAttributes(new { style = "width: 100%; height: 200px" })
.Name("EditQuestionText")
.Tools(tools => tools.Clear().InsertImage())
.ImageBrowser(imageBrowser => imageBrowser
.Image("~/JFA/QuestionImages/{0}")
.Read("Read", "JFAImageBrowser"))
)
I've compared my code to the sample project from Kendo for the EditorFor (which will browse the folder) but can find no discernible differences... I also cannot find much in the way of other people who are having this problem so i suspect there is a setting that i cannot find that is causing my issue, any help would be GREATLY appreicated
my image browser (taken directly from the demo)
public class JFAImageBrowserController : EditorImageBrowserController
{
private const string contentFolderRoot = "~/Content/images";
public override string ContentPath
{
get
{
return contentFolderRoot;
}
}
additionally, using Fiddler the click event for the "Insert Image" button is
GET /JFA/JFAImageBrowser/Read?path=%2F HTTP/1.1
where as the demo is
POST /ImageBrowser/Read HTTP/1.1
I don't know why the demo is using a POST where as mine is using a GET, unless this is because of the overridden image browswer
That code looks fine. Can you make sure your JFAImageBrowser controller looks something like this?
public class BlogImagesController : EditorImageBrowserController
{
//
// GET: /BlogImage/
public ActionResult Index()
{
return View();
}
public override string ContentPath
{
get { return AssetFilePaths.BlogContentPath; }
}
}
It's important that it inherits from EditorImageBrowserController
Also, a 403 may mean that the user doesn't have permission to access the directory. Check the permissions for the user you're running as.
It turns out my problem was in the _Layout page. I was using bundling and either
A) I made some error when setting up the bundling
-or-
b) the bundling didn't work as expected/intended.
either way i added the individual script/java script references and it works as expected.
Here is the solution to this problem
the page this issue fixed was it kendo forum
http://www.telerik.com/forums/implementing-image-browser-for-editor
and the direct link for the demo
http://www.telerik.com/clientsfiles/e3e38f54-7bb7-4bec-b637-7c30c7841dd1_KendoEditorImageBrowser.zip?sfvrsn=0
and if this demo didn't work you can see this sample i made from above
https://www.mediafire.com/?9hy728ht4cnevxt
you can browse the editor through HomeController and the action name is homepage (home/homepage)
& I think that the error was in different uses of paths between the base controller & child controller you make.