Base solution for your next web application

Activities of "maberry"

Mass notifications and "regular" notifications are stored in the same DB table. The table has a CreatorUserId field. If I create a mass notification the CreatorUserId is populated; however, the field is null if I create a "regular" in app notification. Am I doing something wrong, or is this the expected behavior? If it is the expected behavior, how can I get the CreatorUserId saved when creating all notification types?

    public async Task InvoiceNotificationAsync(Vendor vendor, string hostName, long userId, string userName)
    {
        Logger.Warn($"InvoiceRequestNotificationAsync called");

        var vendorTenantId = 1073;

        var notificationData = new LocalizableMessageNotificationData(
            new LocalizableString(
                "message",
                ERAConsts.LocalizationSourceName
            )
        );

        notificationData["hostName"] = hostName;
        notificationData["recordId"] = vendor.Id;
        notificationData["recordType"] = "vendor";
        notificationData["htmlCheck"] = "Yes";
        notificationData["TenantName"] = vendor.TenantName;
        notificationData["userId"] = userId;
        notificationData["userName"] = userName;

        notificationData["OrderNumber"] = vendor.OrderNumber;
        notificationData["InvoiceRequestDate"] = vendor.InvoiceRequestDate;

        await CurrentUnitOfWork.SaveChangesAsync();

        await _notificationPublisher.PublishAsync(AppNotificationNames.InvoiceRequested, notificationData,
                severity: NotificationSeverity.Warn, 
            tenantIds: new int?[] { vendorTenantId });                
    }

END GOAL

Scenario: User1 creates an order, which triggers a notification to inform User2 a task needs to be completed. User1 then realizes the order needs to be modified so he/she cancels the order. The task is removed from User2's view; however, the notification remains. I've been trying to figure out how to delete the notification when User1 cancels the order. I found this method:

    public async Task<GetPublishedNotificationsOutput> GetNotificationsPublishedByUser(
        GetPublishedNotificationsInput input)
    {
        return new GetPublishedNotificationsOutput(
            await _notificationStore.GetNotificationsPublishedByUserAsync(AbpSession.ToUserIdentifier(),
                AppNotificationNames.MassNotification, input.StartDate, input.EndDate)
        );
    }

I created a copy and changed AppNotificationNames.MassNotification to AppNotificationNames.InvoiceRequested, but then I realized the CreatorUserId is not saved.

What is the best way to set up a publicly available form in my multi-tenant application?

Version 12.3 Angular 16.1.2 Typescript 5.1.6

Once it is set up as public, if I understand correctly people could access the page via www.tenant1.myApplication.com/request where tenant1 is the name of the tenant, request is the name of the component, and myApplication is the domain. Is that correct?

Thanks,

Steven

Question

I am using the built in message service when initiating an html to PDF generation. The confirmation dialog does not close until the PDF has been generated. How can I force it to close after confirming so my user is not sitting there waiting for five seconds?

I am using the latest version of aspnetzero Angular and jsPDF and html2canvas to convert html to PDF.

    onGeneratePDF() {

        if (this.paymentInstaller.paymentStatus === PaymentStatusEnum.InvoiceSent) {
            this.message.confirm(
                '',
                this.l('pdfConfirmation'),
                (isConfirmed) => {
                    if (isConfirmed) {
                        this.generatePDF();
                    }
                }
            );
        }
    }


        async generatePDF() {
        const elementToPrint = this.pdfContent.nativeElement;
        this.fileName = this.invoiceNumber + '.pdf';
        const options = {
            margin: 36,
            filename: this.fileName,
            image: { type: 'jpeg', quality: 1 },
            html2canvas: { scale: 3 },
            jsPDF: { unit: 'pt', format: 'letter', orientation: 'portrait' }
        };

        let pdfData = await html2pdf().set(options).from(elementToPrint).toPdf().output('arraybuffer');

        // Convert the array buffer to a Blob
        const pdfBlob1 = new Blob([pdfData], { type: 'application/pdf' });

        this.uploadAndSave(pdfBlob1);
    }

    uploadAndSave(pdfBlob1: Blob) {
        // Convert the Uint8Array to a Blob
        const pdfBlob = new Blob([pdfBlob1], { type: 'application/pdf' });

        // Create a File object from the Blob
        const pdfFile = new File([pdfBlob], this.fileName, { type: 'application/pdf' });

        // Initialize the uploader and save the generated invoice
        this.invoiceFileUploader = this.initializeUploader(
            AppConsts.remoteServiceBaseUrl + '/GeneratedInvoices/UploadinvoiceFile',
            (fileToken) => {
                this.saveGeneratedInvoice(fileToken);
            }
        );

        this.invoiceFileUploader.clearQueue();
        this.invoiceFileUploader.addToQueue([pdfFile]);
        this.invoiceFileUploader.uploadAll();
    }

Question

I am using the most current version of AspNetZero / Angular with the current version of Metronic.

I created a new theme using a copy of Theme 6. Theme 6 has an aside menu, but it is not populated by default. I modified my new theme (themeX) so the "aside" provides the navigation, and I am only using the top-bar-menu in small screen/mobile situations.

I would like to project the <sub-menu> to where the <top-bar-menu> would "normally" be placed. I tried several things that have worked in past applications that were not aspnetzero, but I guess the framework does not make it as easy as it should be.

Can you please tell me what code should be put in my themeX-layout-component.html to project the <sub-menu> from the active page's html to the themeX header?

I have noticed several things with Power Tools that seem counterproductive to the mission of aspnetzero. Can someone please let me know if the issues listed below are problems with the extension or is it working as designed? If the latter, can someone please provide rationale? If I understand the thought process, I may be able to work differently so these situations are not a hinderance to my workflow.

  1. Power Tools generates code for the OnModelCreating section of the DbContext; however, the generated code seems to be lacking a lot of context compared to other similar code generators. Below are snippets of the same entity using Power Tools and then one using the ABP Commercial code generator.

Generated from Power Tools modelBuilder.Entity<Customer>(c => { c.HasIndex(e => new { e.TenantId }); });

Generated from ABP Suite builder.Entity<Customer>(b => { b.ToTable(mergeConsts.DbTablePrefix + "Customer", mergeConsts.DbSchema); b.ConfigureByConvention(); b.Property(x => x.TenantId).HasColumnName(nameof(Customer.TenantId)); b.Property(x => x.FirstName).HasColumnName(nameof(Customer.FirstName)).HasMaxLength(CustomerConsts.FirstNameMaxLength); b.Property(x => x.LastName).HasColumnName(nameof(Customer.LastName)).HasMaxLength(CustomerConsts.LastNameMaxLength); b.Property(x => x.Phone).HasColumnName(nameof(Customer.Phone)).HasMaxLength(CustomerConsts.PhoneMaxLength); b.Property(x => x.Email).HasColumnName(nameof(Customer.Email)).HasMaxLength(CustomerConsts.EmailMaxLength); b.Property(x => x.Business).HasColumnName(nameof(Customer.Business)).HasMaxLength(CustomerConsts.BusinessMaxLength); b.Property(x => x.FullName).HasColumnName(nameof(Customer.FullName)).HasMaxLength(CustomerConsts.FullNameMaxLength); b.Property(x => x.ContactType).HasColumnName(nameof(Customer.ContactType)); b.HasMany(x => x.Locations).WithOne().HasForeignKey(x => x.CustomerId).IsRequired().OnDelete(DeleteBehavior.NoAction); });

  1. I often find code generated several times for the same entity in the OnModelCreating section of the DbContext. For example, say I use Power Tools to create two entities: City and State. Once both are created, I return to PowerTools via the Regenerate Entity tab and create navigational properties between City and State. Rather than update existing code, Power Tools generates another City entity within OnModelCreating. This happens every time I regenerate an entity. It does not seem to be causing any issues, but at least very least it is bloating my code.

  1. Can you please point me to a tutorial related to how I should modify entities without breaking my code. For example - I created an entity titled Location with properties for Street Address, City, State, and Zip code. Later I decided I wanted separate tables for City, State, and Zip Code. I returned to Power Tools via the Regenerate Entity tab and removed the properties for City, State, and Zip Code. Once completed, I rebuilt and refreshed with nswag, but the result was so many errors I had to scrap the application and resort to an earlier copy. I do not have screenshots to show because I deleted the files; however, it seemed as though Power Tools deleted the properties from the projectName.Core folder, but it did not delete anywhere else. I have had this happen several times, so I assume there is a specific way the extension wants me to do it.

Can someone please provide assistance with configuring a dependent dropdown picklist for my application. Specs are as follows: Latest version of aspnetzero is being used.

Table 1: Customer Table 2: Location Table 3: Order Table 4; OrderLocation

Customer can have many locations. Therefore, the customer table uses a master-detail layout with Location (this is working fine). Both customer and location are set up as lookups in the OrderLocation table.

Orders can have only one customer but many locations, and the OrderLocation table provides tracking/status for each location in the order. Therefore, customer is a lookup field in the order table.

I want use one of the Metronic wizard layouts. When I create a new order, I want to be able to select the customer from the picklist. Then next screen will take me to the OrderLocation table where I want to select locations based only on the customer identified in the Order table.

I’ve seen several similar questions, but I haven’t seen anything similar enough for me to replicate. Mainly because I am new to aspnetzero and there is a learning curve with respect to the flow of data from database to angular. I am not the strongest with Angular, but I am using Angular because it appears to be “easier” to manipulate certain aspects within the DDD/aspnetzero framework.

Using this as a guide:

I have not made any modifications to the files generated by PowerTools within Visual Studio, so given the parameters above, I believe I need to change selectedCountry to _orderLocationServiceProxy,

The countries variable will need to be changed to order, and the states variable will need to be changed to location; however, I can not figure out the changes necessary for Country[] and State[] within the aspnetzero framework.

I assumed it would be something similar to _orderLocationServiceProxy.getAll(), but that does not work.

I know changes will also need to be made for the onSelect syntax as well, but I haven’t been able to try anything because I haven’t gotten the above working yet.

As previously indicated, I have searched the support forum here as well popular sites such as stackoverflow, but I have not been able to isolate my specific use case. Any assistance would be greatly appreciated.

Showing 1 to 6 of 6 entries