Closed fasteddys closed 2 years ago
for e.g. in the last .net dev meetup many mentioned
Source?
Can you create a core component, with a graph and table to show number of failed attempts...
Yes you can
It's been triaged for documentation. Keep it open.
I believe @sebastienros works with graphs all day long for its daytime job for analyzing ASP.NET Core performance. I can't remember which library exactly he's using but I believe that everything is possible in Orchard Core. If you want to create widgets in the Dashboard then it's a matter of creating one that will use one of these javascript graphs libraries to display data that comes from the database. As for a single tutorial to do this, I think there are many ways to develop things in Orchard Core. Here, you seem to want something that would be manageable from the admin UI which would use prepared datasets (Queries module). So, you would need some guidance on steps to build something like this which is something we generally don't do here unless this is a feature that might be added in the source code for everyone. I would see this more as an external contrib module because it is really specific.
Here, if we would need to report statistics for an ECommerce module we would probably implement this in the OrchardCore.Commerce module as a OrchardCore.Commerce contrib module that adds widgets for the admin UI dashboard.
I believe that Widgets shapes can be added from the Admin UI by using the "Templates" feature. Though, when it comes to consume a javascript library I generally build an entire module that builds these Widgets. Else, it is also totally doable from the admin UI if you don't need to create handlers and drivers for your custom shapes.
Here, a graph generally needs some specific data and caching over that data because else it can be quite demanding when building complex SQL Queries. So, first, this is about understanding how YesSQL works for building these SQL queries from a managed context. Then, you need to know how to build also database tables with relationships through YesSQL if you want to have one to many, many to many relationships ... Here, I can't say more because I would need to start looking at a simple example of what you need to achieve and from which javascript library. Else, as for the data itself, I think it is about learning to build things with YesSQL / Dapper.
So here, I'm assuming when you say "master -> detail table" you mean one to many relationship in a database. And, the confusion is that most of our documentation is about how to use the map/reduce design pattern with YesSQL.
Here is a SQL diagram that shows a many-to-many relationship.
If we start from a Migrations.cs file in a module to create these tables we can do something like this :
using System;
using OrchardCore.ContentManagement.Metadata;
using OrchardCore.ContentManagement.Metadata.Settings;
using OrchardCore.Data.Migration;
using YesSql.Sql;
namespace YourNamespace
{
public class Migrations : DataMigration
{
public int Create()
{
// We create the 3 tables first
SchemaBuilder.CreateTable(nameof(Employee), table => table
.Column<int>(nameof(Employee.EmployeeID), col => col.PrimaryKey().Identity())
.Column<string>(nameof(IndexingTask.FirstName), c => c.WithLength(50))
.Column<string>(nameof(IndexingTask.LastName), col => c.WithLength(50))
);
// This is the "middle" table that stores the many to many references
SchemaBuilder.CreateTable(nameof(EmployeeSkill), table => table
.Column<int>(nameof(Employee.EmployeeID))
.Column<int>(nameof(SkillDescription.SkillID))
);
SchemaBuilder.CreateTable(nameof(SkillDescription), table => table
.Column<int>(nameof(SkillDescription.SkillID), col => col.PrimaryKey().Identity())
.Column<string>(nameof(SkillDescription.Description), c => c.WithLength(30))
);
// We create the foreign keys that will create the many to many relationship
SchemaBuilder.CreateForeignKey(
"fk_" + nameof(Employee) + "_" + nameof(SkillDescription), // foreign key name
nameof(Employee), // source table name
new string [] { "EmployeeId" }, // source table columns to include in the FK
nameof(EmployeeSkill), // destination table name
new string [] { "EmployeeId" } // destination table name columns to include in the FK
);
SchemaBuilder.CreateForeignKey(
"fk_" + nameof(EmployeeSkill) + "_" + nameof(SkillDescription), // foreign key name
nameof(EmployeeSkill), // source table name
new string [] { "SkillID" }, // source table columns to include in the FK
nameof(SkillDescription), // destination table name
new string [] { "SkillID" } // destination table name columns to include in the FK
);
return 1;
}
}
}
Consider this as a draft as I didn't try this code yet.
Question is now : how do we use this in the context of YesSQL. We can't use these type of queries. I need to read.
_session.Query<ContentItem, ContentItemIndex();
I'm thinking that I'm maybe making a mistake there where I could use SchemaBuilder.CreateMapIndexTable for the EmployeeSkill and SkillDescription tables.
Documentation it is ...
@Skrypt thanks for the guidance here... exactly what we were looking for... first its not always admins looking at dashboards. If you look at Kendo/SiteCore/ABP etc. they have business user facing dashboards
in the apps. This is a very common scenario besides dataTables
or Master-Detail Forms
to view LOB transactional data.
"...I believe that Widgets shapes can be added from the Admin UI by using the "Templates" feature. Though, when it comes to consume a javascript library I generally build an entire module that builds these Widgets. Else, it is also totally doable from the admin UI if you don't need to create handlers and drivers for your custom shapes..." (Awesome advice) 👍
I also see how your migration builder is adding the schema (similar to EF), which has helped us. 👍
Use case
Since we already had another app with dashboards and charts, where we already had a simple ViewComponent
(previously Partials) tried to easily convert/port over that code and failed.. because of the internals on how to wire it up.
Scaffolder: We tried to scaffold a new module and port over the code - we were unable to follow how to achieve this even from the documentation (I have not see the latest), but if it could have some pictures describing the layers/shapes imagine a lasagna or a stack to visually depict what goes where and the sequence of steps or even a sample that would help.
I think I would start by analyzing the OrchardCore.Demo module
https://github.com/OrchardCMS/OrchardCore/tree/main/src/OrchardCore.Modules/OrchardCore.Demo
And then I think you need to learn the differences between "Content Type", "Content Part", "Content Field", Shapes, Drivers, Handlers.
Here, a driver is something similar to a controller but for a shape. And a shape is kind of a dynamic ViewModel but it is also more than just that; it is used also as views templates. You need to think about the fact that Orchard Core uses composition to create its runtime data models and there is some dynamic typing involved because of that. So, we don't use standard controllers for these because of the dynamic nature of shapes. We have handlers too that can be used to morph the data based on specific predefined events in the Orchard Core framework.
I think you need to take a simple module like the OrchardCore.Demo one and try different things. Look at other modules to see how things are done when needing more advanced things. That's the best way to learn. Else, there is the documentation for really specific things but maybe we are missing simple tutorials.
There is also this repository :
https://github.com/OrchardCMS/OrchardCore.Samples
But I think it needs an update.
In terms of graphs and chart I think Lombiq already did a module for Chart Js. @Piedone correct me if I'm wrong
Yes, the Chart.js module. Thanks for pointing out Hisham.
@Piedone I was able to download an build and see the chart component very helpful 👍 missing some steps on making it functional in a module for us.
Usecase: The user selected the widget and wants to connect materials or shift dataset to it, can you please share some info on how are the backend DataSources/Tables exposed/discovered to the widget and how does the Module know about the widget?
For e.g. we have several Tables, and taking these two for e.q:
MaterialsTable
[id, vendor, materialtype (metal/plastic/glass), WeightDropOff, MeltingCompleted, ShiftHours, TotalHours ]
ShiftsTable
[id, ShiftType, DateTimeStarted,DateTimeCompleted, WeightCompleted, NumberOfWorkers, TotalCost ]
ChartView... Manager wants to view in the graph widget
We can render the graph, and we see your datasets definition, but do we configure this so user can pick each of those to view.
Please confirm we are doing right steps:
We made a widget and a module but dont know what to do to connect the two.
codegen module Manfacturing /IncludeInSolution:true
From your ChartJsDataSet
base class we created new dataSets
public class MaterialsTableDataSet : ChartJsDataSet
{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public IEnumerable<string> materialtype { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public IEnumerable<decimal> TotalHours { get; set; }
//... other props
}
public class ShiftsTableDataSet : ChartJsDataSet
{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public IEnumerable<string> ShiftType { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public IEnumerable<decimal> TotalCost { get; set; }
//... other props
}
EDIT: We have a sample project now, see here.
Hi @fasteddys ,
The Chart.JS module is focused on the front-end side of things. You have to access data from the DB separately. It sounds like you already have a DB with this data to be displayed, so doing a database-first setup with Entity Framework Core might be the most appropriate.
You shouldn't inherit from ChartJsDataSet
. If you haven't yet, create a separate model you use to get data from your DB table. Then create a view-model for your widget that contains these properties:
public IEnumerable<string>> ChartLabels { get; set; }
public IEnumerable<ChartJsDataSet> ChartDataSets { get; set; }
public object ChartOptions { get; set; }
Your widget's driver should fetch the DB rows, convert them into data series according to your business logic and then initialize the viewmodel that contains the above properties like this:
// Fetch from DB, convert as needed. If you need his to be user customizable, attach that information to
// your widget's content item so it can be accessed by your logic here.
var shifts = ...;
model.ChartLabels = shifts.Select(shift => shift.DateTimeStarted.ToString());
model.ChartDataSets = new List<ChartJsDataSet>
{
new()
{
Label = "Total Cost",
Data = shifts.Select(shift => shift.TotalCost),
},
};
// Options can be PascalCase, but otherwise same as https://www.chartjs.org/docs/2.9.4/configuration/#global-configuration
model.ChartOptions = new
{
Layout = new Layout(50, 10, 10, 10),
};
Finally include in your widget's template:
<chart labels="@viewModel.ChartLabels"
datasets="@viewModel.ChartDataSets"
options="@viewModel.ChartOptions"></chart>
Much love 😄 to your help @DAud-IcI thanks to your help the mud is clearing up some.
Samples: don't show drivers When I study/follow/tried to search for driver inside the chart Widget sample and module sample both were empty https://github.com/Lombiq/Orchard-Chart.js/search?q=driver https://github.com/OrchardCMS/OrchardCore.Samples/search?q=driver
So, from your help, I understand this I should code it up like a regular MVC app, and let user switch between datasets in frontend, and in view switch in JS code, I am assuming when I pass more than one in the model, the driver will make it available to the chartJSWidget
model.ChartDataSets = new List<ChartJsDataSet>
{
new()
{
Label = "Total Cost",
Data = shifts.Select(shift => shift.TotalCost),
},
};
// I added these and planning to let user select and should I change it in the frontend, like a regular MVC view?
model.MaterialsDataSets = new List<ChartJsMaterialsDataSet>
{
new()
{
Label = "Total Time",
Data = Materials.Select(materials=> materials.TotalHours),
},
};
Documentation help section: is confusing it shows drivers inside modules, but the ChartJs is a UI widget?? so are they the same thing, how do they get linked/wired up?? I added a suggestion below...
I was trying to follow this Orchard help so I could build the driver for the widget
Please correct me
Maybe the clue is the content part behind a widget, yes?? public class MyChartDriver : ContentPartDriver<MyChartWidget>
?
While, they have a good effort and nice amount of documentation, a picture to show the architecture & composition would really help clear up the relationships/inheritance/structure and MODULE
<-> Widget
composition/aggregates.
For e.g. a layered or relationship image on how to build up to the widget from a module!
Samples: don't show drivers
Yes, my sample only included the Chart specific parts to keep it simple. Drivers are kind of like controllers for content items, and a widget is just a specialized content item. Check out the "Content Item and Content Part development" section of our training demo (or specifically the driver here) if you've never worked with them before.
Documentation help section:
Disregard that documentation, it's for the legacy "Orchard CMS" (also known as O1). It's an older CMS made for .Net Framework and many concepts don't translate to Orchard Core so it will only get confusing.
So I assumed a Widget is just another independent module/project packaging on how code is organized?
A widget is a content type with a special stereotype value. They can be placed on the layout independently of the current page's content (in Admin Dashboard > Design > Widgets). A module can contain multiple widgets, but you have to define them like any other content type (see the training demo linked above).
Humble Suggestion
I've tried, but I'm not graphic designer.
Which component Strategy for new developers & Students to build metrics based components
There's some confusion in the Developers & students community. they do not know, which path to take to build transactional components/functionality, for e.g. if a developer wants to create a component with a
master-details table
for customer shipping/orders tables Or, GRAPH for e.g. Number ofreturns per product D3 / eCharts Graph
, and a table below with details on selected row-item in the graph... which one / do they use a module, do they use a widget, or content type its very fuzzy on which one to pick??Next, if a developer wants to scaffold Orchard Form, or custom Widgets , module, for e.g. in the last .net dev meetup many mentioned, they don't know how to create a simple pie chart in orchard for e.g. there are several use cases like a customer returns per product.
I posted a help request in the Lombiq CVS2022 extension, and proposed using Extension, they gave up after trying, first because of the compatibility issue, which is being fixed, but also some functionality issue. So, if it has more comments/picture on what the code structure/components its scaffolding, step 1, 2 etc. in comments form then developers would be able to use it to easily create Module or Widget.
They key thing to understand is the flexibility in your scaffolding / visual extension is perhaps a good entry point as a visual tool in VS to help them create the components they want.
If you notice in the admin dashboard there is no single graph there?
Can you create a core component, with a graph and table to show number of failed attempts, IP aaddress (kinda like WordFence or loginizer in WP), this would be a good reference app.