Corprio.AspNetCore.Site 2.0.31

dotnet add package Corprio.AspNetCore.Site --version 2.0.31                
NuGet\Install-Package Corprio.AspNetCore.Site -Version 2.0.31                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Corprio.AspNetCore.Site" Version="2.0.31" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Corprio.AspNetCore.Site --version 2.0.31                
#r "nuget: Corprio.AspNetCore.Site, 2.0.31"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Corprio.AspNetCore.Site as a Cake Addin
#addin nuget:?package=Corprio.AspNetCore.Site&version=2.0.31

// Install Corprio.AspNetCore.Site as a Cake Tool
#tool nuget:?package=Corprio.AspNetCore.Site&version=2.0.31                

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

  1. dx.material.corprio-scheme.css
  2. dx-analytics.material.corprio-scheme.css
  3. 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 then processTs

  • 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:

  1. Transpile all typescript ES modules in ts folder and outputs the javascript ES modules into the dist/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.

  2. Copies everything from ts/declarations directly into dist/js/declarations without alteration. Then, watch for changes in ts/declarations to re-copy.

  3. Bundles all the modules in the ts folder into one large module named corprio.bundle.js This module is a UMD module, meaning if this script is included in a page, then corprio and its functions will be available globally for access. This is for backwards-compatibility and ease of use. Otherwise, it is better to use corprio.js, which is the ES module version.

    Note: Besides corprio.bundle.js you may also notice files like 295.corprio.bundle.js. These files are a result of dynamic imports. At first 295.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 module exceljs. 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.json devDependencies.

  • 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.

  1. Add a service class which implements IProductTourService in the application
  2. Register the service class in ConfigureServices of the Startup class. For example services.AddProductTour<ProductTourService>();
  3. 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:

  1. Standard tour steps have been defined in the ProductTour class which can be shared by applications which use the standard layouts.
  2. 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.

  1. 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.31 115 12/3/2024
2.0.30.1 100 11/29/2024
2.0.30 124 11/14/2024
2.0.29.55 149 9/23/2024
2.0.29.54 137 9/19/2024
2.0.29.38 145 9/9/2024
2.0.29 105 8/6/2024
2.0.28.1 111 8/5/2024
2.0.28 114 8/1/2024
2.0.27 92 7/31/2024
2.0.26.1 128 7/26/2024
2.0.26 120 7/26/2024
2.0.25.4 140 7/18/2024
2.0.25.3 124 7/18/2024
2.0.25.2 109 7/17/2024
2.0.25.1 108 7/17/2024
2.0.25 127 7/16/2024
2.0.24.33 168 6/24/2024
2.0.24.32 140 6/3/2024
2.0.24.31 162 5/27/2024
2.0.24.28 133 5/18/2024
2.0.24.27 138 5/17/2024
2.0.24.24 152 5/14/2024
2.0.24.7 172 5/9/2024
2.0.24.6 171 5/9/2024
2.0.24.1 123 5/3/2024
2.0.24 134 5/2/2024
2.0.23.1 158 4/26/2024
2.0.23 129 4/26/2024
2.0.22.5 134 4/26/2024
2.0.22.3 144 4/26/2024
2.0.22.2 180 4/22/2024
2.0.22.1 152 4/19/2024
2.0.22 153 4/19/2024
2.0.21 167 4/16/2024
2.0.20.2 168 4/15/2024
2.0.20.1 164 4/14/2024
2.0.20 150 4/14/2024
2.0.19.2 159 4/12/2024
2.0.19 157 4/11/2024
2.0.18 167 4/5/2024
2.0.17 184 3/28/2024
2.0.16.4 202 3/27/2024
2.0.16.3 155 3/27/2024
2.0.16 166 3/27/2024
2.0.15.11 164 3/27/2024
2.0.15.10 148 3/27/2024
2.0.15.4 148 3/25/2024
2.0.15.3 133 3/22/2024
2.0.15 153 3/20/2024
2.0.14.18 172 3/15/2024
2.0.14.17 179 3/11/2024
2.0.14.13 138 3/11/2024
2.0.14.10 175 3/7/2024
2.0.14.8 177 3/6/2024
2.0.14.6 174 3/4/2024
2.0.14.4 163 3/1/2024
2.0.14.3 165 3/1/2024
2.0.14.2 181 3/1/2024
2.0.14 175 3/1/2024
2.0.13.8 159 3/1/2024
2.0.13.7 161 2/27/2024
2.0.13.6 144 2/27/2024
2.0.13 139 2/26/2024
2.0.12.5 174 2/22/2024
2.0.12.4 163 2/22/2024
2.0.12.2 163 2/22/2024
2.0.12 160 2/21/2024
2.0.11.8 179 2/19/2024
2.0.11 132 2/18/2024
2.0.10.2 148 2/16/2024
2.0.10.1 141 2/16/2024
2.0.9 180 2/16/2024
2.0.8 184 2/15/2024
2.0.7 148 1/30/2024
2.0.6.1 119 1/30/2024
2.0.6 130 1/30/2024
2.0.5 117 1/30/2024
2.0.1 141 1/19/2024
1.2.0 130 1/18/2024
1.1.60.1 141 1/19/2024
1.1.60 144 1/17/2024
1.1.59.14 131 1/17/2024
1.1.59.6 150 1/15/2024
1.1.59.3 151 1/12/2024
1.1.59 139 1/12/2024
1.1.58 176 1/4/2024
1.1.57 186 12/20/2023
1.1.56 173 12/18/2023
1.1.55 161 12/15/2023
1.1.54.5 168 12/14/2023
1.1.54.3 162 12/12/2023
1.1.54 142 12/12/2023
1.1.53.16 174 12/5/2023
1.1.53.11 174 11/29/2023
1.1.53.6 182 11/25/2023
1.1.53 201 11/17/2023
1.1.52.22 174 11/17/2023
1.1.52.11 172 11/14/2023
1.1.52.9 147 11/14/2023
1.1.52.5 170 11/14/2023
1.1.52.3 177 11/10/2023
1.1.52 157 11/6/2023
1.1.51 156 11/2/2023
1.1.50.9 150 10/30/2023
1.1.50.8 171 10/27/2023
1.1.50.7 160 10/27/2023
1.1.50.6 171 10/27/2023
1.1.50 175 10/25/2023
1.1.49 183 10/19/2023
1.1.48.3 164 10/19/2023
1.1.48 201 10/18/2023
1.1.47.6 177 10/18/2023
1.1.47.5 186 10/17/2023
1.1.47.2 154 10/17/2023
1.1.47.1 159 10/17/2023
1.1.47 176 10/17/2023
1.1.45.6 198 10/16/2023
1.1.45 179 10/13/2023
1.1.44.11 184 10/12/2023
1.1.44.10 179 10/12/2023
1.1.44 191 10/11/2023
1.1.43.1 200 10/11/2023
1.1.43 191 10/6/2023
1.1.42.12 185 10/6/2023
1.1.42.11 194 9/28/2023
1.1.42.10 182 9/21/2023
1.1.42.2 176 9/19/2023
1.1.42.1 156 9/19/2023
1.1.42 165 9/17/2023
1.1.41.1 170 9/15/2023
1.1.41 172 9/13/2023
1.1.40 183 9/7/2023
1.1.39.1 212 8/25/2023
1.1.39 224 8/18/2023
1.1.38 224 8/11/2023
1.1.37.1 229 7/26/2023
1.1.37 233 7/22/2023
1.1.36.1 219 7/20/2023
1.1.36 219 7/19/2023
1.1.35 213 7/19/2023
1.1.34.6 254 7/7/2023
1.1.34.5 223 7/7/2023
1.1.34.4 251 7/4/2023
1.1.34 250 7/3/2023
1.1.33.45 251 7/3/2023
1.1.33.42 260 6/12/2023
1.1.33.41 206 6/5/2023
1.1.33.26 287 4/11/2023
1.1.33.25 260 4/11/2023
1.1.33.20 279 4/4/2023
1.1.33.19 289 4/3/2023
1.1.33.15 273 3/31/2023
1.1.33.14 286 3/31/2023
1.1.33.11 316 3/29/2023