Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • Write tests for your code. We use jasmine for unit testing and protractor for end-to-end.
  • Ensure your code doesn't break any existing tests.

Creating a new component

  • A new component should consist of at least 3 files, in the same folder
    • an HTML file, containing the template e.g. sidebar.component.html
    • an SCSS file, containing the style. Create this even if it's to remain empty. e.g. sidebar.component.scss
    • a TypeScript file, containing the component definition e.g. sidebar.component.ts
      • Its templateUrl attribute should contain a reference to the HTML file: e.g. templateUrl: './sidebar.component.html'
      • Its styleUrls attribute (this is an array) should contain a reference to the style file: e.g. styleUrls: ['./sidebar.component.css']
        • Note that styleUrls refers to a CSS file rather than an SCSS file.That's because the AoT build process doesn't yet support SCSS, and the SCSS files get converted to CSS ahead of time. More information in the comments on this PR.
      • it's selector attribute should start with ds- This ensures the component name contains a dash, and indicates it's a dspace component. e.g. selector: 'ds-sidebar'
      • Example:

        Code Block
        languagejs
        @Component({
            selector: 'ds-sidebar',
            styleUrls: ['./sidebar.component.css'],
            templateUrl: './sidebar.component.html'
        })
        export class SidebarComponent {
        }

(S)CSS

  • General
    • Avoid writing (S)CSS if you can. Instead use Bootstrap 4 CSS classes and components where possible. That way it will be much easier to keep the style consistent across many different contributors. 
    • If you want to use a bootstrap component, take a look at the ng-bootstrap docs first. Chances are they've already turned it into an angular component for you.
    • If you need to add margins, padding, change font-sizes or colors etc, make use of the bootstrap variables rather than entering numerical values. (e.g. write margin-bottom: $spacer-y; instead of margin-bottom: 15px; and color: $brand-primary; instead of color: #0275d8;)
    • If there's no other way but to add a numerical value or color code yourself, consider turning it in to a variable, so it can be reused by others. Also calculations that are used more than once can benefit from being stored as variables: e.g. $ds-table-margin-bottom: ($font-size-base * 2) - ($gutter-width / 2);
  • Component Styles

    • Angular 2 makes use of component styles. By default, these can't leak out and affect the style of other components. Not even child components
    • The style for a component should go in a file called name.component.scss, in the same directory as the component. e.g. for src/app/home/home.component.ts the component style file is src/app/home/home.component.scss.
    • Note that the styleUrls parameter of the component refers to a CSS file, not an SCSS file. That's because the AoT build process doesn't yet support SCSS, and the SCSS files get converted to CSS ahead of time. More information in the comments on this PR.

...

  • Don't hard code user-facing text in components. We're using ng2-translate for i18n. You use it by adding your key to resources/i18n/en.json, and then using that key in the component with the translate pipe. e.g.:
    • in en.json put:  "my-route.my-component.my-label-descriptor": "My User Facing Text";
    • in your component put: "<h1>{{ 'my-route.my-component.my-label-descriptor' | translate }}</h1>"
  • For more info see the ng2-translate docs

State changes

  • The state in this application is managed by ngrx
  • Using it properly requires some discipline from developers and reviewers.
  • If you're new to redux or ngrx, take a look at the resources on the technology page
  • Anything that's dynamic about the application is called a state change, and should be saved in the store. 
  • That means a boolean that saves if the navigation is open or closed, or a list of DSpace Objects from the backend, anything that can change as the application runs.
  • Every state change should be defined as an action. in a file called ${feature-name}-actions.ts. e.g. host-window.actions.ts
    An action definition consists of 
  • The effect of each action on the state should be defined in the reducer, in a file called ${feature-name}-reducer.ts. e.g. host-window.reducer.ts
  • If an action is be the source of another action, that relation is described in an effect.
    • e.g. submitting the login form dispatches a LOGIN_REQUEST action, with the user's credentials as its payload.
    • an AuthorizationEffect class listens for that action, and when it occurs it calls the rest api with those login credentials 
    • if the REST API answers positively, the AuthorizationEffect dispatches a new LOGIN_SUCESS action, with the token that was returned.
    • if the REST API returns an error, the AuthorizationEffect dispatches a new LOGIN_ERROR action, with the error message that was returned.
  • All reducers need to be added to a single reducer aggregator file per module before they can be used
  • The same needs to happen for effect files

General

  • Keep adaptability in mind. An institution installing DSpace will often want to modify a few things about the UI. The easier we can make that, the better. Therefore keep your components small (divide them in to sub-components), make sub-modules for coherent functionality, use SASS variables, etc.
  • We agreed to remove the concept of Communities from the UI. They should be called Collections as well.

...