Activities of "bunyamin"

Hello,

You can simply initiate it as new TreeAdapter(list).

The important bit is that the list should have children that has fields like id, parentId which builds up the tree.

Hello @GregB,

We are utilizing this tree adapter which is available within @abp/ng.components package.

Hope it helps.

Hello,

You can follow the guide here

If you simply want to enable users to choose a picture from their computer, you can use something like <input type="file" id="avatar" name="avatar" accept="image/png, image/jpeg">. This is the native way of choosing files from your computer.

If you want them to choose a file that is already uploaded via the file-management module, you have to implement your own interface to do it. For the tree component, we use the tree component of ng-zorro

Hello,

I'm not quite sure about what you are trying to achieve. Could you explain your case little bit further with images if possible?

Thank you

Hello,

I will present two different ways to achieve what you are trying to do. However, keep in mind that the second option heavily relies on the internal implementation of the UsersComponent which could change in the future and we may introduce some breaking changes for that component. If you choose to follow the second option, it is your responsibility to ensure that your code is working. If there are some breaking changes, again it is your responsibility to edit your code accordingly.

First Option: Override UsersComponent

You could implement your own users page so that you can define any logic you'd like. Please refer to the docs for more detail about replacing components.

The key for UsersComponent is eIdentityComponents.Users

Second Option: Override Password field in the form

You can override password field for New user modal.

Please refer to the docs

Firstly, let's create a file and call it identity-create-form-prop-contributors.ts and add the following code block in it.

export function customAsyncPasswordValidator(data: PropData<IdentityUserDto>) {
   // validator will come here
}

const passwordField = new FormProp<IdentityUserDto>({
  type: ePropType.Password,
  name: 'password',
  displayName: 'AbpIdentity::Password',
  id: 'password',
  autocomplete: 'new-password',
  validators: _ => [Validators.required],
  asyncValidators: customAsyncPasswordValidator,
});

export function userCreateFormContributor(formProps: FormPropList<IdentityUserDto>) {
  const index = formProps.indexOf('password', (action, name) => action.name === name);
  formProps.dropByIndex(index);
  formProps.addByIndex(passwordField, index);
}

export const identityCreateFormContributors: IdentityCreateFormPropContributors = {
  [eIdentityComponents.Users]: [userCreateFormContributor],
};

Up to this point, we haven't done anything hacky yet. You can use this part confidently. It is the trivial way of overriding a field within an extensible form. However, the implementation of customAsyncPasswordValidator will be error-prone and depend on the internals of UsersComponent. It is up to you to decide whether to use the following implementation. It contains some comment about

export function customAsyncPasswordValidator(data: PropData<IdentityUserDto>) {
  const roleService = data.getInjected(IdentityRoleService);
  const user = data.getInjected(UsersComponent);

  /**
   * Retrieve the existing roles and filter them with name `Super Admin`
   */
  const superAdminRoleDetails = roleService.getAllList().pipe(
    map(roles => roles.items.filter(role => role.name === 'Super Admin')),
    shareReplay(), // this exists so that we will only retrieve this list once.
  );

  /**
   * If `Super Admin` is not selected, we should keep the default validators.
   * This function calls every validator with `control` to keep the default behavior.
   */
  const defaultValidator = (control: FormControl) =>
    of(
      getPasswordValidators({ get: data.getInjected }).reduce(
        (retVal, currValidator) => ({ ...retVal, ...currValidator(control) }),
        {},
      ),
    );
  const superAdminPasswordValidator = (control: FormControl) =>
    superAdminRoleDetails.pipe(
      map(details => {
        if (details?.length) {
          const rules = details[0];
          // You can write your custom rule here with rules.extraProperties
          return control.value !== '123456'
            ? {
                wrongPassword: true,
              }
            : null;
        }

        return null;
      }),
    );

  const validator = control => {
    /**
     * Find if a role group exists with name `Super Admin`
     */
    const superAdminGroup = user.roleGroups.find(roleGr => roleGr.contains('Super Admin'));

    if (superAdminGroup) {
      const isAdminSelected = superAdminGroup.controls['Super Admin'].value;
      return isAdminSelected ? superAdminPasswordValidator(control) : defaultValidator(control);
    }
    return defaultValidator(control);
  };

  return [validator];
}

Finally, we need to add some imports to app.module and app-routing.module

Import following into app.module

@NgModule({
    // ...
    imports: [
      // ...
      NgxValidateCoreModule.forRoot({
         blueprints: {
           wrongPassword: 'Please choose 123456',
        },
      })
    ]
export class AppModule {}

And, update app-routing.module

{
    path: 'identity',
    loadChildren: () =>
      import('@volo/abp.ng.identity').then(m =>
        m.IdentityModule.forLazy({
          // this line should be added
          createFormPropContributors: identityCreateFormContributors,
        }),
      ),
  },

Hello,

In the latest version of ABP, we replaced the Store parameter with Injector. Since you are running an early version, you should pass Store instead of Injector

You can find the related commit here

Hello,

It is available within @abp/ng.theme.shared package. You find an example of usage here

You can find the code of the function, getPasswordValidators

It is a simple function that takes injector.

setPasswordForm = this.fb.group({
    newPassword: ['', [Validators.required, ...getPasswordValidators(this.injector)]],
});
Answer

Hello @rbarbosa,

I assume you serve your angular application (built HTML and js files) and your APIs from the same domain.

On the localhost, it works just fine because your APIs running on https://localhost:44382 and your angular application on http://localhost:4200. The XSRF-TOKEN is set by a cookie which is marked as secure (meaning only the applications run on HTTPS can read and send this cookie). So, when the Angular application makes a request to the backend, that cookie is not being sent by the browser (as it should).

However, when you build and deploy your Angular application to a server, let's say https://www.yourdomain.com/ng-app which also serves your APIs https://www.yourdomain.com/apis things may get messy. If they are in the same domain, you should not write https://www.yourdomain.com into environment.prod.ts files.

Simply edit the apis section in environment.prod.ts to the following

export const environment = {
  production: true,
 ...snip...
  apis: {
    default: {
      url: '',
      rootNamespace: 'ProjectName',
    },
  },
} as Config.Environment;
Answer

@Ryan.sposato@ethany.com could you please share your setup? I've tried it and it works with my setup.

Showing 131 to 140 of 149 entries
Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11