Base solution for your next web application
Starts in:
01 DAYS
01 HRS
01 MIN
01 SEC

Activities of "BobIngham"

Question

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?

Answer

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

Answer

@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?

Answer

@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()?

Showing 551 to 560 of 619 entries