Corprio.AspNetCore.Site
2.0.27
See the version list below for details.
dotnet add package Corprio.AspNetCore.Site --version 2.0.27
NuGet\Install-Package Corprio.AspNetCore.Site -Version 2.0.27
<PackageReference Include="Corprio.AspNetCore.Site" Version="2.0.27" />
paket add Corprio.AspNetCore.Site --version 2.0.27
#r "nuget: Corprio.AspNetCore.Site, 2.0.27"
// Install Corprio.AspNetCore.Site as a Cake Addin #addin nuget:?package=Corprio.AspNetCore.Site&version=2.0.27 // Install Corprio.AspNetCore.Site as a Cake Tool #tool nuget:?package=Corprio.AspNetCore.Site&version=2.0.27
About the package @corprio/aspnetcore-site
https://www.npmjs.com/package/@corprio/aspnetcore-site
This package is created to share javascripts, css, and images for Corprio built-in web applications.
Its main script is corprio.js
, which is a module that provides useful functions such as
getting the current organizationID, configuring DevExtreme widgets, etc.
This npm package outputs everything inside the dist folder in the
root of the project Corprio.AspNetCore.Site
, as configured in the package.json.
"files": [ "dist" ]
As you can see, the dist folder contains three folders:
dist/css
This folder contains commonly used css files for Corprio apps.
The css files are distributed from the css
folder by the bundleconfig.json.
Basically, each css file is copied over along with its minified version.
Below are brief descriptions of each file or folder in dist/css
corprio.css
Styles used by corprio.js
corprio-app.css
Styles used by corprio apps with the common layout navbar, sidebar. This is used by partials found in the Views/Shared
Customized theme for devextreme
A customized theme for devextreme, made using https://devexpress.github.io/ThemeBuilder/. Devextreme Metadata can be found in dx.material.corprio-scheme.json This, along with override-dx-scheme.css which are additional styles to override the customized theme, are then bundled to output this file.
After upgrading devextreme, need to run the ThemeBuilder to export the updated css file. Open a node.js command prompt and execute
npx devexpress-dashboard-cli@23.2.5 build-theme --input-file dx.material.corprio-scheme.json
and then copy the files
- dx.material.corprio-scheme.css
- dx-analytics.material.corprio-scheme.css
- dx-dashboard.material.corprio-scheme.css to the css folder.
Note: In the above command replace 23.2.5 with the latest version number of devextreme.
localizedFonts
This folder contains css files to set the right fonts for the page's language.
Below is an example of what TC.css might look like.
body{
font-family: 'Noto Sans', 'Noto Sans TC', Helvetica,Arial,sans-serif;
}
Depending on the thread's current culture, a different css file will be served.
C# helper functions can be found in LanguageHelper
so that apps can use it in the _Layout
, like so.
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="@LanguageHelper.GoogleFontCss()" rel="stylesheet">
<link rel="stylesheet" href="~/@("@")corprio/aspnetcore-site/@LanguageHelper.SetFontCss()" />
To use LanguageHelper
,
make sure the Nuget package for Corprio.AspNetCore.Site
is included.
icons
The files in this folder are required by devextreme icons
fonts
The font files in this folder are used as fallback fonts for dx.material.corprio-scheme.css
dist/images
This folder contains the Corprio logo and icon images of Corprio apps. These images are used in the home page of Corprio apps within a css animation. The animation features Corprio as a suite of apps with the apps orbiting around it. The animation code is a partial _OrbitingApps.cshtml
Note that in the future this is not the best way to share resources as part of it is from the npm package, and part of it is from the Nuget package. Hosting the images from one source might be an alternative to look into.
dist/js
The main script in this folder is the corprio.js or alternatively the corprio.bundle.js. This script contains all the javascript helper functions that are commonly useful in our Corprio apps.
Everything in the dist/js
folder is generated from the ts folder by tasks
written in the gulpfile.js. Gulp is used to pipeline the transpiling and bundling
of the client-side resources for distribution. For more information: https://gulpjs.com/
To understand the output in the dist/js
, I will first explain the contents in the ts
folder,
then go on to describe the gulp tasks. Lastly, we will take a look at how to use corprio.js
from this package.
ts folder
This folder contains typescript modules and declarations that will be transpiled into javascript for distribution.
corprio.ts
This is the main script that will transpile into corprio.js
.
It is written as an ES6 module and aggregates by exporting from all modules.
Note that most exports are written as
export * as moduleName from './modules/moduleName.js'
so that calls can be made by corprio.moduleName.moduleFunction()
. However due
to legacy reasons of how the corprio module used to be structured,
some exports are written as
export { moduleFunction } from './modules/moduleName.js'
to expose the function in corprio.moduleFunction()
Another note about the file name extension when importing and exporting.
Note that it is exported from moduleName.js
and not moduleName.ts
.
The reason is that ultimately, the typescript files will be transpiled into javascript files,
and in browsers, that extension is necessary for them to correctly request for the resources.
Typescript will not remap any .ts
imports into .js
for you since it breaks their
principles according to this thread https://github.com/microsoft/TypeScript/issues/16577#issuecomment-754941937
We are not going to implement features, even under a commandline flag, that imply changing JS semantics by rewriting it during emit
modules
This folder contains typescript ES6 modules that will be aggregated by corprio.ts
.
extensions
Scripts in this folder aims to add extension methods to existing javascript prototypes. Because the script nature is not a module (no import or export keywords in file), when using the extension, import it like so
import '../extensions/date.extensions.js'
dynamicImports
Modules in this folder aims to export another module that has been imported dynamically. That other module may be a third-party module that is large in size, but not used often, and therefore you wish to only import it when needed.
To learn more about dynamic imports: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import
In the example below, the exported function retrieve
will return a promise,
which will resolve to whatever the module exceljs
provides.
exceljs.ts
function resolve() {
return import('exceljs')
.then((ExcelJS) => {
return ExcelJS;
})
}
export { resolve }
It can then be used in another file like this:
import * as exceljs from '../dynamicImports/exceljs.js'
exceljs.retrieve().then((ExcelJS) => {
//do something with ExcelJS
});
The reason for separating each dynamic import into another ES module is that it allows for treeshaking by webpack later on. Webpack treeshaking only works for ES modules currently. Therefore if we do not separate the dynamic import, that module will also be included even if it never had been used.
messages
This folder contains modules that load globalized messages used in corprio.js
.
dxMessages
This folder contains modules that load globalized messages used by Devextreme widgets.
loadMessages
This folder contains modules that will load globalized messages in a certain culture
for both corprio.js
and Devextreme widgets. For example, in a page that is going to be
served in simplified Chinese, and uses corprio.js
or Devextreme widgets, you may
include the script in the head.
<script type="module" src="path/to/loadMessages.zh.js" ></script>
Note that type="module"
must be included since the script has import
statements,
which makes it a module.
To make it easier to use with the C# projects, use the LanguageHelper
from the
Nuget package for this project Corprio.AspNetCore.Site
<script type="module" src="~/node_modules/@("@")corprio/aspnetcore-site/@LanguageHelper.LoadMessagesJs()" ></script>
coWidgets
These scripts provide UI widgets such as the image uploader that we use in corprio.
They operate kind of like Devextreme's UI widgets. One thing that is different is
that even if you include the corprio.js
script, you cannot directly use the
coWidgets accessing under jQuery $('#id').coImageUploader(...)
.
That is because corprio.js
has no side-effects. It only exports a bunch of functions,
but doesn't run anything besides that. This is so that corprio.js
can be safely
tree-shaken.
So before you use any coWidgets, first initialize them by
corprio.coWidgets.useCoWidgets();
Or if you are only the coImageUploader
corprio.coWidgets.useCoImageUploader();
After that you can use the coWidgets by attaching them to an Html element
$('#id').coImageUploader({ optionName1: optionValue1, optionName2: optionValue2 })
Then access the instance like so
$('#id').coImageUploader('instance')
declarations
This folder contains type declaration files, which are files ending in .d.ts
.
These are not modules and do not transpile into javascript. They only exist in the typescript
world. The purpose of these files is to define the shape of certain modules or objects,
and declare them to be existent.
We must also tell typescript which type declaration files to include in our tsconfig.json
.
{
"compilerOptions": {
"types": [ "jquery", "file-saver", "bootstrap", "node" ]
},
"include": [
"ts/**/*"
]
}
Here we told them to include types
for "jquery", "file-saver", "bootstrap", "node", which
comes from node_modules/@types
by default. And they types are there because we have included
them in the package.json
. Then, in the include
config, we told typescript we want
everything in the ts
folder to be included in the project, so they will transpile, type-check,
work with everything in there. The ts
folder includes ts/declarations
which is why
the declarations will be automatically included.
devextreme
The modules for corprio.js
use a lot of devextreme library but it never imported the code
for it anywhere. It is just assumed that whoever is using corprio.js
will also have
included the scripts for devextreme elsewhere. This is fine since javascript doesn't care
to type-check, but for typescript, it needs to know that devextreme library has somehow
been included in order to type-check in your editor. That's what
dx.all.d.ts does to declare devextreme types
to exist. The rest of the files in this folder are also used by devextreme as its
dependencies.
The origin of these files are from the folder where Devextreme is installed, in the Lib folder. They are simply copied over into this project.
schema
Files in the folder aims to define the shape of objects used in Corprio, namely the shape of objects pertaining to Corprio API, and the shape of StaticData.
Corprio API
The Corprio API consists of request paths, request methods, data it takes, and data it returns. All of these have a predefined shape, as stated in our swagger documentation. We can make use of these shapes with typescript to make ajax calls a lot easier.
The schema.d.ts file declares the shape of Corprio
API so we can use the typings in our scripts. This file is generated from the
swagger.json which has been manually downloaded
from https://api.corprio.com/swagger/v1/swagger.json. Currently, the entire process
is manual, from downloading the json
file to running a command that generates the
d.ts
file. Instructions on how to generate the file are detailed in the
generate-schema.txt.
Now we can access the types by importing them.
import type { models, paths } from "@corprio/aspnetcore-site/dist/js/corprio"
//get intellisense for the data model SalesOrderLine
var salesOrderLine: models['SalesOrderLine'];
//get intellisense for the requestBody for creating a product by ajax
var productData: paths['/v1/Product/{organizationID}']['post']['requestBody']['content']['application/json']
models
and paths
are exported from corprio.js
which makes the typings available.
The models.d.ts simply re-exports the data model types
under another alias.
StaticData
In corprio.js
there are often references to the object StaticData
but this
variable has not been imported or defined anywhere in the module.
That's why we have defined the shape and declared it in staticData.d.ts
so typescript will know it exists.
But what does it do, and where does it come from?
StaticData
contains "static" data of the geographic world such as country list,
currency list, phone number formats, etc. However, if the object was truly static,
there should be a module or json file to define this object, and thus
we can simply import it and there won't be the need to declare it.
So why is it declared? Because it isn't really static, despite the misleading name.
One reason is that the country list contains globalized names of the country,
and so the object must be generated run-time depending on the thread's culture.
In fact, it is generated on server-side based on data models defined in the
Corprio.Global
project, so as to keep the the server-side and client-side
static data in sync.
But aside from that, the main reason is that StaticData
also serves data
about the current organization being requested and provides it
under StaticData.OrgInfo
. And that's not static at all, and therefore must be
generated server-side per request. That's being done by
StaticDataViewComponent, which is a
view component that generates and inserts the following
<script type="text/javascript">
var StaticData = ...
</script>
into the view, if the view file contains the view component
<vc:static-data model="@StaticDataRequestViewModel.All(true)" />
Now that we know where the actual StaticData
object comes from, how is the
staticData.d.ts
able to know its shape? It doesn't. I generated it manually with
the npm package dts-generator.
I copied the contents of StaticData
at run-time then pasted
it into the command to generate the .d.ts
file.
corprio
Files in this folder aims to declare global variables for corprio.js
.
That includes two things: global variables referenced by corprio.js
that we want
typescript to know about, and the very corprio
module itself, if we want it
to be recognized globally.
globalVariables.d.ts
This file declares variables to exist globally in the Window
scope, that for one reason
or another exists by some other way. This includes StaticData
mentioned earlier.
It also includes some other variables that are here for legacy reasons. It is not a good
practice, since there will be no way to ensure those dependencies actually exist at
run-time. For future, please aim to have all dependencies imported by ES module syntax.
corprio.d.ts
This file declares corprio
to exist and defines its shape for corprio.js
.
Note: this is also here for legacy reasons. In the past, corprio.bundle.js
used to be written as an immediately-invoked factory function that we set to a
var corprio
. This corprio.bundle.js
file is then included in the _Layout
,
and then we use it in our scripts everywhere else, assuming the corprio
variable
to exist, and getting zero intellisense for it.
Now it is rewritten to be ES modules. When using it from other apps, we can simply import the module into our script.
import * as corprio from "@corprio/aspnetcore-site/dist/js/corprio"
This not only ensures that corprio
exists in the context, but also
allows for treeshaking with webpack later on. When using it this way, there is no need for the
corprio.d.ts
file to declare it.
However, because of our generous usage of referencing corprio
everywhere in the past,
it will be difficult to remove the corprio.bundle.js
script from _Layout
because something
is probably going to die without it. And since it is still globally included,
this file corprio.d.ts
exists to declare it, so that you get intellisense in your
typescript files.
coWidgets.d.ts
This is the declaration file for corprio UI widget components, to make typescript intellisense available when using coWidgets as jQuery extension methods.
gulpfile.js
Now that we understand all the contents in the ts
folder, we can take a look at how
these contents are transformed to be the output in the dist/js
folder. The transformation
happens through gulp and the gulpfile.js
contains code that controls how it happens.
In gulp, each process is organized into tasks. They look like functions and always returns something. When exported, the tasks will be visible through Visual Studio's Task Runner Explorer found under View > Other Windows > Task Runner Explorer.
Open it now and have a look. You should see on the left panel a list of tasks defined in the Gulpfile.js
.
And on the right panel, any tabs showing currently running tasks and a Bindings tab that shows
any bindings of which task would automatically run on certain events. If you right-click on a task
in the left panel, you can run the task or bind it to an event.
Let's go over what each task does.
cleanDistJs
Deletes the entire directory
dist/js
processTs
Processes the typescripts and outputs them into
dist/js
refreshDistJs
Runs
cleanDistJs
and thenprocessTs
watchTs
Watches for changes in the
ts
folder and processes them automatically
Some tasks may have the suffix DEVELOPMENT
or PRODUCTION
.
The PRODUCTION
tasks will generate both minified and non-minified versions of corprio.bundle.js
.
The DEVELOPMENT
tasks only generate non-minified scripts. That means when you are developing,
and want to quickly generate output to test, use the dev tasks. Otherwise use the pro tasks.
Remember to run the refreshDistJs_PRODUCTION
task before publishing the npm package
so you have to latest code transpiled.
You most likely want to know what processTs
does. Here's a breakdown:
Transpile all typescript ES modules in
ts
folder and outputs the javascript ES modules into thedist/js
folder, keeping the same folder structure. This will also generate.d.ts
files for each module. Then, watch for changes in modules to re-transpile.Copies everything from
ts/declarations
directly intodist/js/declarations
without alteration. Then, watch for changes ints/declarations
to re-copy.Bundles all the modules in the
ts
folder into one large module namedcorprio.bundle.js
This module is a UMD module, meaning if this script is included in a page, thencorprio
and its functions will be available globally for access. This is for backwards-compatibility and ease of use. Otherwise, it is better to usecorprio.js
, which is the ES module version.Note: Besides
corprio.bundle.js
you may also notice files like295.corprio.bundle.js
. These files are a result of dynamic imports. At first295.corprio.bundle.js
won't be loaded until it is needed. For instance, our corprio module has a function that makes use of the third-party moduleexceljs
. We don't want to pack it with our bundle because it is large. Wepback is smart and separates these dynamic imports into separate modules.
For further details on how each gulp task works, read the comments in the gulpfile.js
.
Some things to note:
Our gulp tasks use third-party npm modules as you can see in the
require
statements. These must be included in the package.jsondevDependencies
.Our gulp tasks depends on configurations in
tsconfig.json
to properly transpile and generate declaration files.{ "compilerOptions": { "forceConsistentCasingInFileNames": true, //to keep file paths consistent. Without this tasks will throw error "noImplicitAny": false, //Currently false because we have yet to add types to all our modules "noEmitOnError": true, "declaration": true, //keep true so that webpack can use it to generate declaration files "removeComments": false, "sourceMap": true, //for debugging purposes "target": "es6", //target es6 so that the output can be used by other modules for treeshaking "module": "esnext", //esnext so that we can use dynamic imports "moduleResolution": "nodenext", "outDir": "", //the correct output path is further configured in the gulpfile.js "types": [ "jquery", "file-saver", "bootstrap", "node" ] //include these types from node_module/@types }, "include": [ "ts/**/*" //include these files for compilation ] } ```
Usage of the corprio module
Let's look at how you may use corprio
module in another project.
There are two ways: corprio.js
and corprio.bundle.js
corprio.js
is an ES module, and you may use it by importing them into your scripts.
This is the preferred way to use it, since ES modules are tree-shakable.
Alternatively you may use corprio.bundle.js
in your project.
This may be the case if you want include it once and be able to use it globally everywhere.
The downside is that corprio.bundle.js
is a UMD module which is not tree-shakable.
Also, dependencies are not as clear as if you use ES modules. Generally it is not the best
idea to inject variables into your javascript global scope.
corprio.bundle.min.js
is just the minified version of corprio.bundle.js
. Use the minified
version for production. Use the non-minified version for development, so that you have the
site-maps and variable names kept in tact to make debugging much easier.
Usage of corprio.js
1. Install @corprio/aspnetcore-site
First, make sure you have this package installed.
npm i @corprio/aspnetcore-site
2. Include the type definitions in your tsconfig.json
If you're using typescript, include type definitions for corprio.js
{
"compilerOptions": {
"types": ["jquery", "file-saver", "bootstrap", "node"]
},
"include": [
"node_modules/@corprio/aspnetcore-site/dist/js/**/*"
],
"exclude": [
//corprio.d.ts is excluded if you are using corprio.js by ES module import syntax
"node_modules/@corprio/aspnetcore-site/dist/js/declarations/corprio/corprio.d.ts"
]
}
3. Import corprio.js in your script
In your script file, import the module and use.
In myScript.js:
import * as corprio from "@corprio/aspnetcore-site/dist/js/corprio"
//use its functions
var orgID = corprio.getCurrentOrgID();
Make sure that when you're including the script in your html, to write type = "module"
unless you will further process your script.
<script type="module" src="path/to/myScript.js" ></script>
4. Treeshake your script with webpack (optional)
Since you are probably not using every function imported from corprio, it is a good idea to treeshake your scripts so that only what is used is being outputted.
More details in https://webpack.js.org/guides/tree-shaking/
Usage of corprio.bundle.js
1. Install @corprio/aspnetcore-site
First, make sure you have this package installed.
npm i @corprio/aspnetcore-site
2. Include the type definitions in your tsconfig.json
If you're using typescript, include type definitions for corprio.bundle.js
{
"compilerOptions": {
"types": ["jquery"]
},
"include": [
"node_modules/@corprio/aspnetcore-site/dist/js/**/*"
]
}
3. Include the corprio.bundle.js in html
In your html file, include the script
<script src="@corprio/aspnetcore-site/dist/js/corprio.bundle.js"></script>
Or if it's an cshtml file such as your _Layout
, you'll have to escape the '@' character
<script src="~/@@corprio/aspnetcore-site/dist/js/corprio.bundle.js"></script>
4. Use in your scripts
You may then call functions from corprio
in the same page, since it is already
available in the global scope.
Product Tour
Follow the steps below to add Product Tour feature in an application.
- Add a service class which implements IProductTourService in the application
- Register the service class in ConfigureServices of the Startup class. For example
services.AddProductTour<ProductTourService>();
- On all views which need the product tour function, run the script in the inside onload
corprio.page.initTour({ defaultTour: 'name of the tour', autoStart: true });
Recommend to name the tour using the syntax [application].[controller].[index] to avoid conflicts between different applications. This is because the name is saved in cookies after the tour is loaded so that it will not run again automatically next time.
Notes:
- Standard tour steps have been defined in the ProductTour class which can be shared by applications which use the standard layouts.
- The library driver.js hard coded the font family in its CSS. This makes the icons of devextreme and fontawesome cannot be shown. To resolve this, add special class when using icons in the tour content.
For fontawesome, add the class fontawesome, e.g.
<i class="fontawesome fa-solid fa-arrow-up-right-from-square"></i>
For icons in devextreme, add the class dxicons, e.g.<i class='dxicons dx-icon-edit'></i>
How to deploy
Windows
To deploy your application which is based on Corprio.AspNetCore.Site or Corprio.AspNetCore.XtraReportSite, follows the stesp below.
- Install the ASP.NET Core 8.0 runtime - Windows Hosting Bundle Installer. Url: https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-aspnetcore-8.0.1-windows-hosting-bundle-installer
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net8.0
- BuildBundlerMinifier (>= 3.2.449)
- Corprio.AspNetCore (>= 2.0.27)
- Corprio.CorprioAPIClient (>= 2.0.27)
- Corprio.DevExpressLib (>= 2.0.27)
- Corprio.DevExtremeLib (>= 2.0.27)
- Microsoft.AspNetCore.Mvc.NewtonsoftJson (>= 8.0.1)
- Microsoft.Extensions.Http.Polly (>= 8.0.1)
- System.Resources.Extensions (>= 8.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Corprio.AspNetCore.Site:
Package | Downloads |
---|---|
Corprio.AspNetCore.XtraReportSite
Extended suppport on Corprio.AspNetCore.Site for using DevExpress XtraReports in ASP.NET Core web applications |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
2.0.30 | 33 | 11/14/2024 |
2.0.29.55 | 138 | 9/23/2024 |
2.0.29.54 | 126 | 9/19/2024 |
2.0.29.38 | 131 | 9/9/2024 |
2.0.29 | 94 | 8/6/2024 |
2.0.28.1 | 100 | 8/5/2024 |
2.0.28 | 103 | 8/1/2024 |
2.0.27 | 81 | 7/31/2024 |
2.0.26.1 | 117 | 7/26/2024 |
2.0.26 | 109 | 7/26/2024 |
2.0.25.4 | 129 | 7/18/2024 |
2.0.25.3 | 107 | 7/18/2024 |
2.0.25.2 | 95 | 7/17/2024 |
2.0.25.1 | 97 | 7/17/2024 |
2.0.25 | 116 | 7/16/2024 |
2.0.24.33 | 157 | 6/24/2024 |
2.0.24.32 | 124 | 6/3/2024 |
2.0.24.31 | 148 | 5/27/2024 |
2.0.24.28 | 116 | 5/18/2024 |
2.0.24.27 | 127 | 5/17/2024 |
2.0.24.24 | 140 | 5/14/2024 |
2.0.24.7 | 158 | 5/9/2024 |
2.0.24.6 | 159 | 5/9/2024 |
2.0.24.1 | 115 | 5/3/2024 |
2.0.24 | 123 | 5/2/2024 |
2.0.23.1 | 150 | 4/26/2024 |
2.0.23 | 121 | 4/26/2024 |
2.0.22.5 | 121 | 4/26/2024 |
2.0.22.3 | 136 | 4/26/2024 |
2.0.22.2 | 163 | 4/22/2024 |
2.0.22.1 | 141 | 4/19/2024 |
2.0.22 | 142 | 4/19/2024 |
2.0.21 | 151 | 4/16/2024 |
2.0.20.2 | 160 | 4/15/2024 |
2.0.20.1 | 156 | 4/14/2024 |
2.0.20 | 133 | 4/14/2024 |
2.0.19.2 | 147 | 4/12/2024 |
2.0.19 | 144 | 4/11/2024 |
2.0.18 | 156 | 4/5/2024 |
2.0.17 | 176 | 3/28/2024 |
2.0.16.4 | 194 | 3/27/2024 |
2.0.16.3 | 147 | 3/27/2024 |
2.0.16 | 158 | 3/27/2024 |
2.0.15.11 | 156 | 3/27/2024 |
2.0.15.10 | 140 | 3/27/2024 |
2.0.15.4 | 139 | 3/25/2024 |
2.0.15.3 | 123 | 3/22/2024 |
2.0.15 | 142 | 3/20/2024 |
2.0.14.18 | 164 | 3/15/2024 |
2.0.14.17 | 171 | 3/11/2024 |
2.0.14.13 | 127 | 3/11/2024 |
2.0.14.10 | 163 | 3/7/2024 |
2.0.14.8 | 168 | 3/6/2024 |
2.0.14.6 | 167 | 3/4/2024 |
2.0.14.4 | 152 | 3/1/2024 |
2.0.14.3 | 156 | 3/1/2024 |
2.0.14.2 | 166 | 3/1/2024 |
2.0.14 | 162 | 3/1/2024 |
2.0.13.8 | 151 | 3/1/2024 |
2.0.13.7 | 152 | 2/27/2024 |
2.0.13.6 | 132 | 2/27/2024 |
2.0.13 | 131 | 2/26/2024 |
2.0.12.5 | 163 | 2/22/2024 |
2.0.12.4 | 155 | 2/22/2024 |
2.0.12.2 | 156 | 2/22/2024 |
2.0.12 | 147 | 2/21/2024 |
2.0.11.8 | 171 | 2/19/2024 |
2.0.11 | 124 | 2/18/2024 |
2.0.10.2 | 139 | 2/16/2024 |
2.0.10.1 | 133 | 2/16/2024 |
2.0.9 | 172 | 2/16/2024 |
2.0.8 | 176 | 2/15/2024 |
2.0.7 | 141 | 1/30/2024 |
2.0.6.1 | 112 | 1/30/2024 |
2.0.6 | 120 | 1/30/2024 |
2.0.5 | 110 | 1/30/2024 |
2.0.1 | 134 | 1/19/2024 |
1.2.0 | 122 | 1/18/2024 |
1.1.60.1 | 132 | 1/19/2024 |
1.1.60 | 138 | 1/17/2024 |
1.1.59.14 | 124 | 1/17/2024 |
1.1.59.6 | 142 | 1/15/2024 |
1.1.59.3 | 142 | 1/12/2024 |
1.1.59 | 132 | 1/12/2024 |
1.1.58 | 167 | 1/4/2024 |
1.1.57 | 179 | 12/20/2023 |
1.1.56 | 165 | 12/18/2023 |
1.1.55 | 154 | 12/15/2023 |
1.1.54.5 | 161 | 12/14/2023 |
1.1.54.3 | 155 | 12/12/2023 |
1.1.54 | 134 | 12/12/2023 |
1.1.53.16 | 168 | 12/5/2023 |
1.1.53.11 | 168 | 11/29/2023 |
1.1.53.6 | 173 | 11/25/2023 |
1.1.53 | 191 | 11/17/2023 |
1.1.52.22 | 166 | 11/17/2023 |
1.1.52.11 | 162 | 11/14/2023 |
1.1.52.9 | 140 | 11/14/2023 |
1.1.52.5 | 162 | 11/14/2023 |
1.1.52.3 | 168 | 11/10/2023 |
1.1.52 | 150 | 11/6/2023 |
1.1.51 | 148 | 11/2/2023 |
1.1.50.9 | 143 | 10/30/2023 |
1.1.50.8 | 162 | 10/27/2023 |
1.1.50.7 | 151 | 10/27/2023 |
1.1.50.6 | 163 | 10/27/2023 |
1.1.50 | 167 | 10/25/2023 |
1.1.49 | 176 | 10/19/2023 |
1.1.48.3 | 155 | 10/19/2023 |
1.1.48 | 193 | 10/18/2023 |
1.1.47.6 | 170 | 10/18/2023 |
1.1.47.5 | 179 | 10/17/2023 |
1.1.47.2 | 147 | 10/17/2023 |
1.1.47.1 | 151 | 10/17/2023 |
1.1.47 | 168 | 10/17/2023 |
1.1.45.6 | 191 | 10/16/2023 |
1.1.45 | 170 | 10/13/2023 |
1.1.44.11 | 174 | 10/12/2023 |
1.1.44.10 | 171 | 10/12/2023 |
1.1.44 | 184 | 10/11/2023 |
1.1.43.1 | 187 | 10/11/2023 |
1.1.43 | 184 | 10/6/2023 |
1.1.42.12 | 175 | 10/6/2023 |
1.1.42.11 | 187 | 9/28/2023 |
1.1.42.10 | 175 | 9/21/2023 |
1.1.42.2 | 167 | 9/19/2023 |
1.1.42.1 | 149 | 9/19/2023 |
1.1.42 | 157 | 9/17/2023 |
1.1.41.1 | 163 | 9/15/2023 |
1.1.41 | 165 | 9/13/2023 |
1.1.40 | 174 | 9/7/2023 |
1.1.39.1 | 204 | 8/25/2023 |
1.1.39 | 214 | 8/18/2023 |
1.1.38 | 217 | 8/11/2023 |
1.1.37.1 | 219 | 7/26/2023 |
1.1.37 | 225 | 7/22/2023 |
1.1.36.1 | 212 | 7/20/2023 |
1.1.36 | 212 | 7/19/2023 |
1.1.35 | 205 | 7/19/2023 |
1.1.34.6 | 247 | 7/7/2023 |
1.1.34.5 | 213 | 7/7/2023 |
1.1.34.4 | 244 | 7/4/2023 |
1.1.34 | 242 | 7/3/2023 |
1.1.33.45 | 244 | 7/3/2023 |
1.1.33.42 | 253 | 6/12/2023 |
1.1.33.41 | 194 | 6/5/2023 |
1.1.33.26 | 280 | 4/11/2023 |
1.1.33.25 | 253 | 4/11/2023 |
1.1.33.20 | 272 | 4/4/2023 |
1.1.33.19 | 281 | 4/3/2023 |
1.1.33.15 | 265 | 3/31/2023 |
1.1.33.14 | 278 | 3/31/2023 |
1.1.33.11 | 308 | 3/29/2023 |