My normal compile command is:
node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng build --prod=true --optimization=true --aot
And that works fine. I follow the Angular instructions at ng-build / options / outputHashing=none|all|media|bundles To give me:
node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng build --prod=true --optimization=true --aot --output-hashing=all
And exactly the same number of bundles are created with exactly the same names. I have to tell my users to update their cache. I currently have five customers with approx ten PC's in each site each being used by several users. It's driving me a bit crazy, how am I supposed to implement CI/CD and release several times a week when my users are seeing old versions? I don't even know what version they're getting if I want to do a major release and then have to implement a few bug fixes afterwards.... I want to move to market but without a solution to this it's practically impossible. However, given the current crisis and the fact my customers are front-line (care homes for the elderly) my move to market will be delayed a few months.... I know it's not a Zero problem but, hey, I'm reaching out, guys. Any help would be appreciated.
It's past midnight here but I sent an email, I'm sure my colleague will be in touch first thing as long he's not in meetings, which is doubtful given current lockdown conditions! Can't do any more for you right now I'm afraid. I suggest you post your "onDataBinding()" and "onDataBound()" methods - there may be something in there. Anything in the browser console at all?
I can't help you there, I'm afraid. But I do have a colleague who uses the MVC version. I will email him the forum link and maybe he can help you.
@mhdevelop - create a controller for your grid in the Web.Host project: Here's a simple example of a method:
[DontWrapResult(WrapOnError = true)]
public async Task<JsonResult> GetActionsForEdit([DataSourceRequest]DataSourceRequest request, int isDeleted, long? parentId)
{
//for testing...
isDeleted = 0;
try
{
var query = await _ncActionService.GetNcActionsForEdit(isDeleted, parentId).ConfigureAwait(false);
var model = await query.ToDataSourceResultAsync(request).ConfigureAwait(false);
return Json(model);
}
catch (Exception ex)
{
throw new Exception(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.ToString(), ex);
}
}
Don't give up, Zero plays really nicely with Kendo Angular. In your Angular project create a separate service for Kendo grids: That code looks like this:
import { Injectable, Inject, Optional, InjectionToken } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { toDataSourceRequestString, translateDataSourceResultGroups, translateAggregateResults, DataResult, DataSourceRequestState } from '@progress/kendo-data-query';
import { GridDataResult } from '@progress/kendo-angular-grid';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { API_BASE_URL } from '@shared/service-proxies/service-proxies';
import * as moment from 'moment';
@Injectable({
providedIn: 'root'
})
export class KendoGridService {
private http: HttpClient;
private baseUrl: string;
constructor(
@Inject(HttpClient) http: HttpClient,
@Optional() @Inject(API_BASE_URL) baseUrl?: string) {
this.http = http;
this.baseUrl = baseUrl ? baseUrl : '';
}
getActions(
state: DataSourceRequestState,
isDeleted): Observable<DataResult> {
let params = new HttpParams();
params = params.append('isDeleted', isDeleted);
let url_ = this.baseUrl + '/kendogrid/GetActions';
url_ = url_.replace(/[?&]$/, '');
const queryStr = `${toDataSourceRequestString(state)}`; // Serialize the state
const hasGroups = state.group && state.group.length;
return this.http
.get(`${url_}?${queryStr}`, { params: params })
.pipe(map(({ data, total /*, aggregateResults*/ }: GridDataResult) => // Process the response
(<GridDataResult>{
// If there are groups, convert them to a compatible format
data: hasGroups ? translateDataSourceResultGroups(data) : data,
total: total,
// Convert the aggregates if such exist
//aggregateResult: translateAggregateResults(aggregateResults)
})));
}
Call your service from your component, casting your dates back to javascript dates:
getDevicesForKendo() {
this.gridLoading = true;
this._kendoGridService.getDevices(this.deviceGridSettings.state,
this.userId,
)
.subscribe((data) => {
data.data.forEach((d) => {
d.creationTime = new Date(d.creationTime);
d.deletionTime = new Date(d.deletionTime);
d.lastModificationTime = new Date(d.lastModificationTime);
});
this.deviceGridSettings.gridData = data;
this.gridLoading = false;
}, (error: HttpErrorResponse) => {
this.gridLoading = false;
if (error.status === 401) {
//this to capture refresh of grid when login has expired
abp.message.confirm(null, this.l('LoginHasExpired'), function (isConfirmed) {
if (isConfirmed) {
abp.auth.clearToken();
abp.utils.setCookieValue(AppConsts.authorization.encrptedAuthTokenName, undefined, undefined, abp.appPath);
location.href = '';
}
});
} else {
abp.message.error(this.l('KendoGridError', this.l('NcDevice')), this.l('Error'));
}
});
}
Hope that helps.
@ismcagdas, yes, that's been tried. It doesn't work. I think it's more to do with webpack config but I havent looked recently. @sumitshah - did you get any further with this?
This is something I would appreciate, I am also about to start building a CI/CD pipleine in DevOps for Angular/Core.
@mahendra, You could use IExtensibleInterface. Create a tenant object which allows the user to add fields dynamically (you will need to use a dynamic forms library e.g. ngx-formly). Use the dynamically created form for your tenant entity and save the results of the form back to the ExtensionData property of your individual entity. It's not easy but it's doable!
Hi @mhdevelop, I'll leave the bundle sizing for the guys at Volosoft to answer, it's not an easy one. If you're using Kendo you can remove lots of third party tools, especially where they are used only in the dashboard and demoui. As for Telerik controls lots of us are using them but the answer lies in the product version you are using. Simply type "Telerik" or "Kendo" into the serach box above; How To Guide: Using Telerik Kendo UI in NetZero 8.1 Core 3.1 jQuery Telerik reporting with ASP Net Zero Core jQuery AspNet Core Telerik
If you need specific code and you're working with the Zero angular version I can help by gicing you code snippets. If it's MVC then I'm sure other guys in the forum will be willing to pitch in.
Hi @Aaron, Nice to learn from those with better knowledge. In this instance I may need to extend the interface because we are not charging by edition but by the number of devices connected to the system. We are using Stripe in Zero only to create a new account (CreateSubscription()) when a trial period ends or when a tenant chooses to upgrade a trial. Our actual charging is done by an Azure function app which reads the db directly. That way we can use variable pricing for each tenant. We may need to extend the interface to pull back info from Stripe to display on the tenant's subscription dashboard. Hope that makes sense, and thanks for the help.
Hi @Aaron, good to see you in the forum, my friend. Your answer is correct, though the solution is not obvious, basically I have to create a n interface which looks as follows:
using Abp.Application.Services;
using Nuagecare.MultiTenancy.Payments.Stripe;
namespace Nuagecare.App.MultiTenancy.Payments.Stripe
{
public interface INuagecareStripePaymentAppService : IApplicationService, IStripePaymentAppService
{
}
}
And then inherit from my service like so:
public class NuagecareStripePaymentAppService : NuagecareAppServiceBase, INuagecareStripePaymentAppService
That may look obvious to guys like your self but it's very odd to me! Thanks for the pointer.