2.0.24 • Published 21 days ago

sdk-datagrid v2.0.24

Weekly downloads
-
License
MIT
Repository
-
Last release
21 days ago

Description:

The sdk-datagrid component is a mobile-friendly, fully-functional data grid that gives the developer complete control over the processing and appearance of the data. From a simple table to a complex, customizable (Excel-like) spreadsheet, this component adds so much power to any application.

NOTE: This package leverages the sdk-core-library for core configurations (i.e., colors, icons, etc.).

INSTALLATION:

Using NPM:

npm install --save sdk-datagrid

CONFIGURATION:

To configure the sdk-datagrid for your application, add the following lines to your app.module.ts file:

import { SDKDatagridModule } from 'sdk-datagrid';

@NgModule({
    imports: [
        SDKDatagridModule
    ]
})
export class AppModule { }

PROPERTIES:

/**************************************************************************
* Input/Output Parameters for updating the Grid
**************************************************************************/
@Input() updateGrid: boolean = false; // Applies changes/data to the grid.
@Output() updateGridChange = new EventEmitter<boolean>(); // Callback to set updateGrid variable.

/**************************************************************************
* Input/Output Parameters for editing a record
**************************************************************************/
@Input() editRecordIndex: number | null | undefined; // The record that is currently being edited.
@Output() editRecordIndexChange = new EventEmitter<number | null | undefined>(); // Callback to set editRecordIndex variable.

/**************************************************************************
* Input/Output Parameters for dataset change
**************************************************************************/
@Input() datasets: string[] = []; // List of datasets.
@Input() activeDataset: string = ""; // The current selected dataset.
@Output() activeDatasetChange = new EventEmitter<string>(); // Callback to set activeDataset variable.

/**************************************************************************
* Input/Output Parameters for updating columns
**************************************************************************/
@Input() columns: SDKDataGridColumn[] = []; // The columns to be used for the grid.
@Input() columnHeaderStyle: string = ""; // Style used for column headers.
@Output() columnsChange = new EventEmitter<SDKDataGridColumn[]>(); // Callback to set columns variable.

/**************************************************************************
* Input/Output Parameters for updating custom filters
**************************************************************************/
@Input() customFilters: SDKDataGridCustomFilter[] = []; // Custom filters added to standard filter provided in loaddata callback (filters).
@Output() customFiltersChange = new EventEmitter<SDKDataGridCustomFilter[]>(); // Callback to set custom filters variable.

/**************************************************************************
* Input/Output Parameters for exporting data
**************************************************************************/
@Input() dataExport: any = ""; // The data to export.
@Output() dataExportChange = new EventEmitter<any>(); // Callback to set dataExport variable.

/**************************************************************************
* Input/Output Parameters for settings data
**************************************************************************/
@Input() settings: SDKDataGridSettings[] = []; // Options that are saved outside the grid. This value should be set to the value retieved from the datagrid @Output method "settingsSavedEvent". Consider it a passthrough value.
@Input() clearSettingsCache: boolean = false; // Clears any grid storage of settings.
@Output() savedSettingsEvent: EventEmitter<SDKDataGridSettings[]> = new EventEmitter(); // Used as a callback to save settings.
@Output() clearSettingsCacheChange = new EventEmitter<boolean>(); // Callback to set clearSettingsCache variable.

/**************************************************************************
* Required Output Parameters
**************************************************************************/
@Output() loadDataEvent = new EventEmitter<any>(); // Callback with grid changes.

/**************************************************************************
* Optional Input/Output Parameters
**************************************************************************/
@Input() name: string = ""; // Unique name of the grid (per page).
@Input() title: string = ""; // Title of the grid.
@Input() titleStyle: string = ""; // Style used for title.
@Input() options: SDKDataGridOptions | undefined; // Grid options.
@Input() fontFamily: string = ""; // font-family used for grid.
@Input() data: any = ""; // The data to display in the grid.
@Input() rowValues: number[] = [10, 25, 50, 100, 500, 1000]; // Sets the values used for records per page.
@Input() defaultRows: number = 100; // Default value for records per page.
@Input() rows: number | undefined; // Current rows in dataset.
@Input() page: number | undefined; // Current page of dataset.
@Input() total: number | undefined; // Total records in dataset.

@Output() saveGridDataEvent: EventEmitter<any> = new EventEmitter(); // Callback for saving changes to data.
@Output() deleteGridDataEvent: EventEmitter<any> = new EventEmitter(); // Callback for saving changes to data.
@Output() selectedRowActionEvent: EventEmitter<any> = new EventEmitter(); // // Callback for row actions. NOTE: The return object is { record: [the record], index: [the record index] }

/**************************************************************************
* Processing Parameters
**************************************************************************/
@Input() error: string = ""; // Any errors that occur during processing.
@Input() isDebug: boolean = false; // Turns on debugging.

USAGE:

Basic Setup

<sdk-datagrid
    [(updateGrid)]="updateGrid"
    [(columns)]="columns"
    [data]="data"
    [rows]="rows"
    [page]="page"
    [total]="total"
    [error]="error"
    (loadDataEvent)="loadData($event)">
</sdk-datagrid>

.ts file

public updateGrid: boolean = false; // Required 2-way binding.
public columns: SDKDataGridColumn[] = []; // Required 2-way binding.
public data: any;
public rows: number | undefined;
public page: number | undefined;
public total: number | undefined;
public error: string = "";

// Callback function for loading data (required).
public async loadData(event: any = null) {
    this.isLoading = true;

    let body: string = this.buildBody(event);

    try {
        await this.httpService.Post(dataSource, body).then((data: any) => {
            if (data) {
                this.data = data["Data"];
                this.rows = parseInt(data["Rows"]);
                this.page = parseInt(data["Page"]);
                this.total = parseInt(data["Total"]);
                this.error = data["Error"];

                setTimeout(() => {
                    this.updateGrid = true; // Tell the grid to update.
                }, 100);
            }
        });
    } catch (error: any) {
        this.error = error.message;
    }

    this.isLoading = false;
}

// Change the body parameters to fit your API call.
private buildBody(event: any = null): string {
    let sorts: any = [];
    let filters: any = [];
    let formulas: any = [];

    this.column.forEach((column: SDKDataGridColumn) => {
        if (column.Sort) {
            sorts.push({ ColumnName: column.Name, Direction: column.Sort.direction, Position: column.Sort.position });
        }

        if (column.Filter) {
            let filtersOperation = Object.keys(Filters)[Object.values(Filters).indexOf(column.Filter.operation.toString())];

            filters.push({ ColumnName: column.Name, Operation: filtersOperation, Value: column.Filter.value });
        }

        if (column.Formulas) {
            let formulaOperation = Object.keys(FormulaOperation)[Object.values(FormulaOperation).indexOf(column.Formulas.operation.toString())];

            formulas.push({ ColumnName: column.Name, Operation: formulaOperation, Format: column.Formulas.format });
        }
    });

    let parameters: any = {
        rows: event.rows,
        page: event.page,
        sorts: sorts,
        filters: filters,
        formulas: formulas
    };

    return JSON.stringify(parameters);
}

Columns

If you want to specify the columns, define them using the SDKDataGridColumn object.

.ts file

@ViewChild('category') category!: TemplateRef<any>;
@ViewChild('dataTemplate') dataTemplate!: TemplateRef<any>;
@ViewChild('actionRight') actionRight!: TemplateRef<any>;

public updateGrid: boolean = false;
public editRecordIndex: number | null | undefined = null;
public columns: SDKDataGridColumn[] = [
    { Name: 'category', DisplayName: 'Category', required: true, requiredColor: 'red', notes: 'MUST be a valid Category.', editTemplate: () => this.category },
    { Name: 'air_date', DisplayName: 'Date', required: true, validCharacters: 'calendar', pattern: 'YYYY-MM-DD' },
    { Name: 'question', DisplayName: 'Question', height: '50px', width: '100px', dataTemplate: () => this.dataTemplate },
    { Name: 'value', DisplayName: 'Value', required: true, notes: 'Between 100 - 1000.', validCharacters: 'numeric' },
    { Name: 'answer', DisplayName: 'Answer', dataTemplate: () => this.dataTemplate },
    { Name: 'round', DisplayName: 'Round' },
    { Name: 'show_number', DisplayName: 'Show', validCharacters: 'custom', pattern: '^[0-9]{4}$' },
    { Name: 'fin', DisplayName: 'Completed' },
    { Name: 'Edit', DisplayName: 'Edit', actionSide: "right", actionTemplate: () => this.actionRight }
];
public data: any;
public rows: number | undefined;
public page: number | undefined;
public total: number | undefined;
public error: string = "";

// If editing is enabled...
public editData(index: any) {
    this.editRecordIndex = index;
}

public saveData(rowItem: any, activeRow: any) {
    for (let key in activeRow) {
        if (Object.prototype.hasOwnProperty.call(activeRow, key)) {
            rowItem[key] = activeRow[key];
        }
    }

    // Save to database and show message.
}

public cancelData() {
    this.editRecordIndex = null;
}

.html file

<sdk-datagrid
    [(updateGrid)]="updateGrid"
    [(columns)]="columns"
    [(editRecordIndex)]="editRecordIndex"
    [data]="data"
    [rows]="rows"
    [page]="page"
    [total]="total"
    [error]="error"
    (loadDataEvent)="loadData($event)">
</sdk-datagrid>

<ng-template #category let-rowItem="rowItem" let-index="index">
    <div>
        <select style="margin-left: 10px;">
            <option value="">...</option>
            <option value="HISTORY">HISTORY</option>
            <option value="3-LETTER WORDS">3-LETTER WORDS</option>
            <option value="THE COMPANY LINE">THE COMPANY LINE</option>
            <option value="EPITAPHS & TRIBUTES">EPITAPHS & TRIBUTES</option>
            <option value="ESPN's TOP 10 ALL-TIME ATHLETES">ESPN's TOP 10 ALL-TIME ATHLETES</option>
        </select>
    </div>
</ng-template>

<ng-template #dataTemplate let-value="value">
    <div>{{ value }}</div>
</ng-template>

<ng-template #actionRight let-rowItem="rowItem" let-activeRow="activeRow" let-index="index">
    <div *ngIf="!rowItem.isEdit">
        <div title="Edit" class="dg-icon material-symbols-outlined cursor" (click)="editData(index)">edit</div>
        <div title="Delete" class="dg-icon material-symbols-outlined cursor delete">delete</div>
    </div>
    <div *ngIf="rowItem.isEdit">
        <div title="Save" class="dg-icon material-symbols-outlined cursor done" (click)="saveData(rowItem, activeRow)">done</div>
        <div title="Cancel" class="dg-icon material-symbols-outlined cursor delete" (click)="cancelData()">close</div>
    </div>
</ng-template>

Custom Options

If you want to add a custom option to the sdk-datagrid, use the optionAddons/windowAddons parameters. First, create your "custom" option and window components.

mycustom-option.component

.html file

<div (click)="showDataOptions('myCustom')">
    <div title="My Custom Option" class="sdk-icon" [ngClass]="optionTitle === 'myCustom' ? 'active' : ''">file_download</div>
    <div *ngIf="myCustomBadge !== ''" class="badge">
        <div class="label">{{ myCustomBadge }}</div>
    </div>
</div>

.ts file

import { Component, EventEmitter, Input, Output } from '@angular/core';

@Component({
    selector: 'mycustom-option',
    templateUrl: './mycustom-option.component.html',
    styleUrls: ['./mycustom-option.component.scss']
})
export class MyCustomOptionComponent {
    @Input() optionTitle: string = ""; // Unique name for option.
    @Output() showDataOptionsEvent = new EventEmitter<any>(); // Method to show option window.

    public myCustomBadge: string = ""; // Used to add badge to custom option.

    public showDataOptions(type: string) {
        this.showDataOptionsEvent.emit(type);
    }
}

mycustom-window.component

.html file

<div *ngIf="dataClass === 'expand' && optionTitle === 'mycustom'" class="sdk-datagrid-window">
    <div class="header">
        <span class="title">My Custom Option</span>
        <span title="Close" class="sdk-icon close" (click)="close()">close</span>
    </div>
    <div class="actions">
        // Add your custom actions here (if applicable).
    </div>
    <div class="content">
        // Add your custom option functionality here.
    </div>
    <div class="footer">
        <button class="button" type="button" (click)="apply()">Apply</button>
    </div>
</div>

.ts file

import { Component, EventEmitter, Input, Output } from '@angular/core';

import { SDKDataGridColumn } from 'sdk-datagrid';

@Component({
    selector: 'mycustom-window',
    templateUrl: './mycustom-window.component.html',
    styleUrls: ['./mycustom-window.component.scss']
})
export class MyCustomWindowComponent {
    @Input() dataClass: string = ""; // Used to indicate if window is open/closed.
    @Input() optionTitle: string = ""; // Unique name for option.
    @Input() datasets: any[] = []; // Data array.
    @Input() columns: SDKDataGridColumn[] = []; // Columns defines for data.
    @Input() filters: any[] = []; // Filters defines for data.
    @Input() sorts: any[] = []; // Sorting defines for data.

    @Output() applyEvent = new EventEmitter<any>(); // Apply option.
    @Output() closeEvent = new EventEmitter<any>(); // Close window.

    public close() {
        this.closeEvent.emit();
    }

    public async apply() {
        this.applyEvent.emit();
        this.closeEvent.emit();
    }
}

Then add those components to your datagrid.

.ts file

import { MyCustomOptionComponent } from './mycustom/option/mycustom-option.component';
import { MyCustomWindowComponent } from './mycustom/window/mycustom-window.component';

public myCustomOptionComponent = MyCustomOptionComponent;
public myCustomWindowComponent = MyCustomWindowComponent;

.html file

<sdk-datagrid
    [(updateGrid)]="updateGrid"
    [(columns)]="columns"
    [data]="data"
    [rows]="rows"
    [page]="page"
    [total]="total"
    [optionAddons]="[myCustomOptionComponent]"
    [windowAddons]="[myCustomWindowComponent]"
    [error]="error"
    (loadDataEvent)="loadData($event)">
</sdk-datagrid>

NOTES:

  • In order to update the grid, you MUST set the updateGrid property to true. The grid will automatically set it back to false once the update is complete (hence the 2-way binding).

  • To customize filtering for a column:

    Define the FilterTypes and FilterValues in the columns object.

    public columns: SDKDataGridColumn[] = [
        { Name: 'category', DisplayName: 'Category', required: true, requiredColor: 'red', notes: 'MUST be a valid Category.', editTemplate: () => this.category },
        { Name: 'air_date', DisplayName: 'Date', required: true, validCharacters: 'calendar', pattern: 'YYYY-MM-DD' },
        { Name: 'question', DisplayName: 'Question', height: '50px', width: '100px', dataTemplate: () => this.dataTemplate },
        { Name: 'value', DisplayName: 'Value', required: true, notes: 'Between 100 - 1000.', validCharacters: 'numeric' },
        { Name: 'answer', DisplayName: 'Answer', dataTemplate: () => this.dataTemplate },
        { Name: 'round', DisplayName: 'Round', FilterTypes: [ Filters.Equals ], FilterValues: [ 'Jeopardy!', 'Double Jeopardy!' ] },
        { Name: 'show_number', DisplayName: 'Show', FilterTypes: [ Filters.LessThanOrEqual, Filters.GreaterThanOrEqual ], FilterValues: [ 4000, 4500, 5000 ], validCharacters: 'custom', pattern: '^[0-9]{4}$' },
        { Name: 'fin', DisplayName: 'Completed', FilterTypes: [ Filters.Equals ], FilterValues: [ true, false ] },
        { Name: 'Edit', DisplayName: 'Edit', actionSide: "right", actionTemplate: () => this.actionRight }
    ];

    To use a multi-select dropdown as your filter, define the FilterMultiSelect and FilterValues in the columns object.

    		public columns: SDKDataGridColumn[] = [
    			{ Name: 'category', DisplayName: 'Category', required: true, requiredColor: 'red', notes: 'MUST be a valid Category.', editTemplate: () => this.category },
    			{ Name: 'air_date', DisplayName: 'Date', required: true, validCharacters: 'calendar', pattern: 'YYYY-MM-DD' },
    			{ Name: 'question', DisplayName: 'Question', isVisible: false, height: '50px', width: '100px', dataTemplate: () => this.dataTemplate },
    			{ Name: 'value', DisplayName: 'Value', required: true, notes: 'Between 100 - 1000.', validCharacters: 'numeric' },
    			{ Name: 'answer', DisplayName: 'Answer', showSort: false, showFilter: false, dataTemplate: () => this.dataTemplate },
    			{ Name: 'round', DisplayName: 'Round', FilterMultiSelect: true, FilterValues: [ 'Jeopardy!', 'Double Jeopardy!', 'Final Jeopardy!', 'Tiebreaker' ] },
    			{ Name: 'show_number', DisplayName: 'Show', FilterTypes: [ Filters.GreaterThanOrEqual, Filters.LessThanOrEqual ], FilterValues: [ 4000, 4500, 5000, 6000 ] },
    			{ Name: 'fin', DisplayName: 'Completed', FilterTypes: [ Filters.Equals ], FilterValues: [ true, false ]},
    			{ Name: 'Edit', DisplayName: 'Edit', actionSide: "right", actionTemplate: () => this.actionRight }
    		];
  • To create custom filters (SDKDataGridCustomFilter), the following properties are available:

    public Name: string = ""; // Unique filter name.
    public DisplayName?: string = "";  // Name to display to user.
    public Type?: FilterType = FilterType.Textbox; // Type of filter (Textbox, TextboxOnly, Checkbox, Dropdown).
    public notes?: string = "";
    
    // START: sdk-select properties for Dropdown filters.
    public FilterMultiSelect?: boolean = false; // Allows multiple filter values to be selected.
    public FilterTypes?: any[] = []; // Allows you to define specific filter types. NOTE: If FilterMultiSelect = true, this property is forced to [Filters.Equals, Filters.NotEquals].
    public FilterValues?: any[] = []; // Allows you to define specific filter values.
    public Filter?: any = null; // Values set for filter.
    public setFilterValues?: () => Promise<any[]>; // Optional callback method to load filter values.
    // END: sdk-select properties for Dropdown filters.
    
    FilterType Enums:
    - Textbox
    - TextboxOnly
    - Checkbox
    - Dropdown

    NOTE: If Type = FilterType.Textbox and is used with FilterTypes, the custom filter will have an Operation/Value layout. If FilterTypes is NOT used, the layout will ONLY have a Value.

  • To use columns (SDKDataGridColumn), the following properties are available:

    public Name: string = ""; // Original db name.
    public DisplayName?: string = "";  // System override of db name (Name).
    public FriendlyName?: string = "";  // User provides. Produces * indicator.
    public Sort?: any = null; // Sorting (asc/desc) applied to column data.
    public Filter?: any = null; // Filters applied to column data.
    public Formulas?: any = null; // Formulas applied to column.
    
    public showSort?: boolean = true; // Allows you to turn on/off sorting capabilities.
    public showFilter?: boolean = true; // Allows you to turn on/off filtering capabilities.
    public showTooltip?: boolean = false;
    public isAction?: boolean = false; // Is the column associated to an action.
    public isVisible?: boolean = true; // Allows you to turn on/off the visibility of the column.
    
    public actionSide?: string = "right" // right or left
    
    // START: Filter properties
    public FilterMultiSelect?: boolean = false; // Allows multiple filter values to be selected.
    public FilterTypes?: any[] = []; // Allows you to define specific filter types. NOTE: If FilterMultiSelect = true, this property is forced to [Filters.Equals, Filters.NotEquals].
    public FilterValues?: any[] = []; // Allows you to define specific filter values.
    public FilterType?: FilterType = FilterType.Textbox; // Type of filter (Textbox, TextboxOnly, Checkbox, Dropdown).
    // END: Filter properties
    
    // START: editTemplate option
    public allowEdit?: boolean = true;
    public required?: boolean = false;
    public notes?: string = "";
    public validCharacters?: string = "";
    public hint?: string = "";
    public pattern?: string = "";
    public height?: string = "";
    public width?: string = "";
    public border?: string = "";
    public style?: string = "";
    // END: editTemplate option
    
    // Custom templates
    public headerTemplate?: () => TemplateRef<any>;
    public dataTemplate?: () => TemplateRef<any>;
    public editTemplate?: () => TemplateRef<any>;
    
    // Custom methods
    public formatData?: (value: any) => string; // Optional callback method to format the data.
    public setFilterValues?: () => Promise<any[]>; // Optional callback method to load filter values.
2.0.24

21 days ago

2.0.22

21 days ago

2.0.23

21 days ago

2.0.21

21 days ago

2.0.19

23 days ago

2.0.20

22 days ago

2.0.17

26 days ago

2.0.18

26 days ago

2.0.15

29 days ago

2.0.16

29 days ago

2.0.13

1 month ago

2.0.14

1 month ago

2.0.11

1 month ago

2.0.12

1 month ago

2.0.10

1 month ago

2.0.3

1 month ago

2.0.2

1 month ago

2.0.5

1 month ago

2.0.4

1 month ago

2.0.7

1 month ago

2.0.6

1 month ago

2.0.9

1 month ago

2.0.1

1 month ago

2.0.0

1 month ago

1.3.24

2 months ago

1.3.25

2 months ago

1.3.23

2 months ago

1.3.28

2 months ago

1.3.26

2 months ago

1.3.27

2 months ago

1.3.22

2 months ago

1.3.21

2 months ago

1.3.13

2 months ago

1.3.14

2 months ago

1.3.17

2 months ago

1.3.18

2 months ago

1.3.15

2 months ago

1.3.16

2 months ago

1.3.19

2 months ago

1.3.20

2 months ago

1.3.11

2 months ago

1.3.12

2 months ago

1.3.10

2 months ago

1.3.9

2 months ago

1.3.8

2 months ago

1.3.7

3 months ago

1.3.6

3 months ago

1.3.5

3 months ago

1.3.3

3 months ago

1.3.2

3 months ago

1.3.1

3 months ago

1.2.8

3 months ago

1.2.12

3 months ago

1.2.13

3 months ago

1.2.10

3 months ago

1.2.11

3 months ago

1.2.9

3 months ago

1.3.0

3 months ago

1.2.6

3 months ago

1.2.5

3 months ago

1.2.4

3 months ago

1.2.3

3 months ago

1.2.2

3 months ago

1.2.0

3 months ago

1.2.1

3 months ago

1.1.67

3 months ago

1.1.68

3 months ago

1.1.63

4 months ago

1.1.62

4 months ago

1.1.66

4 months ago

1.1.65

4 months ago

1.1.64

4 months ago

1.1.61

5 months ago

1.1.60

5 months ago

1.1.59

5 months ago

1.1.52

6 months ago

1.1.51

6 months ago

1.1.50

6 months ago

1.1.56

5 months ago

1.1.55

5 months ago

1.1.54

6 months ago

1.1.53

6 months ago

1.1.58

5 months ago

1.1.57

5 months ago

1.1.49

7 months ago

1.1.29

9 months ago

1.1.28

9 months ago

1.1.30

9 months ago

1.1.34

9 months ago

1.1.33

9 months ago

1.1.32

9 months ago

1.1.31

9 months ago

1.1.38

9 months ago

1.1.37

9 months ago

1.1.36

9 months ago

1.1.35

9 months ago

1.1.39

9 months ago

1.1.41

9 months ago

1.1.40

9 months ago

1.1.45

9 months ago

1.1.44

9 months ago

1.1.43

9 months ago

1.1.42

9 months ago

1.1.48

8 months ago

1.1.47

8 months ago

1.1.46

9 months ago

1.1.1

11 months ago

1.1.0

11 months ago

1.1.9

10 months ago

1.1.8

10 months ago

1.1.7

11 months ago

1.1.6

11 months ago

1.1.5

11 months ago

1.1.4

11 months ago

1.1.3

11 months ago

1.1.2

11 months ago

1.1.12

10 months ago

1.1.11

10 months ago

1.1.10

10 months ago

1.1.16

10 months ago

1.1.15

10 months ago

1.1.14

10 months ago

1.1.13

10 months ago

1.1.19

10 months ago

1.1.18

10 months ago

1.1.17

10 months ago

1.1.23

10 months ago

1.1.22

10 months ago

1.1.21

10 months ago

1.1.20

10 months ago

1.1.27

9 months ago

1.1.26

9 months ago

1.1.25

9 months ago

1.1.24

9 months ago

1.0.100

11 months ago

1.0.99

11 months ago

1.0.98

11 months ago

1.0.97

11 months ago

1.0.96

11 months ago

1.0.62

12 months ago

1.0.61

1 year ago

1.0.60

1 year ago

1.0.66

12 months ago

1.0.65

12 months ago

1.0.64

12 months ago

1.0.63

12 months ago

1.0.69

12 months ago

1.0.68

12 months ago

1.0.67

12 months ago

1.0.73

12 months ago

1.0.72

12 months ago

1.0.71

12 months ago

1.0.70

12 months ago

1.0.77

12 months ago

1.0.76

12 months ago

1.0.75

12 months ago

1.0.74

12 months ago

1.0.79

12 months ago

1.0.78

12 months ago

1.0.39

1 year ago

1.0.38

1 year ago

1.0.40

1 year ago

1.0.44

1 year ago

1.0.43

1 year ago

1.0.42

1 year ago

1.0.41

1 year ago

1.0.48

1 year ago

1.0.47

1 year ago

1.0.46

1 year ago

1.0.45

1 year ago

1.0.49

1 year ago

1.0.51

1 year ago

1.0.50

1 year ago

1.0.55

1 year ago

1.0.54

1 year ago

1.0.53

1 year ago

1.0.52

1 year ago

1.0.59

1 year ago

1.0.58

1 year ago

1.0.57

1 year ago

1.0.56

1 year ago

1.0.33

1 year ago

1.0.32

1 year ago

1.0.31

1 year ago

1.0.30

1 year ago

1.0.37

1 year ago

1.0.36

1 year ago

1.0.35

1 year ago

1.0.34

1 year ago

1.0.80

12 months ago

1.0.84

12 months ago

1.0.83

12 months ago

1.0.82

12 months ago

1.0.81

12 months ago

1.0.88

12 months ago

1.0.87

12 months ago

1.0.86

12 months ago

1.0.85

12 months ago

1.0.89

12 months ago

1.0.91

12 months ago

1.0.90

12 months ago

1.0.95

12 months ago

1.0.94

12 months ago

1.0.93

12 months ago

1.0.92

12 months ago

1.0.29

1 year ago

1.0.28

1 year ago

1.0.27

1 year ago

1.0.26

1 year ago

1.0.25

1 year ago

1.0.24

1 year ago

1.0.23

1 year ago

1.0.22

1 year ago

1.0.21

1 year ago

1.0.20

1 year ago

1.0.19

1 year ago

1.0.18

1 year ago

1.0.17

1 year ago

1.0.16

1 year ago

1.0.15

1 year ago

1.0.14

1 year ago

1.0.13

1 year ago

1.0.12

1 year ago

1.0.11

1 year ago

1.0.10

1 year ago

1.0.8

1 year ago

1.0.7

1 year ago

1.0.6

1 year ago

1.0.5

1 year ago

1.0.4

1 year ago

1.0.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago