aspnet, angular, 5.1.0 If I am not mistaken 5.10 implements PrimeNG 4.2.2. Does that mean we still use DataTable and not TurboTable? I can't see "Prime" in the 5.3 milestone. Are there plans to upgrade?
@ dparizek bump. bump. bump. Build the database, reverse to models, create the UI. I am with you.
@ismcagdas - thanks for your time on this. I will come back to the problem later but I'm beginning to think that the ability to get and set values on the server give me little advantage. I will take a look at mapping to a typescript interface in Angular later but all-in-all I think a simple nvarchar(max) with raw json will give me better results. Again, thanks for your efforts.
@ismcagdas - thanks.
@ismcagdas - perhaps an easier question would be to ask: Once I have ExtensionData set as follows,
{"DataProviderId":"653","DateOfBirth":"03/02/1971 00:00:00"}
how the hell do I iterate over it in Angular?
I have tried pipes and Object.keys but I am getting nothing meaningful.
Is there any code examples of using IExtendableObject in Angular or should I revert to using plain JSON saved in an nvarchar(max) column?
@ismcagdas - the tests gave me a lot of pointers, thanks.
I read a third party database, get the relevant row and iterate through the columns in the database using sys.columns and, if the cell has a value I save it into a dictionary. I serialise the dictionary and pass it back to Zero where it is deserialised and then, using a foreach loop, I use entity.SetData() for each key-value-pair.
I now have a set of entities in Zero and I want to get the data from ExtensionData. Each entity has a different number of kvp's and each may have different values for keys.
My question is:
Is there any foreach mechanism to read through each KVP in the IExtensibleObject interface or am I faced with casting json back to a dymanic object and iterating through that (which kind of negates the whole point of IExtensibleObject?
@ismcagdas - thsnk, I can roll my own but it's always better to have a frame of reference. When designing the setup of the system features and features within editions are a key point of architecture.
Ishmael, there's a lot of code below because I can't work out what file extensions are allowed! The issue is trivial in that it creates a warning on Github which can be ignored, but here are the cli versions and package.json contents. Yarn.lock is too big to post here. Angular CLI:
Angular CLI: 1.6.3
Node: 8.9.1
OS: win32 x64
Angular: 5.1.2
... animations, common, compiler, compiler-cli, core, forms
... http, platform-browser, platform-browser-dynamic
... platform-server, router
@angular/cli: 1.6.3
@angular-devkit/build-optimizer: 0.0.36
@angular-devkit/core: 0.0.22
@angular-devkit/schematics: 0.0.42
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.9.3
@schematics/angular: 0.1.11
@schematics/schematics: 0.0.11
typescript: 2.4.2
webpack: 3.10.0
package.json:
{
"name": "abp-zero-template",
"version": "4.0.0",
"license": "MIT",
"angular-cli": {},
"scripts": {
"ng": "ng",
"start": "ng serve --host 0.0.0.0 --port 4200",
"hmr": "ng serve --host 0.0.0.0 --port 4200 4201 --hmr -e=hmr",
"test": "ng test",
"pree2e": "webdriver-manager update --standalone false --gecko false",
"e2e": "protractor"
},
"private": true,
"dependencies": {
"@angular/animations": "^5.1.2",
"@angular/common": "^5.1.2",
"@angular/compiler": "^5.1.2",
"@angular/core": "^5.1.2",
"@angular/forms": "^5.1.2",
"@angular/http": "^5.1.2",
"@angular/platform-browser": "^5.1.2",
"@angular/platform-browser-dynamic": "^5.1.2",
"@angular/platform-server": "^5.1.2",
"@angular/router": "^5.1.2",
"@fancyapps/fancybox": "^3.1.25",
"abp-ng2-module": "^1.3.0",
"abp-web-resources": "^3.2.3",
"angular2-counto": "^1.2.3",
"animate.css": "3.5.2",
"autosize": "^4.0.0",
"block-ui": "^2.70.1",
"blueimp-file-upload": "^9.19.1",
"bootstrap": "^4.0.0",
"bootstrap-datepicker": "^1.7.1",
"bootstrap-daterangepicker": "^2.1.25",
"bootstrap-hover-dropdown": "^2.2.1",
"bootstrap-markdown": "^2.10.0",
"bootstrap-maxlength": "^1.6.0",
"bootstrap-notify": "^3.1.3",
"bootstrap-select": "^1.12.4",
"bootstrap-switch": "^3.3.4",
"bootstrap-timepicker": "^0.5.2",
"bootstrap-touchspin": "^3.1.1",
"bootstrap4-datetimepicker": "^5.2.3",
"bower": "*",
"chart.js": "^2.6.0",
"chartist": "^0.11.0",
"codelyzer": "^4.0.1",
"core-js": "^2.4.1",
"css-toggle-switch": "^4.0.3",
"d3": "^3.5.17",
"datamaps": "^0.5.8",
"detect-zoom": "^1.0.2",
"devextreme": "17.2.4",
"devextreme-angular": "17.2.4",
"dropzone": "^5.1.1",
"easy-pie-chart": "^2.1.7",
"eonasdan-bootstrap-datetimepicker": "^4.17.47",
"famfamfam-flags": "^1.0.0",
"file-saver": "^1.3.3",
"flot": "^0.8.0-alpha",
"font-awesome": "^4.7.0",
"gmaps": "^0.4.24",
"inputmask": "^3.3.7",
"ion-rangeslider": "^2.2.0",
"jasmine-spec-reporter": "^4.2.1",
"jquery": "^3.2.1",
"jquery-form": "^4.2.1",
"jquery-migrate": "^3.0.0",
"jquery-slimscroll": "^1.3.8",
"jquery-sparkline": "^2.4.0",
"jquery-ui": "^1.12.0",
"jquery-validation": "^1.15.1",
"jquery.counterup": "^2.1.0",
"jquery.flot.tooltip": "^0.9.0",
"jquery.inputmask": "^3.3.4",
"jquery.uniform": "^4.2.0",
"jqueryui": "^1.11.1",
"jqvmap": "^1.5.1",
"js-cookie": "^2.1.4",
"js-url": "^2.3.0",
"json2": "*",
"jstree": "^3.3.4",
"karma": "^1.7.0",
"localforage": "^1.5.0",
"lodash": "^4.17.4",
"malihu-custom-scrollbar-plugin": "^3.1.5",
"moment": "^2.18.1",
"moment-timezone": "^0.5.13",
"morris.js": "^0.5.0",
"mustache": "^2.3.0",
"ng-recaptcha": "^3.0.0",
"ng2-file-upload": "^1.2.1",
"ng2modules-easypiechart": "^0.0.4",
"ng2modules-flot": "^0.0.1",
"ngx-bootstrap": "^2.0.0-beta.8",
"pace-progress": "^1.0.2",
"popper.js": "^1.12.5",
"primeng": "4.2.2",
"prismjs": "^1.8.1",
"push.js": "1.0.4",
"quill": "^1.3.0",
"rangeslider.js": "^2.3.1",
"raphael": "^2.2.7",
"rtl-detect": "^1.0.0",
"rxjs": "^5.5.2",
"select2": "^4.0.3",
"select2-bootstrap-theme": "0.1.0-beta.9",
"signalr": "^2.2.1",
"simple-line-icons": "^2.4.1",
"socicon": "^3.0.5",
"spin.js": "^2.3.2",
"summernote": "^0.8.6",
"sweetalert": "^2.0.8",
"tether": "^1.4.0",
"timeago": "^1.6.1",
"toastr": "^2.1.2",
"topojson": "^3.0.2",
"ts-helpers": "^1.1.2",
"ts-node": "~3.3.0",
"typeahead.js": "^0.11.1",
"typescript": "2.4.2",
"underscore": "^1.8.3",
"urijs": "^1.19.0",
"waypoints": "^4.0.1",
"zone.js": "0.8.17"
},
"devDependencies": {
"@angular/cli": "^1.6.3",
"@angular/compiler-cli": "^5.1.2",
"@angularclass/hmr": "^2.1.3",
"@angularclass/hmr-loader": "^3.0.4",
"@types/bootstrap": "^3.3.33",
"@types/grecaptcha": "^2.0.31",
"@types/jasmine": "~2.5.53",
"@types/jasminewd2": "~2.0.2",
"@types/jquery": "^3.2.12",
"@types/jquery.blockui": "0.0.28",
"@types/jstree": "^3.3.34",
"@types/lodash": "^4.14.62",
"@types/moment": "^2.13.0",
"@types/moment-timezone": "^0.2.34",
"@types/morris.js": "^0.5.6",
"@types/node": "^8.0.27",
"@types/signalr": "^2.2.33",
"@types/tether": "^1.4.2",
"@types/toastr": "^2.1.33",
"codelyzer": "^4.0.1",
"jasmine-core": "~2.8.0",
"jasmine-spec-reporter": "^4.2.1",
"karma": "^1.7.0",
"karma-chrome-launcher": "~2.2.0",
"karma-cli": "~1.0.1",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"nswag": "11.12.7",
"protractor": "~5.1.2",
"ts-node": "~3.3.0",
"tslint": "~5.7.0",
"typescript": "2.4.2"
}
}
Now I see. The method CreateFeatureIfNotExists() is written to work with Boolean Features only, to support testing for chat features. By modifying the method as follows:
private void CreateFeatureIfNotExists(int editionId, string featureName, string value)
{
var defaultEditionChatFeature = _context.EditionFeatureSettings.IgnoreQueryFilters()
.FirstOrDefault(ef => ef.EditionId == editionId && ef.Name == featureName);
if (defaultEditionChatFeature == null)
{
_context.EditionFeatureSettings.Add(new EditionFeatureSetting
{
Name = featureName,
Value = value,
EditionId = editionId
});
}
}
And passing in a string value as opposed to a boolean for isEnabled. The method is written to work with Boolean Features only, the above method changes it to a Value Feature. In fact I believe the terminology is misleading here, a Boolean Feature is identical to a Value feature except that it holds a string value for "true" or "false". Correct me if I am wrong. I think the source would benefit from making the above changes, as it stands it is not possible to test Value features without modification.
I have three editions based on the number of devices registered with the system. The number of devices is defined as a feature. In DefaultEditionCreator I create these editions, for example here is the default edition:
var defaultEdition = _context.Editions.IgnoreQueryFilters().FirstOrDefault(e => e.Name == EditionManager.DefaultEditionName);
if (defaultEdition == null)
{
defaultEdition = new SubscribableEdition {
Name = EditionManager.DefaultEditionName,
DisplayName = EditionManager.DefaultEditionName,
MonthlyPrice = 200,
AnnualPrice = 2000,
TrialDayCount = 14,
WaitingDayAfterExpire = 3
};
_context.Editions.Add(defaultEdition);
_context.SaveChanges();
CreateFeatureIfNotExists(defaultEdition.Id, AppFeatures.MaxUserCount, false);
CreateFeatureIfNotExists(defaultEdition.Id, AppFeatures.MaxDeviceCount, true);
}
Now I create my ten device edition:
var tenDeviceEdition = _context.Editions.IgnoreQueryFilters().FirstOrDefault(e => e.Name == "10 devices");
if (tenDeviceEdition == null)
{
tenDeviceEdition = new SubscribableEdition
{
Name = "10 devices",
DisplayName = "10 devices",
MonthlyPrice = 350,
AnnualPrice = 3500,
WaitingDayAfterExpire = 7
};
_context.Editions.Add(tenDeviceEdition);
_context.SaveChanges();
CreateFeatureIfNotExists(tenDeviceEdition.Id, AppFeatures.MaxUserCount, false);
CreateFeatureIfNotExists(tenDeviceEdition.Id, AppFeatures.MaxDeviceCount, true);
}
Now I want to set the value of MaxDeviceCount for the ten device edition to 10. The method DefaultEditionCreator.CreateEditions() is synchronous. All of the methods for EditionManager and IEditionAppService are asynchronous. I want to set the edition feature value in a similar way to that used in the test, EditionAppService_Tests.Should_Update_Edition():
var output = await _editionAppService.GetEditionForEdit(new NullableIdDto(defaultEdition.Id));
//Changing a sample feature value
var chatFeature = output.FeatureValues.FirstOrDefault(f => f.Name == AppFeatures.ChatFeature);
if (chatFeature != null)
{
chatFeature.Value = chatFeature.Value = "true";
}
My question is:
Is there any way to set feature values for editions in DefaultEditionCreator.CreateEditions()?