GithubHelp home page GithubHelp logo

dspace / dspace-angular Goto Github PK

View Code? Open in Web Editor NEW
119.0 45.0 374.0 68.16 MB

DSpace 7.x (and later) User Interface built on Angular.io

Home Page: https://wiki.lyrasis.org/display/DSDOC7x/

License: BSD 3-Clause "New" or "Revised" License

JavaScript 0.06% TypeScript 91.61% HTML 7.09% Dockerfile 0.01% SCSS 1.20% EJS 0.03%
dspace typescript ngrx yarn angular angular-ui repository user-interface

dspace-angular's Introduction

Build Status Coverage Status Universal Angular

dspace-angular

The DSpace User Interface built on Angular, written in TypeScript and using Angular Universal.

Overview

DSpace open source software is a turnkey repository application used by more than 2,000 organizations and institutions worldwide to provide durable access to digital resources. For more information, visit http://www.dspace.org/

DSpace consists of both a Java-based backend and an Angular-based frontend.

Downloads

Documentation / Installation

Documentation for each release may be viewed online or downloaded via our Documentation Wiki.

The latest DSpace Installation instructions are available at: https://wiki.lyrasis.org/display/DSDOC7x/Installing+DSpace

Quick start

Ensure you're running Node v16.x or v18.x, npm >= v5.x and yarn == v1.x

# clone the repo
git clone https://github.com/DSpace/dspace-angular.git

# change directory to our repo
cd dspace-angular

# install the local dependencies
yarn install

# start the server
yarn start

Then go to http://localhost:4000 in your browser

Not sure where to start? watch the training videos linked in the Introduction to the technology section below.

Table of Contents

Introduction to the technology

You can find more information on the technologies used in this project (Angular.io, Angular CLI, Typescript, Angular Universal, RxJS, etc) on the LYRASIS wiki

Requirements

  • Node.js and yarn
  • Ensure you're running node v16.x or v18.x and yarn == v1.x

If you have nvm or nvm-windows installed, which is highly recommended, you can run nvm install --lts && nvm use to install and start using the latest Node LTS.

Installing

  • yarn install to install the local dependencies

Configuring

Default runtime configuration file is located in config/ folder. These configurations can be changed without rebuilding the distribution.

To override the default configuration values, create local files that override the parameters you need to change. You can use config.example.yml as a starting point.

  • Create a new config.(dev or development).yml file in config/ for a development environment;
  • Create a new config.(prod or production).yml file in config/ for a production environment;

The settings can also be overwritten using an environment file or environment variables.

This file should be called .env and be placed in the project root.

The following non-convention settings:

DSPACE_HOST # The host name of the angular application
DSPACE_PORT # The port number of the angular application
DSPACE_NAMESPACE # The namespace of the angular application
DSPACE_SSL # Whether the angular application uses SSL [true/false]

All other settings can be set using the following convention for naming the environment variables:

  1. replace all . with _
  2. convert all characters to upper case
  3. prefix with DSPACE_

e.g.

# The host name of the REST application
rest.host => DSPACE_REST_HOST

# The port number of the REST application
rest.port => DSPACE_REST_PORT

# The namespace of the REST application
rest.nameSpace => DSPACE_REST_NAMESPACE

# Whether the angular REST uses SSL [true/false]
rest.ssl => DSPACE_REST_SSL

cache.msToLive.default => DSPACE_CACHE_MSTOLIVE_DEFAULT
auth.ui.timeUntilIdle => DSPACE_AUTH_UI_TIMEUNTILIDLE

The equavelant to the non-conventional legacy settings:

DSPACE_UI_HOST => DSPACE_HOST
DSPACE_UI_PORT => DSPACE_PORT
DSPACE_UI_NAMESPACE => DSPACE_NAMESPACE
DSPACE_UI_SSL => DSPACE_SSL

The same settings can also be overwritten by setting system environment variables instead, E.g.:

export DSPACE_HOST=demo.dspace.org
export DSPACE_UI_PORT=4000

The priority works as follows: environment variable overrides variable in .env file overrides external config set by DSPACE_APP_CONFIG_PATH overrides config.(prod or dev).yml

These configuration sources are collected at run time, and written to dist/browser/assets/config.json for production and src/app/assets/config.json for development.

The configuration file can be externalized by using environment variable DSPACE_APP_CONFIG_PATH.

Buildtime Configuring

Buildtime configuration must defined before build in order to include in transpiled JavaScript. This is primarily for the server. These settings can be found under src/environment/ folder.

To override the default configuration values for development, create local file that override the build time parameters you need to change.

  • Create a new environment.(dev or development).ts file in src/environment/ for a development environment;

If needing to update default configurations values for production, update local file that override the build time parameters you need to change.

  • Update environment.production.ts file in src/environment/ for a production environment;

The environment object is provided for use as import in code and is extended with the runtime configuration on bootstrap of the application.

Take caution moving runtime configs into the buildtime configuration. They will be overwritten by what is defined in the runtime config on bootstrap.

Using environment variables in code

To use environment variables in a UI component, use:

import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface';
...
constructor(@Inject(APP_CONFIG) private appConfig: AppConfig) {}
...

or

import { environment } from '../environment.ts';

Running the app

After you have installed all dependencies you can now run the app. Run yarn run start:dev to start a local server which will watch for changes, rebuild the code, and reload the server for you. You can visit it at http://localhost:4000.

Running in production mode

When building for production we're using Ahead of Time (AoT) compilation. With AoT, the browser downloads a pre-compiled version of the application, so it can render the application immediately, without waiting to compile the app first. The compiler is roughly half the size of Angular itself, so omitting it dramatically reduces the application payload.

To build the app for production and start the server (in one command) run:

yarn start

This will run the application in an instance of the Express server, which is included.

If you only want to build for production, without starting, run:

yarn run build:prod

This will build the application and put the result in the dist folder. You can copy this folder to wherever you need it for your application server. If you will be using the built-in Express server, you'll also need a copy of the node_modules folder tucked inside your copy of dist.

After building the app for production, it can be started by running:

yarn run serve:ssr

Running the application with Docker

NOTE: At this time, we do not have production-ready Docker images for DSpace. That said, we do have quick-start Docker Compose scripts for development or testing purposes.

See Docker Runtime Options

Cleaning

# clean everything, including node_modules. You'll need to run yarn install again afterwards.
yarn run clean

# clean files generated by the production build (.ngfactory files, css files, etc)
yarn run clean:prod

# cleans the distribution directory
yarn run clean:dist

Testing

Test a Pull Request

If you would like to contribute by testing a Pull Request (PR), here's how to do so. Keep in mind, you do not need to have a DSpace backend / REST API installed locally to test a PR. By default, the dspace-angular project points at our demo REST API

  1. Pull down the branch that the Pull Request was built from. Easy instructions for doing so can be found on the Pull Request itself.
    • Next to the "Merge" button, you'll see a link that says "command line instructions".
    • Click it, and follow "Step 1" of those instructions to checkout the pull down the PR branch.
  2. yarn run clean (This resets your local dependencies to ensure you are up-to-date with this PR)
  3. yarn install (Updates your local dependencies to those in the PR)
  4. yarn start (Rebuilds the project, and deploys to localhost:4000, by default)
  5. At this point, the code from the PR will be deployed to http://localhost:4000. Test it out, and ensure that it does what is described in the PR (or fixes the bug described in the ticket linked to the PR).

Once you have tested the Pull Request, please add a comment and/or approval to the PR to let us know whether you found it to be successful (or not). Thanks!

Unit Tests

Unit tests use the Jasmine test framework, and are run via Karma.

You can find the Karma configuration file at the same level of this README file:./karma.conf.js If you are going to use a remote test environment you need to edit the ./karma.conf.js. Follow the instructions you will find inside it. To executing tests whenever any file changes you can modify the 'autoWatch' option to 'true' and 'singleRun' option to 'false'. A coverage report is also available at: http://localhost:9876/ after you run: yarn run coverage.

The default browser is Google Chrome.

Place your tests in the same location of the application source code files that they test, e.g. ending with *.component.spec.ts

and run: yarn test

If you run into odd test errors, see the Angular guide to debugging tests: https://angular.io/guide/test-debugging

E2E Tests

E2E tests (aka integration tests) use Cypress.io. Configuration for cypress can be found in the cypress.json file in the root directory.

The test files can be found in the ./cypress/integration/ folder.

Before you can run e2e tests, two things are REQUIRED:

  1. You MUST be running the DSpace backend (i.e. REST API) locally. The e2e tests will NOT succeed if run against our demo/sandbox REST API (https://demo.dspace.org/server/ or https://sandbox.dspace.org/server/), as those sites may have content added/removed at any time.
    • After starting up your backend on localhost, make sure either your config.prod.yml or config.dev.yml has its rest settings defined to use that localhost backend.
    • If you'd prefer, you may instead use environment variables as described at Configuring. For example:
      DSPACE_REST_SSL = false
      DSPACE_REST_HOST = localhost
      DSPACE_REST_PORT = 8080
      
  2. Your backend MUST include our Entities Test Data set. Some tests run against a specific Community/Collection/Item UUID. These UUIDs are all valid for our Entities Test Data set.

After performing the above setup, you can run the e2e tests using

ng e2e

NOTE: By default these tests will run against the REST API backend configured via environment variables or in config.prod.yml. If you'd rather it use config.dev.yml, just set the NODE_ENV environment variable like this:

NODE_ENV=development ng e2e

The ng e2e command will start Cypress and allow you to select the browser you wish to use, as well as whether you wish to run all tests or an individual test file. Once you click run on test(s), this opens the Cypress Test Runner to run your test(s) and show you the results.

Writing E2E Tests

All E2E tests must be created under the ./cypress/integration/ folder, and must end in .spec.ts. Subfolders are allowed.

  • The easiest way to start creating new tests is by running ng e2e. This builds the app and brings up Cypress.
  • From here, if you are editing an existing test file, you can either open it in your IDE or run it first to see what it already does.
  • To create a new test file, click + New Spec File. Choose a meaningful name ending in spec.ts (Please make sure it ends in .ts so that it's a Typescript file, and not plain Javascript)
  • Start small. Add a basic describe and it which just cy.visit the page you want to test. For example:
    describe('Community/Collection Browse Page', () => {
     it('should exist as a page', () => {
         cy.visit('/community-list');
     });
    });
    
  • Run your test file from the Cypress window. This starts the Cypress Test Runner in a new browser window.
  • In the Cypress Test Runner, you'll Cypress automatically visit the page. This first test will succeed, as all you are doing is making sure the page exists.
  • From here, you can use the Selector Playground in the Cypress Test Runner window to determine how to tell Cypress to interact with a specific HTML element on that page.
    • Most commands start by telling Cypress to get() a specific element, using a CSS or jQuery style selector
      • It's generally best not to rely on attributes like class and id in tests, as those are likely to change later on. Instead, you can add a data-test attribute to makes it clear that it's required for a test.
    • Cypress can then do actions like click() an element, or type() text in an input field, etc.
      • When running with server-side rendering enabled, the client first receives HTML without the JS; only once the page is rendered client-side do some elements (e.g. a button that toggles a Bootstrap dropdown) become fully interactive. This can trip up Cypress in some cases as it may try to click or type in an element that's not fully loaded yet, causing tests to fail.
      • To work around this issue, define the attributes you use for Cypress selectors as [attr.data-test]="'button' | ngBrowserOnly". This will only show the attribute in CSR HTML, forcing Cypress to wait until CSR is complete before interacting with the element.
    • Cypress can also validate that something occurs, using should() assertions.
  • Any time you save your test file, the Cypress Test Runner will reload & rerun it. This allows you can see your results quickly as you write the tests & correct any broken tests rapidly.
  • Cypress also has a great guide on writing your first test with much more info. Keep in mind, while the examples in the Cypress docs often involve Javascript files (.js), the same examples will work in our Typescript (.ts) e2e tests.

Hint: Creating e2e tests is easiest in an IDE (like Visual Studio), as it can help prompt/autocomplete your Cypress commands.

More Information: docs.cypress.io has great guides & documentation helping you learn more about writing/debugging e2e tests in Cypress.

Learning how to build tests

See our DSpace Code Testing Guide for more hints/tips.

Documentation

Official DSpace documentation is available in the DSpace wiki at https://wiki.lyrasis.org/display/DSDOC7x/

Some UI specific configuration documentation is also found in the ./docs folder of this codebase.

Building code documentation

To build the code documentation we use TYPEDOC. TYPEDOC is a documentation generator for TypeScript projects. It extracts information from properly formatted comments that can be written within the code files. Follow the instructions here to know how to make those comments.

Run:yarn run docs to produce the documentation that will be available in the 'doc' folder.

Other commands

There are many more commands in the scripts section of package.json. Most of these are executed by one of the commands mentioned above.

A command with a name that starts with pre or post will be executed automatically before or after the script with the matching name. e.g. if you type yarn run start the prestart script will run first, then the start script will trigger.

Recommended Editors/IDEs

To get the most out of TypeScript, you'll need a TypeScript-aware editor. We've had good experiences using these editors:

Contributing

See Contributing documentation

File Structure

dspace-angular
├── config                                              *
│   └── config.yml                                      * Default app config
├── cypress                                             * Folder for Cypress (https://cypress.io/) / e2e tests
│   ├── downloads                                       *
│   ├── fixtures                                        * Folder for e2e/integration test files
│   ├── integration                                     * Folder for any fixtures needed by e2e tests
│   ├── plugins                                         * Folder for Cypress plugins (if any)
│   ├── support                                         * Folder for global e2e test actions/commands (run for all tests)
│   └── tsconfig.json                                   * TypeScript configuration file for e2e tests
├── docker                                              * See docker/README.md for details
│   ├── cli.assetstore.yml                              *
│   ├── cli.ingest.yml                                  *
│   ├── cli.yml                                         *
│   ├── db.entities.yml                                 *
│   ├── docker-compose-ci.yml                           *
│   ├── docker-compose-rest.yml                         *
│   ├── docker-compose.yml                              *
│   └── README.md                                       *
├── docs                                                * Folder for documentation
│   └── Configuration.md                                * Configuration documentation
├── scripts                                             *
│   ├── merge-i18n-files.ts                             *
│   ├── serve.ts                                        *
│   ├── sync-i18n-files.ts                              *
│   └── test-rest.ts                                    *
├── src                                                 * The source of the application
│   ├── app                                             * The source code of the application, subdivided by module/page.
│   ├── assets                                          * Folder for static resources
│   │   ├── fonts                                       * Folder for fonts
│   │   ├── i18n                                        * Folder for i18n translations
│   │   └── images                                      * Folder for images
│   ├── backend                                         * Folder containing a mock of the REST API, hosted by the express server
│   ├── config                                          *
│   ├── environments                                    *
│   │   ├── environment.production.ts                   * Production configuration files
│   │   ├── environment.test.ts                         * Test configuration files
│   │   └── environment.ts                              * Default (development) configuration files
│   ├── mirador-viewer                                  *
│   ├── modules                                         *
│   ├── ngx-translate-loaders                           *
│   ├── styles                                          * Folder containing global styles
│   ├── themes                                          * Folder containing available themes
│   │   ├── custom                                      * Template folder for creating a custom theme
│   │   └── dspace                                      * Default 'dspace' theme
│   ├── index.csr.html                                  * The index file for client side rendering fallback
│   ├── index.html                                      * The index file
│   ├── main.browser.ts                                 * The bootstrap file for the client
│   ├── main.server.ts                                  * The express (http://expressjs.com/) config and bootstrap file for the server
│   ├── polyfills.ts                                    *
│   ├── robots.txt                                      * The robots.txt file
│   ├── test.ts                                         *
│   └── typings.d.ts                                    *
├── webpack                                             *
│   ├── helpers.ts                                      * Webpack helpers
│   ├── webpack.browser.ts                              * Webpack (https://webpack.github.io/) config for browser build
│   ├── webpack.common.ts                               * Webpack (https://webpack.github.io/) common build config
│   ├── webpack.mirador.config.ts                       * Webpack (https://webpack.github.io/) config for mirador config build
│   ├── webpack.prod.ts                                 * Webpack (https://webpack.github.io/) config for prod build
│   └── webpack.test.ts                                 * Webpack (https://webpack.github.io/) config for test build
├── angular.json                                        * Angular CLI (https://angular.io/cli) configuration
├── cypress.json                                        * Cypress Test (https://www.cypress.io/) configuration
├── Dockerfile                                          *
├── karma.conf.js                                       * Karma configuration file for Unit Test
├── LICENSE                                             *
├── LICENSES_THIRD_PARTY                                *
├── nodemon.json                                        * Nodemon (https://nodemon.io/) configuration
├── package.json                                        * This file describes the npm package for this project, its dependencies, scripts, etc.
├── postcss.config.js                                   * PostCSS (http://postcss.org/) configuration
├── README.md                                           * This document
├── SECURITY.md                                         *
├── server.ts                                           * Angular Universal Node.js Express server
├── tsconfig.app.json                                   * TypeScript config for browser (app)
├── tsconfig.json                                       * TypeScript common config
├── tsconfig.server.json                                * TypeScript config for server
├── tsconfig.spec.json                                  * TypeScript config for tests
├── tsconfig.ts-node.json                               * TypeScript config for using ts-node directly
├── tslint.json                                         * TSLint (https://palantir.github.io/tslint/) configuration
├── typedoc.json                                        * TYPEDOC configuration
└── yarn.lock                                           * Yarn lockfile (https://yarnpkg.com/en/docs/yarn-lock)

Managing Dependencies (via yarn)

This project makes use of yarn to ensure that the exact same dependency versions are used every time you install it.

  • yarn creates a yarn.lock to track those versions. That file is updated automatically by whenever dependencies are added/updated/removed via yarn.
  • Adding new dependencies: To install/add a new dependency (third party library), use yarn add. For example: yarn add some-lib.
    • If you are adding a new build tool dependency (to devDependencies), use yarn add some-lib --dev
  • Upgrading existing dependencies: To upgrade existing dependencies, you can use yarn upgrade. For example: yarn upgrade some-lib or yarn upgrade some-lib@version
  • Removing dependencies: If a dependency is no longer needed, or replaced, use yarn remove to remove it.

As you can see above, using yarn commandline tools means that you should never need to modify the package.json manually. We recommend always using yarn to keep dependencies updated / in sync.

Adding Typings for libraries

If the library does not include typings, you can install them using yarn:

yarn add d3
yarn add @types/d3 --dev

If the library doesn't have typings available at @types/, you can still use it by manually adding typings for it:

  1. In src/typings.d.ts, add the following code:

      declare module 'typeless-package';
  2. Then, in the component or file that uses the library, add the following code:

      import * as typelessPackage from 'typeless-package';
      typelessPackage.method();

Done. Note: you might need or find useful to define more typings for the library that you're trying to use.

If you're importing a module that uses CommonJS you need to import as

import * as _ from 'lodash';

Frequently asked questions

  • Why is my service, aka provider, is not injecting a parameter correctly?
    • Please use @Injectable() for your service for typescript to correctly attach the metadata
  • Where do I write my tests?
    • You can write your tests next to your component files. e.g. for src/app/home/home.component.ts call it src/app/home/home.component.spec.ts
  • How do I start the app when I get EACCES and EADDRINUSE errors?
    • The EADDRINUSE error means the port 4000 is currently being used and EACCES is lack of permission to build files to ./dist/
  • What are the naming conventions for Angular?
  • Why is the size of my app larger in development?
    • The production build uses a whole host of techniques (ahead-of-time compilation, rollup to remove unreachable code, minification, etc.) to reduce the size, that aren't used during development in the intrest of build speed.
  • node-pre-gyp ERR in yarn install (Windows)
    • install Python x86 version between 2.5 and 3.0 on windows. See this issue
  • How do I handle merge conflicts in yarn.lock?
    • first check out the yarn.lock file from the branch you're merging in to yours: e.g. git checkout --theirs yarn.lock
    • now run yarn install again. Yarn will create a new lockfile that contains both sets of changes.
    • then run git add yarn.lock to stage the lockfile for commit
    • and git commit to conclude the merge

Getting Help

DSpace provides public mailing lists where you can post questions or raise topics for discussion. We welcome everyone to participate in these lists:

Great Q&A is also available under the DSpace tag on Stackoverflow

Additional support options are at https://wiki.lyrasis.org/display/DSPACE/Support

DSpace also has an active service provider network. If you'd rather hire a service provider to install, upgrade, customize or host DSpace, then we recommend getting in touch with one of our Registered Service Providers.

Issue Tracker

DSpace uses GitHub to track issues:

License

DSpace source code is freely available under a standard BSD 3-Clause license. The full license is available in the LICENSE file or online at http://www.dspace.org/license/

DSpace uses third-party libraries which may be distributed under different licenses. Those licenses are listed in the LICENSES_THIRD_PARTY file.

dspace-angular's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dspace-angular's Issues

Add npm scripts to start in production mode with AoT

npm run build:prod:ngc:json will build the project for production.

node dist/server/index.js will start the app in production.

"start:prod:node": "node dist/server/index.js",
"start:prod": "npm run build:prod:ngc:json && npm run start:prod:node",

this could work and npm run start:prod will build and start production.

Include tslint in webpack build

Tslint and codelyzer were added to the project, but currently you have to manually run them.
There's probably a webpack loader to run them every time webpack builds. We should add that

Refactor existing code to match Module style guide

The style guide has been updated with recommendations about how to use modules: https://angular.io/styleguide#!#04-09

  • The recommendation is now to create a separate module for each feature
    • The main reasons are because it creates better separation of concerns
    • makes it easier to lazy load them
    • makes it easier to test
  • They also recommend a SharedModule
    • that should contain components and pipes that are used all over the application
    • we already have this, but it also contains services, and the recommendation is now to add services to a different globally shared module:
  • And a CoreModule
    • that should contain Singletons that need to be shared throughout the application -> services
    • The module helps to ensure all your services are actually singletons. They should be added to the provider's list of only the CoreModule, and not anywhere else
    • It should also contain other single use components, that are only used in the appComponent. a sidebar-component or a notification component would be examples of those
    • We don't have a CoreModule yet
    • Note that not every service needs to be in this module, if it's only need across a subset of the app, move it up to the first module that encompasses them all, not further

Refactor the current code to fit this structure.

Create models for Collections, Items and Bitstreams

Also create an interface or class to represent a DSpaceObject. All models should implement it or inherit from it.

Keep in mind that the Collection model should represent both Communities and Collections in the DSpace backend

You can take a look at the REST API Contract on the wiki, but at the time of writing it far enough advanced yet to be more than a rough guideline

Footer component

Create a component for the footer. Take a look at the prototype for an example. Note that for the prototype it was part of the AppComponent and never refactored in to its own component.

Use the same content as the prototype

Automatically set the end-year in the copyright message to the current year. That way people don't need to remember to update that i18n message every year. Angular's built-in DatePipe could be useful for this

Make it stick to the bottom using flexbox.

As it is a single-use component that is only referenced in AppComponent's template, it belongs in the CoreModule. Create that module if it doesn't exist yet.

Full Item View Page

Add a component for the full Item view page
Its route should be /items/:id/full

It should contain a table that lists the key, value and language for all the Item's metadata fields, sorted alphabetically by key
Use bootstrap's responsive table styles to make the table responsive for now, we may replace it with something a little more useable on smaller screens later

It should also contain a file section that shows the following fields for each bitstream in the ORIGINAL and LICENSE bundles

  • thumbnail: reuse the component from the simple item view page
  • name
  • size: reuse the pipe from the simple item view page
  • format
  • description
  • a download link

It should also contain a list of the collections the item is a direct descendant of, with a link and their short description.

Pagination component

We need a way to handle pagination that can be shared between components.

  • It should make use of the ng-bootstrap pagination component for the pager.
  • it should be possible to set the number of results per page - in the style of discovery seems fine - a gear with a dropdown
  • the page number, and the number of results per page should be reflected in the URL: if you share the URL to a page with a pageable component it should take you to the exact same place.
  • However I can imagine we'll have pages with multiple pageable lists. adding an optional identifier to these URL params is a possible solution
  • It should be easy to use as part of another component
  • In the prototype we had to add a bunch of properties to the models themselves to get information about the pagination to the components using it. It would be great if that wasn't necessary this time.
  • An interesting project to take a look at is ng2-pagination, if not to use it directly (at the time of writing there are open issues about angular universal and rollup) then at least to borrow a few ideas from

i18n: add ng2-translate

  • add ng2-translate to the project
  • ensure it works on both server and client (that needed a custom provider in the prototype if I'm not mistaken)
  • create an english translations file
  • move any untranslated labels currently in the UI to this file

fsevents error with shrinkwrap on Windows 10

When I launch npm install on Windows 10 I'm getting this error

npm WARN [email protected] No license field.
npm ERR! Windows_NT 10.0.14393
npm ERR! argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install"
npm ERR! node v6.9.2
npm ERR! npm  v3.10.9
npm ERR! code EBADPLATFORM

npm ERR! notsup Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm ERR! notsup Valid OS:    darwin
npm ERR! notsup Valid Arch:  any
npm ERR! notsup Actual OS:   win32
npm ERR! notsup Actual Arch: x64

I've seen that the problem doesn't occurs if the following lines are removed from npm-shrinkwrap.json :

    "fsevents": {
      "version": "1.0.17",
      "from": "fsevents@>=1.0.0 <2.0.0",
      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.0.17.tgz",
      "dev": true,
      "optional": true,
      "dependencies": {...}
    },

Replace NPM with Yarn

We should consider looking at yarn: an alternative package manager for node, designed to solve these dependency problems in a better way.

  • It’s also supposed to be 3 to 5 times faster than npm
  • Yarn is open-source, and a collaboration between facebook, google and tilde
    • in other words the people behind react, angular and ember.
  • A lot of projects have started to adopt it lately. angular-cli is one of them.
  • It works in much the same way as npm
    • uses package.json with the same syntax
    • it creates the same node_modules folder
  • It uses something like npm-shrinkwrap by default, but it’s supposed to be more reliable.
  • Since yarn projects are also valid npm projects, we can decide to switch back if the yarn should be discontinued in the future.

Add postcss and autoprefixer

postcss allows us to add a number of plugins that perform actions on the css, after it has been converted by sass

The most important such plugin is autoprefixer. It allows you to write plain css without having to worry about browser specific prefixes. You specify in your autoprefixer config how many browser versions you want to support (e.g. 'last 2 versions') and autoprefixer does the rest.

Bootstrap 4 was written with autoprefixer in mind, so as we're converting bootstrap's sass to css ourselves we'll need to add autoprefixer as well.

The conversation in the PR that added bootstrap may be useful

Fresh Install on Windows throws response errors

Environment:

  • Windows 10
  • Node 6.10.1
  • NPM 3.10.10
  • Yarn 0.21.3

Steps to reproduce:

  • clone repo
  • yarn run global
  • yarn install
  • yarn start (or yarn watch)
  • Attempt to access http://localhost:3000 in browser

Th result is that the server immediately dies (browser displays "The connection was reset." error and nothing is displayed). Also, the following error occurs:

Listening on: http://:::3000
Error in SSR, serving for direct CSR e {
  _body:
   { Error: read ECONNRESET
       at exports._errnoException (util.js:1018:11)
       at TCP.onread (net.js:572:26) code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' },
  status: 200,
  ok: true,
  statusText: 'Ok',
  headers: t { _headers: Map {}, _normalizedNames: Map {} },
  type: 3,
  url: null }
EXCEPTION: Response with status: 200 Ok for URL: null

D:\programming\dspace-angular\node_modules\zone.js\dist\zone-node.js:158
                        throw error;
                        ^
Response with status: 200 Ok for URL: null
error Command failed with exit code 1.

This error seems to be the one noted here: ngx-translate/core#362

In that ticket, the suggestion is the move UniversalModule to load before TranslateModule.

I tried doing that in both our node.module.ts and browser.module.ts. This resolves the previously mentioned error, and results in the homepage loading successfully. However, on the backend, I now see a new error:

EXCEPTION: This method is not implemented in Parse5DomAdapter: getCookie
ORIGINAL STACKTRACE:
Error: This method is not implemented in Parse5DomAdapter: getCookie
    at r (D:\programming\dspace-angular\dist\server\index.js:32:15014)
    at e.getCookie (D:\programming\dspace-angular\dist\server\index.js:32:28322)
    at t.configureRequest (D:\programming\dspace-angular\dist\server\index.js:16:2330)
    at t.createConnection (D:\programming\dspace-angular\dist\server\index.js:16:2574)
    at r (D:\programming\dspace-angular\dist\server\index.js:16:2815)
    at t.request (D:\programming\dspace-angular\dist\server\index.js:16:3718)
    at t.get (D:\programming\dspace-angular\dist\server\index.js:16:3789)
    at t.getTranslation (D:\programming\dspace-angular\dist\server\index.js:4:6657)
    at t.getTranslation (D:\programming\dspace-angular\dist\server\index.js:4:7496)
    at t.use (D:\programming\dspace-angular\dist\server\index.js:4:7207)
Error: This method is not implemented in Parse5DomAdapter: getCookie
    at r (D:\programming\dspace-angular\dist\server\index.js:32:15014)
    at e.getCookie (D:\programming\dspace-angular\dist\server\index.js:32:28322)
    at t.configureRequest (D:\programming\dspace-angular\dist\server\index.js:16:2330)
    at t.createConnection (D:\programming\dspace-angular\dist\server\index.js:16:2574)
    at r (D:\programming\dspace-angular\dist\server\index.js:16:2815)
    at t.request (D:\programming\dspace-angular\dist\server\index.js:16:3718)
    at t.get (D:\programming\dspace-angular\dist\server\index.js:16:3789)
    at t.getTranslation (D:\programming\dspace-angular\dist\server\index.js:4:6657)
    at t.getTranslation (D:\programming\dspace-angular\dist\server\index.js:4:7496)
    at t.use (D:\programming\dspace-angular\dist\server\index.js:4:7207)

This new error seems to be detailed here: angular/universal-starter#167 and the suggestion in that ticket is the list UniversalModule last (which is the opposite of the previous suggestion which said it needs to be listed before TranslateModule).

Use OpaqueToken for injecting global configurations

https://angular.io/docs/ts/latest/api/core/index/OpaqueToken-class.html

The global config should be provided and injected where needed.

example

import { OpaqueToken } from '@angular/core';

export interface GlobalConfig {
  API: string
}

export const DEFAULT_GLOBAL_CONFIG: GlobalConfig = {
  API: 'http://localhost/dspace-api'
};

export let GLOBAL_CONFIG = new OpaqueToken('config');

Then provide it in the browser and node module

 providers: [
    { provide: GLOBAL_CONFIG, useValue: DEFAULT_GLOBAL_CONFIG },
    ...

There will have to be adjustments to allow for configurable environment based config. Such as development, production, and test. The configurations could be in separate files and the build can decide which to provide.

Have all asynchronous requests cached using Universal Cache to support SEO

The application runs XHR requests on the server & once again on the Client-side (when the application bootstraps)
Use a UniversalCache instead of regular Http, to save certain requests so they aren't re-ran again on the Client. (Example useage here)

https://github.com/angular/universal-starter

With redux storing a centralized state, it seems that all asynchronous requests should be put into the store and that put into Universal Cache.

Add an npm script to install global dependencies

Some npm scripts won't work unless certain dependencies are installed globally. webpack-bundle-size-analyzer is one such example. We need to identify the others, and add an npm script to install them.

Configuration isn't integrated in a useful way

The configuration UI URL is not used within the server.ts and server.aot.ts. The node express engine binds to the port and address. It should get the values from a configuration file.

The production and development builds and tests are not dictating what environment configuration to use.

Cache time to live isn't setting anything in the server or client side cache. server.ts and server.aot.ts sets the Cache-Control per request but does not reference a configuration.

Whether or not to preboot is a property of the ngApp response. I do not see any reason to ever prevent the browser from rehydrating the universal cache set during pre-render on the server side node. For this to even make since it would have to condition on the configuration everywhere in the code where an asynchronous response is put into the universal cache.

Also, the process to get the environment configuration seems a bit more complex then necessary.

Switch angular-cli with universal-cli

"Universal-CLI is fork from Angular-CLI. It supports Angular Universal (with --universal flag after ung new or ung init), see Support for server side rendering for detail. It is a separate package because the Core-CLI team is not able to maintain non-core functionality."

https://github.com/devCrossNet/universal-cli#usage

"Universal-CLI is fork from Angular-CLI. It is a separate package because the Core-CLI team is not able to maintain non-core functionality."

https://github.com/angular/universal

This switch will impact many aspects of the build process, including sass, tree-shaking, tests, etc.

We probably want to wait for Angular Universal to be merged into Angular. At that time there will be many dependency upgrades and will be able to switch the build process with less changes after the upgrades.

Add bootstrap

  • include the ng-bootstrap module in the project
  • Include the sass version of bootstrap 4 separately if that's required
  • Ensure there is a global styles file that affects everything on the page (as opposed to scoped component styles)
    • This should be something that can be used by an institution to tweak or add additional css without having to touch the component styles
  • Ensure there is a way for bootstrap's stylesheets and variables to be imported in component styles.

Upgrade to Angular 4

Angular 4 has been released.

A little background info: Angular 3 never existed, and the step from Angular 2 to 4 is a lot smaller than the step from 1 to 2 was. It's comparable DSpace 3 in that regard. You can find the reasoning behind the change here

This blogpost gives an overview of what's new, and how to migrate.

In our case migration won't be quite as simple as it is explained in that blogpost, because of Universal. Angular Universal used to be a separate project, but is included in Angular 4 now, so our dependencies and likely also a lot of the universal specific files (server.ts, node.module.ts, browser.module.ts, …) will need to change.

Universal starter, the boilerplate project we started from, has an open issue to migrate to 4: angular/universal-starter#376

@types/lodash version higher than 4.14.50 causes build errors

lodash is a transitive dependency of this project. The latest versions are no longer compatible with TypeScript versions < 2.1. At the moment this project uses TypeScript 2.0.10.

The build errors you get as a consequence look like this:

    ERROR in [default] /Users/art/tmp/dspace-angular/node_modules/@types/lodash/index.d.ts:244:12
    Duplicate identifier '_'.

    ERROR in [default] /Users/art/tmp/dspace-angular/node_modules/@types/lodash/index.d.ts:244:15
    Cannot find namespace '_'.

    ERROR in [default] /Users/art/tmp/dspace-angular/node_modules/@types/lodash/index.d.ts:246:24
    Cannot find name 'Partial'.

    ERROR in [default] /Users/art/tmp/dspace-angular/node_modules/@types/lodash/index.d.ts:248:18
    Duplicate identifier '_'.

    ERROR in [default] /Users/art/tmp/dspace-angular/node_modules/@types/lodash/index.d.ts:366:38
    Cannot find namespace '_'.
…

Using npm-shrinkwrap should prevent this problem for now.

If you add a new dependency and have to recreate npm-shrinkwrap.json you may run in to this again. If that dependency doesn't depend on @types/lodash > 4.15.50 but uses a range, you can safely set the @types/lodash version back to 4.15.50 in npm-shrinkwrap.json manually.

After adding a certain number of tests you get an exception

I ran in to this issue while writing tests for my reducers. I tried to reproduce in as simple a way as possible in this test branch

What happens is: if there are more than 16 tests in my spec file I get the following exception:

ERROR: 'Unhandled Promise rejection:', 'Cannot create the component AppComponent as it was not imported into the testing module!', '; Zone:', 'ProxyZone', '; Task:', 'Promise.then', '; Value:', Error{}, 'Error: Cannot create the component AppComponent as it was not imported into the testing module!
    at TestBed.createComponent (http://localhost:9876/base/spec-bundle.js?274b278a2430fa736a07be440401dc19db37e718:13936:23)
    at Function.TestBed.createComponent (http://localhost:9876/base/spec-bundle.js?274b278a2430fa736a07be440401dc19db37e718:13763:33)
    at http://localhost:9876/base/spec-bundle.js?274b278a2430fa736a07be440401dc19db37e718:83501:41
    at ZoneDelegate.invoke (http://localhost:9876/base/spec-bundle.js?274b278a2430fa736a07be440401dc19db37e718:53551:26)
    at ProxyZoneSpec.onInvoke (http://localhost:9876/base/spec-bundle.js?274b278a2430fa736a07be440401dc19db37e718:53215:39)
    at ZoneDelegate.invoke (http://localhost:9876/base/spec-bundle.js?274b278a2430fa736a07be440401dc19db37e718:53550:32)
    at Zone.run (http://localhost:9876/base/spec-bundle.js?274b278a2430fa736a07be440401dc19db37e718:53433:43)
    at http://localhost:9876/base/spec-bundle.js?274b278a2430fa736a07be440401dc19db37e718:53821:57
    at ZoneDelegate.invokeTask (http://localhost:9876/base/spec-bundle.js?274b278a2430fa736a07be440401dc19db37e718:53584:35)
    at ProxyZoneSpec.onInvokeTask (http://localhost:9876/base/spec-bundle.js?274b278a2430fa736a07be440401dc19db37e718:53239:39)
    at ZoneDelegate.invokeTask (http://localhost:9876/base/spec-bundle.js?274b278a2430fa736a07be440401dc19db37e718:53583:40)
    at Zone.runTask (http://localhost:9876/base/spec-bundle.js?274b278a2430fa736a07be440401dc19db37e718:53473:47)
    at drainMicroTaskQueue (http://localhost:9876/base/spec-bundle.js?274b278a2430fa736a07be440401dc19db37e718:53720:35)'

The tests I added are trivial and don't use any part of angular, so they shouldn't need AppComponent for anything. If there are fewer tests, everything works fine.

This also happens when you spread the tests out over multiple files, as you can see in this commit

I think this is a bug, but there could also be something wrong with my approach, as my experience with testing angular apps is limited.

Switch to ngrx platform

The next version of ngrx will combine their most commonly used separate modules in to a single module: platform. It will bring their versions in sync with Angular's. It hasn't been released yet.

There will be a few breaking changes. Nothing problematic for us at first sight. Here is the migration guide

Implement services to interact with the REST API

This task depends on #30

  • For the Collections, Items and Bitstreams endpoints, create a service, a reducer an actions and an effects file
  • each service should have
    • a findById method
    • a findAll method, that supports pagination and sorting
    • a findAllInScope method, and supports pagination and sorting
  • when a find method is called, dispatch the appropriate FIND_REQUEST action (e.g. dspace/shared/data/item/FIND_BY_ID_REQUEST)
  • in the corresponding effects file, listen for that FIND_REQUEST action
    • when it arrives, call the appropriate endpoint using ApiService
    • If the call succeeds, use a JSONAPISerializer to deserialize the result, and dispatch the appropriate FIND_SUCCESS action that adds the object(s) to the store
    • If the response is an error, or times out, dispatch the appropriate FIND_ERROR action with an error message.
  • The find methods should return observables that select the proper values from the store
  • You can find a simplified example of this way of working in this test branch
  • Don't worry about caching at the moment, that's part of a separate task.

Write a JSONAPISerializer

  • Write a JSONAPISerializer based on yayson.
  • use generics to specify the type of model it's working with (Collections, Items, …)
  • add a deserialize method: this will get the response body from the REST API as input and return a single model of the generic type
    • Don't use yayson's store as a cache, it doesn't have all the features we need and it doesn't use ngrx. Instead create a new store for every new deserialize operation.
  • add a deserizalizeArray method: that will do the same thing, but for an array (e.g. a GET call to /api/collections/)
  • add a serialize method: this will turn a single model of the generic type in to a JSON API object to be sent to the REST API.
  • add a serializeArray method: this will turn an array of models of the generic type in to a JSON API object to be sent to the REST API.
  • instead of making separate methods for a single object and an array, you could also consider using TypeScript's union types to work with either a single object or an array in the same method.
  • To start with every endpoint can use the same serializer, we can extend it (and make e.g. an ItemSerializer) if exceptions need to be made for an endpoint
  • The docs for yayson aren't great. It may help to take a look at the tests on DefinitelyTyped
  • I also have a test-branch, that uses yayson to parse a list of collections.

Collection home page

Add a collection home page
Their route should be/collections/:id
The component should show the following fields if they exist:

  • title
  • logo
  • introductory text (html)
  • news (html - also referred to as sidebarText)
  • copyright text (html)
  • license

Create a smart component at the root that connects to the CollectionDataService to fetch the data,
Use small dumb components (i.e. a component that gets all its information through inputs rather than services) for each of the fields.
Ensure the html fields get rendered as html.

For adaptability's sake, it would be best if you'd take the approach of the simple-item-view component in the prototype, where you create a single wrapping component to render a section of the page, and then a specific component that makes use of the wrapping component, for each field on the page.
That way, if an institution using this UI later on, wants to customize the way e.g. news is rendered, they only need to touch the news component and nothing else. The wrapping component ensures that you can still re-use as much code as possible.

For the layout, I'd say base yourself on the prototype, rather than the current DSpace UIs

Add caching

This task depends on #31

  • Each Data service created in #31 should have a cache.
  • users of the data services (meaning components, other services, …) shouldn't need to know about the cache. They should just go on working the same way (with the same observables) as if the data came from the REST API.
  • This cache should store its data in the ngrx store
  • It should be implemented in such a way that most code can be shared between data services for different endpoints
  • But it should be possible to determine separate time-to-live for each endpoint. For some endpoints it may be necessary to disable the cache altogether
  • It should also be possible to combine partial objects:
    • e.g. I first get only a collection's id, name and handle from the REST API, for a certain page
    • next I go to another page and I get that same collection's id and shortDescription from the REST API, but not it's name or handle
    • the store should now contain the collection's name, handle and shortDescription

LoadingService

Create a service to track everything that is loading.

It should have a track method that takes an Observable<boolean>

It should offer an isLoading Observable<boolean> that is true when any its tracked Observables are true, false otherwise. CombineLatest is probably useful here

Afterwards, Components that are waiting for something to load should register an Observable with the LoadingService.
e.g. this.loadingService.track(this.remoteData.isLoading)

Question: should components be stateless?

Using redux means the application state is stored in only one place.
This means to me that components should not introduce their own state variables, but rather access the state via functions.

State variables add unnecessary complexity. They can get out of sync if they aren't managed properly - which is exactly what redux wants to avoid. With functions you're always sure to get the current state.

To illustrate what I mean I made a commit where I "fix" the header component.

antoine-atmire@1e9550d

Ease UI translation (i18n) process

This is a placeholder ticket for future work on internationalization (i18n) for the Angular UI. Others are encouraged to add comments to this ticket on other ways to improve the translation process for the new UI.

Currently, we are using ngx-translate as our internationalization library. This uses JSON formatted translation files by default.

To simplify the translation process (for non-technical users) we may wish to use a more standard translation file format, e.g. .po which can be used with Poedit.net. Ngx-translate already has at least to one sample po-loader.

Simple Item View Page

Add a component for the simple Item view page
Its route should be /items/:id

For adaptability's sake, it would be best if you take inspiration from the simple-item-view component in the prototype, where you create a single wrapping component to render a section of the page, and then a specific component that makes use of the wrapping component, for each field on the page.

You could even take it a little further than the prototype, and have a sub-component to render a generic metadata-field. It takes a list of Metadatum objects as input and can have some basic configuration options that are usable for any metadata field.
e.g. by default multiple values could be separated by a line break, but if you pass in an optional separator as a component input, it is used instead
<ds-item-page-field data="item.filterMetadata('dc.contributor.author')" separator=";">…</ds-item-page-field>

The contents of the specific author component could simply look like the above example: all it does is configure the generic item-page-field component.

The reason for still creating a dedicated author component instead of configuring the generic component in the main item-page component is customizability; if an institution using this UI later on, wants to customize the way the authors is rendered, they only need to touch the author component and not the item-page component itself.

The root component should fetch the data from ItemDataService, the sub-components should be "dumb" components that get their information through component inputs rather than services.

The simple item view page should show the following fields if they exist.

  • dc.title as the page header

  • A thumbnail

    • The thumbnail component shouldn't be tied to the item page, it should be able to be reused in search results for example. So put it in the SharedModule.
    • Assume for now this is bitstream.thumbnail: Bitstream, for the primary bitstream in the ORIGINAL bundle. In older DSpaces the logic for deciding which file to use as thumbnail was part of the theme, I'd like to move that to the REST API if at all possible.
    • If there is no thumbnail, use a placeholder instead.
  • The file section

    • with download links and filesizes (in IEC values A pipe for #this in the SharedModule would be useful as we're sure to need it elsewhere) everything in the ORIGINAL and LICENCE bundles
  • The date:

    • dc.date.issued
  • The authors

    • dc.contributor.author
    • dc.creator
    • dc.contributor
  • The abstract

    • dc.description.abstract
  • The URI

    • dc.identifier.uri
  • The collections the item is a direct descendant of, as links

If the current mock data doesn't contain a value for any of these metadata fields, feel free to add it.

Add typedoc config and comment initial code

We need to get typedocs setup and make sure we keep up on comments.

Here is a basic typedoc.json

{
  "mode": "modules",
  "out": "doc",
  "theme": "default",
  "ignoreCompilerErrors": "true",
  "experimentalDecorators": "true",
  "emitDecoratorMetadata": "true",
  "target": "ES5",
  "moduleResolution": "node",
  "preserveConstEnums": "true",
  "stripInternal": "true",
  "suppressExcessPropertyErrors": "true",
  "suppressImplicitAnyIndexErrors": "true",
  "module": "commonjs"
}

We should probably have a npm script to generate typedocs.

Warnings about usage of `eval` when running `yarn start`

Environment: Windows 10, Yarn 0.21.3, Node 6.10.1, npm 3.10.10

After running yarn start, I see the following in the output (just before yarn run server is triggered, near the end)

$ rollup -c rollup-server.js && rollup -c rollup-client.js
Use of `eval` (in D:\programming\dspace-angular\dist\server\index.js) is strongly discouraged, as it poses security risks and may cause
issues with minification. See https://github.com/rollup/rollup/wiki/Troubleshooting#avoiding-eval for more details
Use of `eval` (in D:\programming\dspace-angular\dist\client\main.bundle.js) is strongly discouraged, as it poses security risks and may
cause issues with minification. See https://github.com/rollup/rollup/wiki/Troubleshooting#avoiding-eval for more details

The warnings link over to this message from rollup: https://github.com/rollup/rollup/wiki/Troubleshooting#avoiding-eval

However, as I don't see any usages of eval in our codebase, it's unclear where it is being pulled in from. Nonetheless, it seems like we should have a ticket to track this.

Create a spinner component & service

In order to show when a page is loading

I'm thinking of something like this:

  • Create a router-outlet-with-spinner component, that replaces the app.component's router-outlet
  • Also create a SpinnerService, that stores whether or not the spinner should be active in the ngrx store, has a few methods to change the active state, and to observe it.
  • in the router-outlet-with-spinner component, if the service says the spinner should be active, show a spinner component, otherwise show the router-outlet
  • Each component that corresponds to a route can set the SpinnerService to active in its constructor, and subscribe to (the combination of) its observables-that-take-time-to-resolve to disable it again.
  • Use either a pure css, or svg spinner. Use (a calculation with) bootstrap variables for its color and dimensions. e.g.$spinner-height: 4*$line-height-base;

Run all tests at once

It would be useful to be able to run all tests at once using a single command. For example to use in Travis CI. However it should still be possible to run them separately during development.

I would also create a pree2e script that triggers webdriver:update to ensure protractor doesn't fail because webdriver:update hasn't run.

Use npm shrinkwrap

shrinkwrap is a tool built in to npm that creates a json file with the versions of all dependencies, and their dependencies, currently installed.

You add this file to git, and all subsequent npm installs will use those exact versions of dependencies, instead of the latest version in each range.

This can help ensure that everyone is working with the exact same set of pacakges, and that no issues can arise simply because a new version of a package we depend on was released.

The downside is that after you install add a new dependency to package.json, you have to run npm shrinkwrap again. If you're not adding new dependencies nothing changes

Build error on Windows 10

When running build locally on Windows 10 postcss script generates a command not found error.
It works properly on Unix like OS.

It's possible to solve it adding node command to the script.

Add and configure test tools

We agreed on using:

  • jasmine for unit tests
  • protractor for e2e tests
  • karma as a test runner

These tools need to be added to the project and configured.

We'll also need some documentation added to the wiki on how to use them (e.g. create a my.component.spec file in the same directory as the component for jasmine, put your e2e tests in that folder, that sort of thing…)

Test JSData

JSData looks like a promising way to make it easy for us to parse JSON API responses, keeping relations intact, work with partial responses, and have caching.

We need to test if it works well with Universal and ngrx before we can commit on using it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.