├── .editorconfig
├── .gitignore
├── .npmignore
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── angular.json
├── docs
├── Makefile
├── advanced.rst
├── anim.gif
├── basic-usage.rst
├── conf.py
├── deployment.rst
├── development.rst
├── index.rst
├── make.bat
├── principles.rst
├── reference
│ ├── components.rst
│ ├── directives.rst
│ ├── index.rst
│ ├── services.rst
│ ├── traversal.rst
│ └── views.rst
└── setup.rst
├── mrs.developer.json
├── package-lock.json
├── package.json
├── projects
└── plone-restapi-angular
│ ├── README.md
│ ├── ng-package.json
│ ├── package.json
│ ├── src
│ ├── lib
│ │ ├── components
│ │ │ ├── breadcrumbs.spec.ts
│ │ │ ├── breadcrumbs.ts
│ │ │ ├── comments.spec.ts
│ │ │ ├── comments.ts
│ │ │ ├── global.navigation.spec.ts
│ │ │ ├── global.navigation.ts
│ │ │ ├── navigation.level.ts
│ │ │ ├── navigation.ts
│ │ │ └── workflow.ts
│ │ ├── directives
│ │ │ ├── download.directive.spec.ts
│ │ │ └── download.directive.ts
│ │ ├── index.ts
│ │ ├── interfaces.ts
│ │ ├── module.ts
│ │ ├── services
│ │ │ ├── api.service.spec.ts
│ │ │ ├── api.service.ts
│ │ │ ├── authentication.service.spec.ts
│ │ │ ├── authentication.service.ts
│ │ │ ├── cache.service.spec.ts
│ │ │ ├── cache.service.ts
│ │ │ ├── comments.service.spec.ts
│ │ │ ├── comments.service.ts
│ │ │ ├── configuration.service.spec.ts
│ │ │ ├── configuration.service.ts
│ │ │ ├── index.ts
│ │ │ ├── loading.service.spec.ts
│ │ │ ├── loading.service.ts
│ │ │ ├── navigation.service.spec.ts
│ │ │ ├── navigation.service.ts
│ │ │ ├── resource.service.spec.ts
│ │ │ ├── resource.service.ts
│ │ │ └── services.ts
│ │ ├── traversal.spec.ts
│ │ ├── traversal.ts
│ │ ├── traversing.ts
│ │ ├── views
│ │ │ ├── add.ts
│ │ │ ├── edit.spec.ts
│ │ │ ├── edit.ts
│ │ │ ├── login.spec.ts
│ │ │ ├── login.ts
│ │ │ ├── password-reset.ts
│ │ │ ├── request-password-reset.ts
│ │ │ ├── search.spec.ts
│ │ │ ├── search.ts
│ │ │ ├── sitemap.ts
│ │ │ ├── view.spec.ts
│ │ │ └── view.ts
│ │ └── vocabularies.ts
│ └── public-api.ts
│ ├── tsconfig.lib.json
│ ├── tsconfig.spec.json
│ └── tslint.json
├── src
├── .browserslistrc
├── app
│ ├── app.component.css
│ ├── app.component.html
│ ├── app.component.spec.ts
│ ├── app.component.ts
│ ├── app.module.ts
│ ├── components
│ │ ├── search.html
│ │ └── search.ts
│ └── custom
│ │ ├── breadcrumbs.html
│ │ ├── index.ts
│ │ ├── navigation.html
│ │ └── view.html
├── assets
│ └── .gitkeep
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── favicon.ico
├── index.html
├── jestGlobalMocks.ts
├── main.ts
├── polyfills.ts
├── setupJest.ts
├── styles.css
├── tsconfig.app.json
├── tsconfig.spec.json
└── tslint.json
├── tsconfig.json
└── tslint.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 4
8 | end_of_line = lf
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.md]
13 | max_line_length = 0
14 | trim_trailing_whitespace = false
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /tmp
5 | dist/
6 | src/**/*.js
7 |
8 | # dependencies
9 | node_modules
10 |
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | *.launch
16 | .settings/
17 | .vscode/
18 |
19 | # misc
20 | /.sass-cache
21 | /connect.lock
22 | /coverage/*
23 | /libpeerconnection.log
24 | npm-debug.log
25 | testem.log
26 | /typings
27 |
28 | # e2e
29 | e2e/*.js
30 | e2e/*.map
31 |
32 | #System Files
33 | .DS_Store
34 | Thumbs.db
35 |
36 | # test sub-projects and demo
37 | /demo
38 | /src/develop
39 |
40 | /venv
41 | /docs/_build
42 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | *.ngFactory.ts
2 | /node_modules
3 | /src
4 | /tests
5 | /tmp
6 | /demo
7 |
8 | # IDEs and editors
9 | /.idea
10 | .project
11 | .classpath
12 | *.launch
13 | .settings/
14 | .editorconfig
15 | .vscode
16 |
17 | # misc
18 | /.sass-cache
19 | /connect.lock
20 | /coverage/*
21 | /libpeerconnection.log
22 | npm-debug.log
23 | testem.log
24 | /typings
25 | .travis.yml
26 | .npmignore
27 |
28 | # e2e
29 | /e2e/*.js
30 | /e2e/*.map
31 |
32 | #System Files
33 | .DS_Store
34 | Thumbs.db
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 12.4.0
4 | cache:
5 | directories:
6 | - node_modules
7 | dist: trusty
8 | install:
9 | - npm install
10 | - missdev --https
11 | script:
12 | - npm run test
13 | - npm run build
14 | notifications:
15 | email:
16 | - ebrehault@gmail.com, ramon.nb@gmail.com, thomas.desvenain@gmail.com
17 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 2.2.0 (Unreleased)
2 |
3 | - Change project structure to use ng cli [Mathilde Pellerin]
4 | - Remove rxjs-compat [Mathilde Pellerin]
5 | - Upgrade to angular 7.2 [Mathilde Pellerin and Eric Brehault]
6 |
7 | # 2.1.0 (Unreleased)
8 |
9 | ## New features
10 |
11 | - Json deserialize dexterity validation errors. [Thomas Desvenain]
12 | - add PUT method support [Eric Brehault]
13 | - support Guillotina registry [Eric Brehault]
14 | - support Guillotina delete endpoints [Eric Brehault]
15 | - support Guillotina addons endpoint [Eric Brehault]
16 | - support Guillotina sharing [Eric Brehault]
17 | - add pending status to Authentication [Eric Brehault]
18 | - support Guillotina behaviors [Eric Brehault]
19 | - support basic authentication [Eric Brehault]
20 |
21 | ## API
22 |
23 | - works with Angular 6 and RxJS 6 + rxjs-compat [Thomas Desvenain]
24 |
25 | ## Bug fixes
26 |
27 | - support backend running on same domain [Eric Brehault]
28 | - default to basic auth if no JWT [Eric Brehault]
29 | - clean basic auth on logout [Eric Brehault]
30 | - emit when not authorized [Eric Brehault]
31 | - export password views [Thomas Desvenain]
32 | - export Services object from root. [Thomas Desvenain]
33 | - angular-traversal is a peer dependency [Thomas Desvenain]
34 |
35 |
36 | # 2.0.0 (2018-05-07)
37 |
38 | ## BREAKING CHANGES
39 |
40 | - `login` method is now an observable.
41 | If you don't subscribe to it, request is not send.
42 |
43 | - `getUserInfo` method has been removed.
44 |
45 | - By default, patch request returns a 200 with full modified content representation.
46 | No effect with plone.restapi <= 1.0a25
47 |
48 | - Since angular2-schema-form dependency has been removed,
49 | edit forms are not anymore auto-generated by angular2-schema-form by default.
50 |
51 | - `review_state` is not a possible search *option* anymore. It is now a possible search criterion only.
52 |
53 |
54 | ## New features
55 |
56 | - Add plone-workflow component. [Thomas Desvenain]
57 |
58 | - We can set a comment on workflow transition. [Thomas Desvenain]
59 |
60 | - Add `workflow` method to get available transitions and history. [Thomas Desvenain]
61 |
62 | - Add `username` to isAuthenticated behavior subject. [Thomas Desvenain]
63 |
64 | - `login` method of `authentication` service now returns an observable. [Thomas Desvenain]
65 |
66 | - Normalized many error responses. Added unit tests on this. [Thomas Desvenain]
67 |
68 | - Add `vocabulary` method to retrieve zope vocabularies. [Thomas Desvenain]
69 |
70 | - We can configure request retries and auth token expiration delay. [Thomas Desvenain]
71 |
72 | - Add interface and helper for file field value upload. [Thomas Desvenain]
73 |
74 | - Compatibility with plone.restapi 1.0b1 and later: url has been renamed to @id on @navigation and @breadcrumb endpoints. Keep the url property on the NavLink interface to be backwards compatible. [Sune Wøller]
75 |
76 | ## Bug fixes
77 |
78 | - Dont fail in normalising urls if path is null [Sune Wøller]
79 |
80 | - Do not prefix url once it starts with http: or https:
81 |
82 | - url was missing from navlink interface. [Thomas Desvenain]
83 |
84 | - Fixed Date search criteria. [Thomas Desvenain]
85 |
86 | - Renamed Comment interface to CommentItem to prevent name collision with component.
87 |
88 | ## Refactor
89 |
90 | - All services injected are protected to ease overloading [Thomas Desvenain]
91 |
92 | - Remove dependency on angular2-schema-form. [Eric Brehault]
93 |
94 | - Add an edit view with angular2-schema-form on test app. [Thomas Desvenain]
95 |
96 |
97 | # 1.3.1 (2017-11-08)
98 |
99 | ## Bug fixes
100 |
101 | - Move from @components plone.restapi endpoint to @navigation and @breadcrumbs [Sune Brøndum Wøller]
102 |
103 | - More robust error handling [Thomas Desvenain]
104 |
105 | # 1.3.0 (2017-11-04)
106 |
107 | ## New features
108 |
109 | - New LoadingService to manage loading status.
110 | Global loading status is now robust on parallel requests.
111 | [Thomas Desvenain]
112 |
113 | - Angular 5 compliancy [Eric Bréhault]
114 |
115 | ## Bug fixes
116 |
117 | - Fixed password reset for browsers that does not have UrlSearchParams.
118 |
119 | ## Refactoring
120 |
121 | - All services are moved to a services subfolder.
122 |
123 | # 1.2.4 (2017-10-11)
124 |
125 | ## New features
126 |
127 | - New download directive attribute [Thomas Desvenain]
128 |
129 | ## Bug fixes
130 |
131 | - Fix missing active links in global navigation, bug introduced in 1.2.0 [Sune Brøndum Wøller]
132 | - Improve test project set up [Sune Brøndum Wøller]
133 |
134 | # 1.2.3 (2017-09-29)
135 |
136 | ## Bug fixes
137 |
138 | - fix error handling
139 |
140 | # 1.2.2 (2017-09-29)
141 |
142 | ## Bug fixes
143 |
144 | - fix error handling
145 |
146 | # 1.2.1 (2017-09-29)
147 |
148 | ## Bug fixes
149 |
150 | - restore peerDependencies instead of dependencies to avoid compilation issues
151 |
152 | # 1.2.0 (2017-09-29)
153 |
154 | ## New features
155 |
156 | - Proper interfaces instead of any types [Thomas Desvenain]
157 | - Password reset feature [Thomas Desvenain]
158 | - Make local and global nav reactive [Thomas Desvenain]
159 | - Migrate to @angular/common/http [Fulvio Casali]
160 | - Cache management [Thomas Desvenain]
161 |
162 | # 1.1.0 (2017-09-12)
163 |
164 | ## New features
165 |
166 | - api.download() allows the user to access a file from the backend via a local blob
167 |
168 | ## Bug fixes
169 |
170 | - Fix api call for workflow transition
171 |
172 | # 1.0.1 (2017-09-08)
173 |
174 | ## New features
175 |
176 | - Support local URLs for backend
177 |
178 | # 1.0.0-alpha.28 (2017-08-03)
179 |
180 | ## New features
181 |
182 | - Allow to use Plone REST API expansion (provided by 1.0a19).
183 |
184 | # 1.0.0-alpha.27 (2017-07-06)
185 |
186 | ## Breaking changes
187 |
188 | - Inject all services in a single service for all the components.
189 |
190 | ## New features
191 |
192 | - Scroll to top after traversing.
193 | - Display subcontents in default view.
194 |
195 | # 1.0.0-alpha.26 (2017-06-30)
196 |
197 | ## Bug fixes
198 |
199 | - Fix navigation request parameter
200 |
201 | # 1.0.0-alpha.25 (2017-06-28)
202 |
203 | ## Breaking changes
204 |
205 | - API service `loading` observable is now replaced by a `status` observable.
206 |
207 | ## New features
208 |
209 | - Handle errors in API service
210 |
211 | ## Bug fixes
212 |
213 | - Fix navigation request parameter
214 | - Fix navigation tree
215 |
216 | # 1.0.0-alpha.24 (2017-06-28)
217 |
218 | ## New features
219 |
220 | - Comments read/add
221 |
222 | # 1.0.0-alpha.23 (2017-06-27)
223 |
224 | ## New features
225 |
226 | - When search results contain File contents, return an actual link, not a traverse
227 | - Sitemap view
228 |
229 | # 1.0.0-alpha.22 (2017-06-26)
230 |
231 | ## Breaking changes
232 |
233 | - The `isAuthenticated` observable is not a boolean anymore but an object (state + error)
234 |
235 | # 1.0.0-alpha.21 (2017-06-16)
236 |
237 | ## Breaking changes
238 |
239 | - The resource service find() method signature has changed
240 | - Requires Plone RESTAPI >= 1.0a18
241 |
242 | ## New features
243 |
244 | - find(): all search options passed as a unique dictionary
245 | - find(): add fullobjects option to retrieve full objects
246 |
247 | # 1.0.0-alpha.20 (2017-06-15)
248 |
249 | ## New features
250 |
251 | - Can subscribe to APIService.loading to knwo when loading is done or not.
252 |
253 | ## Bug fixes
254 |
255 | - Fix find() method when criteria are lists.
256 |
257 | # 1.0.0-alpha.19 (2017-06-02)
258 |
259 | ## New features
260 |
261 | - Allow 0 as root level (i.e. current folder) for local navigation.
262 |
263 | ## Bug fixes
264 |
265 | - Fix local navigation.
266 |
267 | # 1.0.0-alpha.18 (2017-06-01)
268 |
269 | ## New features
270 |
271 | - Use TypeMarker as default marker for traversing view registration.
272 |
273 | ## Bug fixes
274 |
275 | - Fix sort_order in find() method.
276 |
277 | # 1.0.0-alpha.17 (2017-05-25)
278 |
279 | ## New features
280 |
281 | - search view
282 | - redirect to login page if not authorized
283 | - Angular Universal support
284 | - expose title and description meta in HEAD
285 |
286 | # 1.0.0-alpha.16 (2017-04-25)
287 |
288 | ## New features
289 |
290 | - specific service for HTTP calls
291 | - login view
292 | - edit view
293 |
294 | ## Bug fixes
295 |
296 | - manage unsubscribe for all traversing aware components
297 |
298 | # 1.0.0-alpha.15 (2017-04-17)
299 |
300 | ## Bug fixes
301 |
302 | - fix AOT support
303 | - fix src/href replace in body text
304 |
305 | # 1.0.0-alpha.14 (2017-04-01)
306 |
307 | ## New features
308 |
309 | - add start and size options in search
310 | - fully functional navigation service and component
311 |
312 | ## Bug fixes
313 |
314 | - encode metadata_fields and booleans properly in search
315 |
316 | # 1.0.0-alpha.13 (2017-03-30)
317 |
318 | ## New feature
319 |
320 | - convert images and files to full backend path in rich text content
321 |
322 | ## Bug fixes
323 |
324 | - fix active link in navigation
325 |
326 | # 1.0.0-alpha.12 (2017-03-30)
327 |
328 | ## New feature
329 |
330 | - upgrade angular-traversal to allow full path traversing
331 |
332 | # 1.0.0-alpha.11 (2017-03-29)
333 |
334 | ## New feature
335 |
336 | - manage active link in local navigation
337 | - display parent navigation if context is not a folder
338 |
339 | ## Bug fixes
340 |
341 | - rename component.service properly and export it
342 | - set target to es5 for tests (so we can clean up custom components)
343 |
344 | # 1.0.0-alpha.10 (2017-03-24)
345 |
346 | ## New feature
347 |
348 | Upgrade to Angular 4.0
349 |
350 | # 1.0.0-alpha.6 to .9 (2017-03-22)
351 |
352 | ## New feature
353 |
354 | - Set active link in global navigation
355 |
356 | # 1.0.0-alpha.6 (2017-03-22)
357 |
358 | ## Bug fixes
359 |
360 | - Fix package exported classes
361 |
362 | # 1.0.0-alpha.5 (2017-03-22)
363 |
364 | ## New features
365 |
366 | - Add global navigation component
367 |
368 | # 1.0.0-alpha.4 (2017-03-19)
369 |
370 | ## Bug Fixes
371 |
372 | - Move dependencies to peer dependencies
373 |
374 | # 1.0.0-alpha.3 (2017-03-19)
375 |
376 | ## Bug Fixes
377 |
378 | - Fix TypeScript compilation
379 |
380 | # 1.0.0-alpha.2 (2017-03-16)
381 |
382 | ## Bug Fixes
383 |
384 | - Clean up package content
385 |
386 | # 1.0.0-alpha.1 (2017-03-16)
387 |
388 | Initial release
389 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Plone Foundation
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # The Plone Angular SDK
2 |
3 | [](https://travis-ci.org/plone/plone.restapi-angular)
4 | [](https://coveralls.io/github/plone/plone.restapi-angular?branch=master)
5 | [](http://plonerestapi-angular.readthedocs.io/en/latest/?badge=latest)
6 |
7 | **A simple Angular SDK to build web sites easily on top of the Plone RESTAPI.**
8 |
9 | This package aims to provide the services and components needed to build an Angular applications based on the [Plone REST API](http://plonerestapi.readthedocs.io/en/latest/).
10 |
11 | Plone is a flexible and powerful backend, it provides:
12 |
13 | - hierachical storage
14 | - customizable content types
15 | - granular access control
16 | - workflows
17 | - a rich management interface
18 |
19 | The Plone Angular SDK provides ready-to-use components to build a wide range of applications.
20 |
21 | 
22 |
23 | ## Documentation
24 |
25 | See [documentation](http://plonerestapi-angular.readthedocs.io).
26 |
27 | ## Example
28 |
29 | This repository contains a very simple example: [https://github.com/collective/plone-angular-demo](https://github.com/collective/plone-angular-demo).
30 |
31 | To initialize it, run:
32 | ```
33 | yarn install
34 | ```
35 |
36 | Make sure you have a Plone server running on localhost:8080 with Plone RESTAPI installed.
37 |
38 | Then launch:
39 | ```
40 | ng serve
41 | ```
42 | and visit http://locahost:4200/.
43 |
44 | By checking out this [commit](https://github.com/collective/plone-angular-demo/commit/152068ef3db2362da52e36ae7fe753992dd3bf42), you will get a site displaying the current content plus a navigation bar, with no customization.
45 |
46 | If you checkout this [commit](https://github.com/collective/plone-angular-demo/commit/3881c003d1d253208d2db4a14c2bbec6dbe1b484), you will have bootstrap style (you will need to run `yarn install` in order to update your node modules) and a custom navigation.
47 |
48 | ## Run tests
49 |
50 | cd tests
51 | yarn install
52 | cd ..
53 | yarn test
54 |
55 | ## Contribute
56 |
57 | - Issue Tracker: https://github.com/plone/plone.restapi-angular/issues
58 | - Source Code: https://github.com/plone/plone.restapi-angular
59 | - Documentation: https://github.com/plone/plone.restapi-angular/README.md
60 |
61 | ## Support
62 |
63 | If you are having issues, please let us know.
64 |
65 | Use thissue tracker https://github.com/plone/plone.restapi-angular/issues
66 |
67 | ## License
68 |
69 | The project is licensed under the MIT license.
70 |
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "restapi-angular": {
7 | "root": "",
8 | "sourceRoot": "src",
9 | "projectType": "application",
10 | "prefix": "app",
11 | "schematics": {},
12 | "architect": {
13 | "build": {
14 | "builder": "@angular-devkit/build-angular:browser",
15 | "options": {
16 | "outputPath": "dist/restapi-angular",
17 | "index": "src/index.html",
18 | "main": "src/main.ts",
19 | "polyfills": "src/polyfills.ts",
20 | "tsConfig": "src/tsconfig.app.json",
21 | "assets": [
22 | "src/favicon.ico",
23 | "src/assets"
24 | ],
25 | "styles": [
26 | "src/styles.css"
27 | ],
28 | "scripts": [],
29 | "es5BrowserSupport": true
30 | },
31 | "configurations": {
32 | "production": {
33 | "fileReplacements": [
34 | {
35 | "replace": "src/environments/environment.ts",
36 | "with": "src/environments/environment.prod.ts"
37 | }
38 | ],
39 | "optimization": true,
40 | "outputHashing": "all",
41 | "sourceMap": false,
42 | "extractCss": true,
43 | "namedChunks": false,
44 | "aot": true,
45 | "extractLicenses": true,
46 | "vendorChunk": false,
47 | "buildOptimizer": true,
48 | "budgets": [
49 | {
50 | "type": "initial",
51 | "maximumWarning": "2mb",
52 | "maximumError": "5mb"
53 | }
54 | ]
55 | }
56 | }
57 | },
58 | "serve": {
59 | "builder": "@angular-devkit/build-angular:dev-server",
60 | "options": {
61 | "browserTarget": "restapi-angular:build"
62 | },
63 | "configurations": {
64 | "production": {
65 | "browserTarget": "restapi-angular:build:production"
66 | }
67 | }
68 | },
69 | "extract-i18n": {
70 | "builder": "@angular-devkit/build-angular:extract-i18n",
71 | "options": {
72 | "browserTarget": "restapi-angular:build"
73 | }
74 | },
75 | "test": {
76 | "builder": "@angular-devkit/build-angular:karma",
77 | "options": {
78 | "main": "src/test.ts",
79 | "polyfills": "src/polyfills.ts",
80 | "tsConfig": "src/tsconfig.spec.json",
81 | "karmaConfig": "src/karma.conf.js",
82 | "styles": [
83 | "src/styles.css"
84 | ],
85 | "scripts": [],
86 | "assets": [
87 | "src/favicon.ico",
88 | "src/assets"
89 | ]
90 | }
91 | },
92 | "lint": {
93 | "builder": "@angular-devkit/build-angular:tslint",
94 | "options": {
95 | "tsConfig": [
96 | "src/tsconfig.app.json",
97 | "src/tsconfig.spec.json"
98 | ],
99 | "exclude": [
100 | "**/node_modules/**"
101 | ]
102 | }
103 | }
104 | }
105 | },
106 | "restapi-angular-e2e": {
107 | "root": "e2e/",
108 | "projectType": "application",
109 | "prefix": "",
110 | "architect": {
111 | "e2e": {
112 | "builder": "@angular-devkit/build-angular:protractor",
113 | "options": {
114 | "protractorConfig": "e2e/protractor.conf.js",
115 | "devServerTarget": "restapi-angular:serve"
116 | },
117 | "configurations": {
118 | "production": {
119 | "devServerTarget": "restapi-angular:serve:production"
120 | }
121 | }
122 | },
123 | "lint": {
124 | "builder": "@angular-devkit/build-angular:tslint",
125 | "options": {
126 | "tsConfig": "e2e/tsconfig.e2e.json",
127 | "exclude": [
128 | "**/node_modules/**"
129 | ]
130 | }
131 | }
132 | }
133 | },
134 | "plone-restapi-angular": {
135 | "root": "projects/plone-restapi-angular",
136 | "sourceRoot": "projects/plone-restapi-angular/src",
137 | "projectType": "library",
138 | "prefix": "lib",
139 | "architect": {
140 | "build": {
141 | "builder": "@angular-devkit/build-ng-packagr:build",
142 | "options": {
143 | "tsConfig": "projects/plone-restapi-angular/tsconfig.lib.json",
144 | "project": "projects/plone-restapi-angular/ng-package.json"
145 | }
146 | },
147 | "test": {
148 | "builder": "@angular-devkit/build-angular:karma",
149 | "options": {
150 | "main": "projects/plone-restapi-angular/src/test.ts",
151 | "tsConfig": "projects/plone-restapi-angular/tsconfig.spec.json",
152 | "karmaConfig": "projects/plone-restapi-angular/karma.conf.js"
153 | }
154 | },
155 | "lint": {
156 | "builder": "@angular-devkit/build-angular:tslint",
157 | "options": {
158 | "tsConfig": [
159 | "projects/plone-restapi-angular/tsconfig.lib.json",
160 | "projects/plone-restapi-angular/tsconfig.spec.json"
161 | ],
162 | "exclude": [
163 | "**/node_modules/**"
164 | ]
165 | }
166 | }
167 | }
168 | }
169 | },
170 | "defaultProject": "restapi-angular"
171 | }
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | SPHINXPROJ = PloneAngularSDK
8 | SOURCEDIR = .
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
--------------------------------------------------------------------------------
/docs/advanced.rst:
--------------------------------------------------------------------------------
1 | Advanced
2 | ========
3 |
4 | Configuration options
5 | ---------------------
6 |
7 | The CONFIGURATION provider gets some values:
8 |
9 | - `BACKEND_URL`: the url of the backed
10 | - `CLIENT_TIMEOUT` the time (in ms) client waits for a backend response before it raises a timeout error. Defaults to 15000.
11 |
12 |
13 | Registering a custom marker for view registration
14 | -------------------------------------------------
15 |
16 | TBD
17 |
--------------------------------------------------------------------------------
/docs/anim.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/plone/plone.restapi-angular/b65c901a8f2efa673345cddc0e005edc0333acb8/docs/anim.gif
--------------------------------------------------------------------------------
/docs/basic-usage.rst:
--------------------------------------------------------------------------------
1 | Basic usage
2 | ===========
3 |
4 | In ``src/app.module.ts``, load the module and set the backend URL:
5 |
6 | .. code-block:: javascript
7 |
8 | import { RESTAPIModule } from '@plone/restapi-angular';
9 |
10 | ...
11 |
12 | @NgModule({
13 | ...
14 | imports: [
15 | ...
16 | RESTAPIModule,
17 | ],
18 | providers: [
19 | {
20 | provide: 'CONFIGURATION', useValue: {
21 | BACKEND_URL: 'http://localhost:8080/Plone',
22 | CLIENT_TIMEOUT: 5000,
23 | }
24 | },
25 | ],
26 | ...
27 |
28 | And you have to set up the Plone views for traversal in ``src/app.component.ts``:
29 |
30 | .. code-block:: javascript
31 |
32 | import { Component } from '@angular/core';
33 | import { Traverser } from 'angular-traversal';
34 | import { PloneViews } from '@plone/restapi-angular';
35 |
36 | @Component({
37 | ...
38 | })
39 | export class AppComponent {
40 |
41 | constructor(
42 | private views:PloneViews,
43 | private traverser: Traverser,
44 | ) {
45 | this.views.initialize();
46 | }
47 | }
48 |
49 | Now you can use the Plone components in your templates, for example in ``src/app.component.html``:
50 |
51 | .. code-block:: html
52 |
53 |
54 |
55 |
56 | Customize components
57 | ---------------------
58 |
59 | **WORK IN PROGRESS** (we will propose a better customization story)
60 |
61 | If you want to change the component's rendering, you can provide your own template by extending the original Plone component.
62 |
63 | In this example we will override the template used by the ``Navigation`` component in order to use `Material Design `_ styling. The navigation menu is actually provided by two separate components, |Navigation|_ and |NavigationLevel|_. The actual customization will happen in the latter, but we also need a custom ``Navigation`` in order to refer to our custom ``NavigationLevel``.
64 |
65 | .. |Navigation| replace:: ``Navigation``
66 | .. _Navigation: https://github.com/plone/plone.restapi-angular/blob/master/src/components/navigation.ts
67 |
68 | .. |NavigationLevel| replace:: ``NavigationLevel``
69 | .. _NavigationLevel: https://github.com/plone/plone.restapi-angular/blob/master/src/components/navigation.level.ts
70 |
71 | Let's use Angular CLI to create our custom components:
72 |
73 | .. code-block:: bash
74 |
75 | ng generate component custom-navigation
76 | ng generate component custom-navigation-level
77 |
78 | This will create two new folders: ``./src/app/custom-navigation`` and ``./src/app/custom-navigation-level``.
79 |
80 | We will start with ``./src/app/custom-navigation/custom-navigation.component.ts``:
81 |
82 | .. code-block:: javascript
83 |
84 | import { Component } from '@angular/core';
85 | import { Navigation } from '@plone/restapi-angular';
86 |
87 | @Component({
88 | selector: 'custom-navigation',
89 | template: ``
90 | })
91 | export class CustomNavigationComponent extends Navigation {}
92 |
93 | - We add an ``import`` for the default ``Navigation``.
94 | - Rename the ``selector``.
95 | - Put the ``template`` inline (using backticks) instead of using an external ``templateUrl``, since the template is very short.
96 | - Replace ``implements`` with ``extends`` and extend from ``Navigation``.
97 | - Delete the ``constructor`` and ``ngOnInit``.
98 |
99 | Let us now turn to ``./src/app/custom-navigation-level/custom-navigation-level.component.ts``:
100 |
101 | .. code-block:: javascript
102 |
103 | import { Component } from '@angular/core';
104 | import { NavigationLevel } from '@plone/restapi-angular';
105 |
106 | @Component({
107 | selector: 'custom-navigation-level',
108 | templateUrl: './custom-navigation-level.component.html',
109 | })
110 | export class CustomNavigationLevelComponent extends NavigationLevel {
111 | }
112 |
113 | This is very similar to the custom navigation component, except that we point to a ``templateUrl``, because in this case the template (``./src/app/custom-navigation-level/custom-navigation-level.component.html``) is a little more involved.
114 |
115 | .. code-block:: javascript
116 |
117 |
118 |
119 |
120 | {{ link.properties.title }}
121 |
122 |
125 |
126 |
127 |
128 | Note that we are using the same structure as in the |defaultNavigationLeveltemplate|_, only using markup from Angular Material. Before we can call this done, we also need to install the dependencies (see `the setup here `_):
129 |
130 | .. |defaultNavigationLeveltemplate| replace:: default ``NavigationLevel`` template
131 | .. _defaultNavigationLeveltemplate: https://github.com/plone/plone.restapi-angular/blob/master/src/components/navigation.level.ts#L5
132 |
133 | .. code-block:: bash
134 |
135 | npm install --save @angular/material
136 | npm install --save @angular/animations
137 |
138 | Finally, edit your app module (``./src/app/app.module.ts``):
139 |
140 | .. code-block:: javascript
141 |
142 | ...
143 | import { CustomNavigation } from './src/custom-navigation/custom-navigation.component';
144 | ...
145 | @NgModule({
146 | declarations: [
147 | ...
148 | CustomNavigation,
149 | ],
150 | ...
151 |
152 | And load the CSS for Angular Material in the "main template" ``./src/index.html``:
153 |
154 | .. code-block:: html
155 |
156 |
157 |
158 | Now you can use your ```` component in templates, for example by using it instead of ````.
159 |
160 | Customize views
161 | ---------------------
162 |
163 | Customizing a view is quite similar to component customization, the only extra step is to declare it for traversal.
164 | In this example we will modify the default view so that it will display the context's summary under its title.
165 |
166 | Let's use Angular CLI to create our custom view:
167 |
168 | .. code-block:: bash
169 |
170 | ng generate component custom-view
171 |
172 | This will create a new folder: ``./src/app/custom-view``.
173 |
174 | Edit ``./src/app/custom-view/custom-view.component.ts``:
175 |
176 | .. code-block:: javascript
177 |
178 | import { Component } from '@angular/core';
179 | import { ViewView } from '@plone/restapi-angular';
180 |
181 | @Component({
182 | selector: 'custom-view',
183 | template: `
{{ context.title }}
{{ context.description }}
`,
184 | })
185 | export class CustomViewView extends ViewView {}
186 |
187 | You can see in the inline template that we added the ``context.description``.
188 |
189 | In ``app.module.ts``, you will need to put our custom view in ``declarations`` and in ``entryComponents``:
190 |
191 | .. code-block:: javascript
192 |
193 | import { CustomViewView } from './custom-view/custom-view.component';
194 | @NgModule({
195 | declarations: [
196 | AppComponent,
197 | CustomViewView,
198 | ],
199 | entryComponents: [
200 | CustomViewView,
201 | ],
202 | ...
203 |
204 | And in ``app.component.ts``, you will need to register it for traversal this way:
205 |
206 | .. code-block:: javascript
207 |
208 | ...
209 | import { CustomViewView } from './custom-view/custom-view.component';
210 |
211 | ...
212 | export class AppComponent {
213 |
214 | constructor(
215 | private views:PloneViews,
216 | private traverser: Traverser,
217 | ) {
218 | this.views.initialize();
219 | this.traverser.addView('view', '*', CustomViewView);
220 | }
221 | }
222 |
223 | Now your custom view will replace the original one.
224 |
--------------------------------------------------------------------------------
/docs/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Plone Angular SDK documentation build configuration file, created by
4 | # sphinx-quickstart on Thu Nov 16 10:48:57 2017.
5 | #
6 | # This file is execfile()d with the current directory set to its
7 | # containing dir.
8 | #
9 | # Note that not all possible configuration values are present in this
10 | # autogenerated file.
11 | #
12 | # All configuration values have a default; values that are commented out
13 | # serve to show the default.
14 |
15 | # If extensions (or modules to document with autodoc) are in another directory,
16 | # add these directories to sys.path here. If the directory is relative to the
17 | # documentation root, use os.path.abspath to make it absolute, like shown here.
18 | #
19 | # import os
20 | # import sys
21 | # sys.path.insert(0, os.path.abspath('.'))
22 |
23 |
24 | # -- General configuration ------------------------------------------------
25 |
26 | # If your documentation needs a minimal Sphinx version, state it here.
27 | #
28 | # needs_sphinx = '1.0'
29 |
30 | # Add any Sphinx extension module names here, as strings. They can be
31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
32 | # ones.
33 | extensions = ['sphinx.ext.autodoc']
34 |
35 | # Add any paths that contain templates here, relative to this directory.
36 | templates_path = ['_templates']
37 |
38 | # The suffix(es) of source filenames.
39 | # You can specify multiple suffix as a list of string:
40 | #
41 | # source_suffix = ['.rst', '.md']
42 | source_suffix = '.rst'
43 |
44 | # The master toctree document.
45 | master_doc = 'index'
46 |
47 | # General information about the project.
48 | project = u'Plone Angular SDK'
49 | copyright = u'2017, ebrehault sunew tdesvenain fulv'
50 | author = u'ebrehault sunew tdesvenain fulv'
51 |
52 | # The version info for the project you're documenting, acts as replacement for
53 | # |version| and |release|, also used in various other places throughout the
54 | # built documents.
55 | #
56 | # The short X.Y version.
57 | version = u'1.3.1'
58 | # The full version, including alpha/beta/rc tags.
59 | release = u'1.3.1'
60 |
61 | # The language for content autogenerated by Sphinx. Refer to documentation
62 | # for a list of supported languages.
63 | #
64 | # This is also used if you do content translation via gettext catalogs.
65 | # Usually you set "language" from the command line for these cases.
66 | language = None
67 |
68 | # List of patterns, relative to source directory, that match files and
69 | # directories to ignore when looking for source files.
70 | # This patterns also effect to html_static_path and html_extra_path
71 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
72 |
73 | # The name of the Pygments (syntax highlighting) style to use.
74 | pygments_style = 'sphinx'
75 |
76 | # If true, `todo` and `todoList` produce output, else they produce nothing.
77 | todo_include_todos = False
78 |
79 |
80 | # -- Options for HTML output ----------------------------------------------
81 |
82 | # The theme to use for HTML and HTML Help pages. See the documentation for
83 | # a list of builtin themes.
84 | #
85 | html_theme = 'sphinx_rtd_theme'
86 |
87 | # Theme options are theme-specific and customize the look and feel of a theme
88 | # further. For a list of options available for each theme, see the
89 | # documentation.
90 | #
91 | # html_theme_options = {}
92 |
93 | # Add any paths that contain custom static files (such as style sheets) here,
94 | # relative to this directory. They are copied after the builtin static files,
95 | # so a file named "default.css" will overwrite the builtin "default.css".
96 | html_static_path = ['_static']
97 |
98 | # Custom sidebar templates, must be a dictionary that maps document names
99 | # to template names.
100 | #
101 | # This is required for the alabaster theme
102 | # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
103 | html_sidebars = {
104 | '**': [
105 | 'relations.html', # needs 'show_related': True theme option to display
106 | 'searchbox.html',
107 | ]
108 | }
109 |
110 |
111 | # -- Options for HTMLHelp output ------------------------------------------
112 |
113 | # Output file base name for HTML help builder.
114 | htmlhelp_basename = 'PloneAngularSDKdoc'
115 |
116 |
117 | # -- Options for LaTeX output ---------------------------------------------
118 |
119 | latex_elements = {
120 | # The paper size ('letterpaper' or 'a4paper').
121 | #
122 | # 'papersize': 'letterpaper',
123 |
124 | # The font size ('10pt', '11pt' or '12pt').
125 | #
126 | # 'pointsize': '10pt',
127 |
128 | # Additional stuff for the LaTeX preamble.
129 | #
130 | # 'preamble': '',
131 |
132 | # Latex figure (float) alignment
133 | #
134 | # 'figure_align': 'htbp',
135 | }
136 |
137 | # Grouping the document tree into LaTeX files. List of tuples
138 | # (source start file, target name, title,
139 | # author, documentclass [howto, manual, or own class]).
140 | latex_documents = [
141 | (master_doc, 'PloneAngularSDK.tex', u'Plone Angular SDK Documentation',
142 | u'ebrehault sunew tdesvenain fulv', 'manual'),
143 | ]
144 |
145 |
146 | # -- Options for manual page output ---------------------------------------
147 |
148 | # One entry per manual page. List of tuples
149 | # (source start file, name, description, authors, manual section).
150 | man_pages = [
151 | (master_doc, 'ploneangularsdk', u'Plone Angular SDK Documentation',
152 | [author], 1)
153 | ]
154 |
155 |
156 | # -- Options for Texinfo output -------------------------------------------
157 |
158 | # Grouping the document tree into Texinfo files. List of tuples
159 | # (source start file, target name, title, author,
160 | # dir menu entry, description, category)
161 | texinfo_documents = [
162 | (master_doc, 'PloneAngularSDK', u'Plone Angular SDK Documentation',
163 | author, 'PloneAngularSDK', 'One line description of project.',
164 | 'Miscellaneous'),
165 | ]
166 |
167 |
168 |
169 |
--------------------------------------------------------------------------------
/docs/deployment.rst:
--------------------------------------------------------------------------------
1 | Deployment
2 | ==========
3 |
4 | Basic Deployment
5 | ----------------
6 |
7 | Deployment can be achieved in two very basic steps:
8 |
9 | - build the app: `ng build --prod`,
10 | - push the resulting `./dist` folder to any HTTP server.
11 |
12 | But we need to tell the HTTP server to not worry about traversed URL.
13 | Basically any requested URL must be redirected to `index.html`, so Angular Traversal
14 | takes care about the requested path.
15 |
16 | If you use Nginx, it can be achieved with this very simple configuration::
17 |
18 | location / {
19 | try_files $uri $uri/ /index.html;
20 | }
21 |
22 | Basically any existing file (like index.html, JS or CSS bundles, etc.) will be
23 | served directly, and anything else is redirected to index.html.
24 |
25 | Server-side rendering
26 | ---------------------
27 |
28 | For a single page app, it might be interesting to be able to render pages on the server-side:
29 |
30 | - it improves the first-page display time,
31 | - it improves SEO,
32 | - it makes social network sharing more accurate.
33 |
34 | Angular provides a server-side rendering solution named `Universal `_.
35 | Universal uses NodeJS to render the requested page as plain HTML which is delivered to the client directly.
36 | But once the first page is delivered, the page is rehydrated, meaning the JavaScript application
37 | is loaded on the background and takes the control back smoothly, so when the user clicks on
38 | any link or performs any action offered by the UI, it is processed on the client-side.
39 |
40 | @plone/restapi-angular is Universal compliant.
41 |
42 | A little extra configuration is needed to allow it in a regular Angular CLI project,
43 | and an example will be provided soon.
--------------------------------------------------------------------------------
/docs/development.rst:
--------------------------------------------------------------------------------
1 | Development
2 | ===========
3 |
4 |
5 | To make development and debugging of this library easy, you can run on a linked git clone when using it from an angular-cli based app.
6 |
7 |
8 | Goals:
9 |
10 | - Run on a git clone, not just on a released version of the library in node_modules. Making it possible to run on a branch, (master, feature branch for a later pull request...)
11 | - Sourcemaps of the library Typescript code in the browsers developer tools.
12 | - ``debugger;``-statements can be placed in the typescript sourcecode of the library, as well as of the app.
13 | - instant recompile and reload of both app and library code changes when using ``ng serve``.
14 | - keep imports the same: ``import { RESTAPIModule } from '@plone/restapi-angular';`` should work both when we run on a release in node_modules or on a git clone.
15 |
16 | Prerequisites:
17 |
18 | You have created an app with angular-cli.
19 |
20 |
21 | Setting up development
22 | ----------------------
23 |
24 | The method is:
25 |
26 | 1. clone the library (or libraries).
27 | 2. symlink the src-folder of the library into a packages-folder in your apps src-folder.
28 | 3. configure the module resolution
29 | 4. configure angular-cli build to follow symlinks
30 |
31 | This method will build the library with the methods and configuration of your app. Production releases can behave differently.
32 |
33 | 1 and 2: The following script clones two libraries - plone.restapi-angular and angular-traversal, and symlinks them into src/packages
34 |
35 | Run it from inside your app.
36 |
37 | .. code-block:: shell
38 |
39 | #!/bin/sh
40 | # Run me from project root
41 | mkdir develop
42 | cd develop
43 | git clone git@github.com:plone/plone.restapi-angular.git
44 | git clone https://github.com/makinacorpus/angular-traversal.git
45 | cd ..
46 |
47 | mkdir src/packages
48 | mkdir src/packages/@plone
49 | ln -sT ../../../develop/plone.restapi-angular/src ./src/packages/@plone/restapi-angular
50 | ln -sT ../../develop/angular-traversal/src ./src/packages/angular-traversal
51 |
52 |
53 | For ``@plone/restapi-angular``, we need to create the full namespace folder hierarchy (``@plone``).
54 |
55 | 3: Module resolution: We want to keep being able to import from ``@plone/restapi-angular``, just as when running on a released version of the library::
56 |
57 | import { RESTAPIModule } from '@plone/restapi-angular';
58 |
59 | In ``tsconfig.json`` it is possible to configure a ``paths``-mapping of module names to locations, relative to the baseUrl (the location of your apps main entry point).
60 |
61 | See https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping
62 |
63 | Add the paths mapping to the ``compilerOptions`` in the ``tsconfig.app.json`` of your app, (I assume you have the layout of an angular-cli standard project), and make sure the location matches with your ``baseUrl``-setting.
64 |
65 | .. code-block:: javascript
66 |
67 | "baseUrl": "./",
68 | "paths": {
69 | "@plone/restapi-angular": ["packages/@plone/restapi-angular"],
70 | "angular-traversal": ["packages/angular-traversal"]
71 | }
72 |
73 | With some IDEs, like IntelliJ, you will have to put those settings into root ``tsconfig.json``.
74 | Note that the baseUrl will be your source directory (probably ``./src``) there.
75 |
76 | .. code-block:: javascript
77 |
78 | "baseUrl": "./src",
79 | "paths": {
80 | "@plone/restapi-angular": ["packages/@plone/restapi-angular"],
81 | "angular-traversal": ["packages/angular-traversal"]
82 | },
83 |
84 | 4: Add the following to the ``defaults`` section of your ``.angular-cli.json``::
85 |
86 | "defaults": {
87 | "build": {
88 | "preserveSymlinks": true
89 | }
90 | }
91 |
92 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | .. Plone Angular SDK documentation master file, created by
2 | sphinx-quickstart on Thu Nov 16 10:48:57 2017.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to Plone Angular SDK's documentation!
7 | =============================================
8 |
9 | .. toctree::
10 | :maxdepth: 2
11 | :caption: Contents:
12 |
13 | basic-usage
14 | setup
15 | principles
16 | deployment
17 | development
18 | advanced
19 | reference/index
20 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 | set SPHINXPROJ=PloneAngularSDK
13 |
14 | if "%1" == "" goto help
15 |
16 | %SPHINXBUILD% >NUL 2>NUL
17 | if errorlevel 9009 (
18 | echo.
19 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
20 | echo.installed, then set the SPHINXBUILD environment variable to point
21 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
22 | echo.may add the Sphinx directory to PATH.
23 | echo.
24 | echo.If you don't have Sphinx installed, grab it from
25 | echo.http://sphinx-doc.org/
26 | exit /b 1
27 | )
28 |
29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
30 | goto end
31 |
32 | :help
33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
34 |
35 | :end
36 | popd
37 |
--------------------------------------------------------------------------------
/docs/principles.rst:
--------------------------------------------------------------------------------
1 | Principles
2 | ==========
3 |
--------------------------------------------------------------------------------
/docs/reference/components.rst:
--------------------------------------------------------------------------------
1 | Components
2 | ==========
3 |
4 | Breadcrumbs
5 | -----------
6 |
7 | .. code-block:: html
8 |
9 |
10 |
11 | Displays the breadcrumbs links for the current context.
12 |
13 | Forms
14 | -----
15 |
16 | Based on `Angular2 Schema Form `_.
17 |
18 | Global navigation
19 | -----------------
20 |
21 | .. code-block:: html
22 |
23 |
24 |
25 | Displays the first level links.
26 |
27 | Navigation
28 | ----------
29 |
30 | .. code-block:: html
31 |
32 |
33 |
34 | Display navigation links.
35 |
36 | ``root`` can be either a string (to specify a static path like ``/news``) or a null or negative number to specify an ancestor of the current page (0 means current folder).
37 |
38 | ``depth`` defines the tree depth.
39 |
40 | Note: be careful, in Angular templates, inputs are considered as string unless they are interpolated, so ``root="/events"`` returns the string ``"/events"`` and it works. It is equivalent to ``[root]="'/events'"``.
41 | But ``root="-1"`` is wrong, as it would return the string ``"-1"`` which is not a number. To get an actual number, interpolation is mandatory: ``[root]="-1"``.
42 |
43 | Comments
44 | --------
45 |
46 | .. code-block:: html
47 |
48 |
49 |
50 | Display the existing comments and allow to add new ones.
51 |
52 | Workflow
53 | --------
54 |
55 | .. code-block:: html
56 |
57 |
58 |
59 | Display workflow history and actionable list of available transitions.
60 |
61 |
62 | Toolbar
63 | -------
64 |
65 | .. code-block:: html
66 |
67 |
68 |
69 | TO BE IMPLEMENTED
70 |
--------------------------------------------------------------------------------
/docs/reference/directives.rst:
--------------------------------------------------------------------------------
1 | Directives
2 | ==========
3 |
4 |
5 | Download directive
6 | ------------------
7 |
8 | Download directive makes the component to start a file download at click.
9 |
10 | You have to provide a NamedFile object to the directive::
11 |
12 | Click here to download {{ context.thefile.filename }}
13 |
14 | This works with any html element::
15 |
16 |
17 |
18 | The directive has three outputs,
19 |
20 | - `onBeforeDownloadStarted`,
21 | - `onDownloadSucceeded`,
22 | - `onDownloadFailed`
23 |
--------------------------------------------------------------------------------
/docs/reference/index.rst:
--------------------------------------------------------------------------------
1 | References
2 | ==========
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 | :caption: References:
7 |
8 | components
9 | directives
10 | services
11 | traversal
12 | views
13 |
--------------------------------------------------------------------------------
/docs/reference/services.rst:
--------------------------------------------------------------------------------
1 | Services
2 | ========
3 |
4 | Services injection
5 | ------------------
6 |
7 | To make injection easier, all the following services are available in a unique service named `Services`. Example:
8 |
9 | .. code-block:: javascript
10 |
11 | import { Services } from '@plone/restapi-angular';
12 | ...
13 |
14 | constructor(public services: Services) { }
15 |
16 | ...
17 |
18 | this.services.resource.find(...);
19 |
20 | Configuration
21 | -------------
22 |
23 | It manages the following configuration values:
24 |
25 | - `AUTH_TOKEN_EXPIRES`: the expiration delay of the authentication token stored in local storage, in milliseconds (1 day by default).
26 | - `BACKEND_URL`: the URL of the backend searver exposing a valid Plone REST API
27 | - `PATCH_RETURNS_REPRESENTATION`: if true (by default), successful patch requests return a 200
28 | with full modified content representation as body.
29 | If false, it returns a 204 response with no content.
30 | - `RETRY_REQUEST_ATTEMPTS`: the number of times client will try a request when server is unavailable. (3 by default).
31 | - `RETRY_REQUEST_DELAY`: the retry delay in milliseconds (2000 by default).
32 |
33 | Methods:
34 |
35 | `get(key: string)`: returns the configuration value for the given key.
36 |
37 | `urlToPath(url: string): string`: converts a full backend URL into a locally traversable path.
38 |
39 | Authentication
40 | --------------
41 |
42 | Properties:
43 |
44 | `isAuthenticated`: observable indicating the current authentication status.
45 | The `state` property is a boolean indicating if the user is logged or not, and the `error` property indicates the error if any.
46 | The `username` property is the name of the logged in user, if any.
47 |
48 | Methods:
49 |
50 | `getUserInfo()`: returns an object containing the current user information.
51 |
52 | `login(login: string, password: string)`: authenticate to the backend using the provided credentials,
53 | the resulting authentication token and user information will be stored in localstorage.
54 | It returns an observable.
55 |
56 | `logout()`: delete the current authentication token.
57 |
58 | Comments
59 | --------
60 |
61 | Methods:
62 |
63 | `add(path: string, data: any)`: add a new comment in the content corresponding to the path.
64 |
65 | `delete(path: string)`: delete the comment corresponding to the path.
66 |
67 | `get(path: string)`: get all the comments of the content corresponding to the path.
68 |
69 | `update(path: string, data: any)`: update the comment corresponding to the path.
70 |
71 | Resources
72 | ---------
73 |
74 | This service gives access to all the Plone RESTAPI endpoints to manage resourcezs (i.e contents).
75 |
76 | Properties:
77 |
78 | `defaultExpand`: array of string indicating the default expansions that will be asked to the backend when we call `get`.
79 |
80 | Methods:
81 |
82 | `breadcrumbs(path: string)`: return the breadcrumbs links for the specified content.
83 |
84 | `copy(sourcePath: string, targetPath: string)`: copy the resource to another location. Returns an observable.
85 |
86 | `create(path: string, model: any)`: create a new resource in the container indicated by the path. Returns an observable.
87 |
88 | `delete(path: string)`: remove the requested resource as an observable. Returns an observable.
89 |
90 | `find(query: any, path: string='/', options: SearchOptions={})`: returns the search results as an observable.
91 |
92 | See `http://plonerestapi.readthedocs.io/en/latest/searching.html#search `_.
93 | The `options` parameter can contain the following attributes:
94 |
95 | - sort_on: string, name of the index used to sort the result.
96 | - metadata_fields: string[], list of extra metadata fields to retrieve
97 | - start: number, rank of the first item (used for batching, default is 0),
98 | - size: number, length of the batching (default is 20)
99 | - sort_order: string, `'reverse'` to get a reversed order,
100 | - fullobjects: boolean, if `True`, the result will be fully serialized objects, not just metadata.
101 |
102 | `getSearchQueryString`: (static) get a query string from a criterion/value(s) mapping and options object. Used by `find` method.
103 |
104 | `get(path: string, expand?: string[])`: returns the requested resource as an observable. `expand` allow to specify extra expansion (they will be added to `defaultExpand`).
105 |
106 | `lightFileRead(file: File): Observable`: (static) get a plone file field from a javascript File object. Not suitable for big files.
107 |
108 | `move(sourcePath: string, targetPath: string)`: move the resource to another location. Returns an observable.
109 |
110 | `navigation()`: get the global navigation links. Returns an observable.
111 |
112 | `transition(path: string, transition: string, options: WorkflowTransitionOptions)`: perform the transition on the resource. You can set a workflow comment. Returns an observable of the last action information.
113 |
114 | `workflow(path: string)`: get the workflow history and the available transitions on the content. Returns an observable.
115 |
116 | `update(path: string, model: any)`: update the resource by storing the provided model content (existing attibutes are not overidden). Returns an observable.
117 |
118 | `save(path: string, model: any)`: update the resource by replacing its model with the provided model content. Returns an observable.
119 |
120 | `type(typeId)`: return the JSON schema of the specified resource type.
121 |
122 | `vocabulary(vocabularyId)`: return the specified vocabulary object. Returns an observable.
123 |
124 | API service
125 | -----------
126 |
127 | This service allows to call regular HTTP verbs (for instance to call non-standard endpoints implemented on our backend):
128 |
129 | - `get(path)`
130 | - `post(path, data)`
131 | - `patch(path, data)`
132 | - `delete(path)`
133 |
134 | They all takes care to add the appropriate headers (like authentication token), and return an observable.
135 |
136 | In addition, it provides a specific method to download a file as a blob:
137 |
138 | `download(path)` returns an observable containing a `Blob object `_.
139 |
140 | A Blob object can be turned into an URL like this:
141 |
142 | .. code-block:: javascript
143 |
144 | import { DomSanitizer } from '@angular/platform-browser';
145 |
146 | constructor(
147 | ...
148 | public sanitizer: DomSanitizer,
149 | ) { }
150 |
151 | ...
152 | this.services.api.download(path).subscribe(blob => {
153 | this.downloadURL = this.sanitizer.bypassSecurityTrustUrl(
154 | window.URL.createObjectURL(blob));
155 | });
156 |
157 | It also exposes a `status` observable which returns an object containing:
158 |
159 | - `loading`, boolean, true if call is pending, false if finished
160 | - `error`, the HTTP error if any.
161 |
162 | It exposes a `backendAvailable` observable that emits `false` when backend server can't be reached or consistently responds 502, 503 or 504.
163 |
164 |
165 | Cache service
166 | -------------
167 |
168 | The CacheService service provides a `get` method which wraps `get` method from Api service with caching features.
169 |
170 | The http request observable is piped into a Subject that repeats the same response during a delay. This delay can be set while providing `CACHE_REFRESH_DELAY` property of `CONFIGURATION` provider.
171 |
172 | You can clear the cache emitting the `revoke` event of the service. It revokes all the cache if you give no argument to the emission. It revokes cache for a single path if you give it a string.
173 |
174 | .. code-block:: javascript
175 |
176 | this.cache.revoke.emit('http://example.com/home')
177 |
178 | The cache can't store more than as many entries as set on `CACHE_MAX_SIZE` property.
179 |
180 | A `hits` property contains the hits statistics (number of hits by path).
181 |
182 | Cache service is massively used by `resource` and `comments` service. All get requests are cached and all create/update/delete requests revokes cache.
183 |
184 |
185 | Loading service
186 | ---------------
187 |
188 | Loading service stores ids for what is currently loading. You declare here which loadings have begun and finished.
189 |
190 | The service provides observables that emits when loading status changes. This is useful when you want to display a reactive loader.
191 |
192 | You give an id to each 'thing' you mark as loaded using the `begin` method. You mark loading as finished using the `finish` method.
193 |
194 | `status` behavior subject changes when there is nothing left to load or if there is at least one thing loading.
195 |
196 | `isLoading` method provides an observable that emits the loading status for a specific id.
197 |
198 |
199 | .. code-block:: javascript
200 |
201 | loading.status.subscribe((isLoading) => {
202 | this.somethingIsLoading = isLoading;
203 | });
204 |
205 | loading.isLoading('the-data').subscribe((isLoading: boolean) => {
206 | this.dataIsLoading = isLoading;
207 | });
208 |
209 | loading.begin('the-data') // mark 'the-data' as loading
210 | dataService.getData().subscribe((data: string[]) => {
211 | loading.finish('the-data');
212 | this.data = data;
213 | }, (error) => {
214 | loading.finish('the-data');
215 | this.data = [];
216 | this.error = error;
217 | });
218 |
219 |
220 | This service is used by LoadingInterceptor http interceptor that marks a loading status when any http request is done.
221 |
--------------------------------------------------------------------------------
/docs/reference/traversal.rst:
--------------------------------------------------------------------------------
1 | Traversal
2 | =========
3 |
4 | Based on `Angular traversal `_.
5 |
6 | The Traversal service replaces the default Angular routing. It uses the current location to determine the backend resource (the **context**) and the desired rendering (the **view**).
7 |
8 | The view is the last part of the current location and is prefiexd by `@@`.
9 | If no view is specified, it defaults to `view`.
10 |
11 | The rest of the location is the resource URL.
12 |
13 | Example: `/news/what-about-traversal/@@edit`
14 |
15 | When traversing to the location, the resource will be requested to the backend, and the result will become the current context, accessible from any component in the app.
16 |
17 | According the values in the `@type` property of the context, the appropriate component will be used to render the view.
18 |
19 | Note: We can also use another criteria than `@type` by registring a custom marker (the package comes with an `InterfaceMarker` which marks context according the `interfaces` attribute, which is supposed to be a list. At the moment, the Plone REST API does not expose this attribute).
20 |
21 | Outlet:
22 |
23 | .. code-block:: html
24 |
25 |
26 |
27 |
28 | It allows to position the view rendeirng in the main layout.
29 |
30 | Directive:
31 |
32 | `traverseTo` allows to create a link to a given location.
33 |
34 | Example:
35 | .. code-block:: html
36 |
37 | See the sprint event
38 |
39 |
40 | Methods:
41 |
42 | `addView(name: string, marker: string, component: any)`: register a component as a view for a given marker value. By default, we use the context's `@type` value as marker.
43 |
44 | `traverse(path: string, navigate: boolean = true)`: traverse to the given path. If `navigate` is false, the location will not be changed (useful if the browser location was already set before we traverse).
45 |
--------------------------------------------------------------------------------
/docs/reference/views.rst:
--------------------------------------------------------------------------------
1 | Views
2 | =====
3 |
4 | @@add
5 | -----
6 |
7 | Example: `http://localhost:4200/site/folder1/@@add?type=Document`
8 |
9 | Display the form to add a new content in the current context folder. The content-type is specified in the query string.
10 |
11 | @@edit
12 | ------
13 |
14 | Example: `http://localhost:4200/site/folder1/@@edit`
15 |
16 | Display the current context in an edit form.
17 |
18 | @@layout
19 | --------
20 |
21 | Example: `http://localhost:4200/site/folder1/@@layout`
22 |
23 | Display the layout editor for current context.
24 |
25 | TO BE IMPLEMENTED
26 |
27 | @@login
28 | -------
29 |
30 | Example: `http://localhost:4200/site/@@login`
31 |
32 | Display the login form.
33 |
34 | @@search
35 | --------
36 |
37 | Example: `http://localhost:4200/site/@@search?SearchableText=RESTAPI`
38 |
39 | Display the search results for the specified criteria.
40 |
41 | @@sharing
42 | ---------
43 |
44 | Example: `http://localhost:4200/site/folder1/@@sharing`
45 |
46 | Display the sharing form for the current context.
47 |
48 | TO BE IMPLEMENTED
49 |
50 | @@view
51 | ------
52 |
53 | Example: `http://localhost:4200/site/folder1` or `http://localhost:4200/site/folder1/@@view`
54 |
55 | Display the current context.
56 |
--------------------------------------------------------------------------------
/docs/setup.rst:
--------------------------------------------------------------------------------
1 | Installation
2 | ============
3 |
4 | NodeJs
5 | ------
6 |
7 | We will need NodeJS 6.10+.
8 |
9 | We recommend using NVM to install NodeJS.
10 |
11 | Install nvm on our system using the instructions and provided script at:
12 |
13 | https://github.com/creationix/nvm#install-script
14 |
15 | Using ``nvm`` we will look up the latest LTS version of node.js and install it::
16 |
17 | $ nvm ls-remote --lts
18 | $ nvm install 6.10
19 |
20 | Then, each time we want to use this version of NodeJS, we just type::
21 |
22 | $ nvm use 6.10
23 |
24 | Angular CLI
25 | -----------
26 |
27 | `Angular CLI `_ is the commande line interface provided by Angular.
28 |
29 | .. note::
30 |
31 | We need CLI 1.0.0+
32 |
33 | We install it with NPM::
34 |
35 | $ npm install -g @angular/cli
36 |
37 | The ``-g`` option install the CLI globally, meaning it is available wherever we activate our NVM.
38 |
39 | ``ng`` will be available from the command line and we are ready to bootstrap an application.
40 |
41 | Backend
42 | -------
43 |
44 | We need a running instance providing the Plone REST API.
45 |
46 | TODO: provide deployment options here.
47 |
48 | Setup a new Angular project
49 | ---------------------------
50 |
51 | Enter the command::
52 |
53 | $ ng new myapp
54 |
55 | It will setup a standard Angular project structure and install all the default dependencies.
56 |
57 | The app can be served locally with::
58 |
59 | $ ng serve
60 |
61 | The result can be seen on http://localhost:4200, and any change in the project code triggers an automatic reload of the page.
62 |
63 | Add the @plone/restapi-angular dependency
64 | -----------------------------------------
65 |
66 | Stop the local server and type::
67 |
68 | $ npm install @plone/restapi-angular --save
69 |
70 | Note: the ``--save`` option ensures the dependency is added in our ``package.json``.
71 |
72 | We are now ready to use Plone Angular SDK.
73 |
--------------------------------------------------------------------------------
/mrs.developer.json:
--------------------------------------------------------------------------------
1 | {
2 | "ngx-schema-form": {
3 | "path": "/projects/schema-form/src/lib",
4 | "url": "git@github.com:guillotinaweb/ngx-schema-form.git",
5 | "https": "https://github.com/guillotinaweb/ngx-schema-form.git",
6 | "branch": "angular7-2"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "restapi-angular",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "start": "ng serve",
7 | "build": "ng build",
8 | "test": "jest --no-cache",
9 | "test:watch": "jest --watch",
10 | "test:ci": "jest --runInBand --ci",
11 | "lint": "ng lint",
12 | "e2e": "ng e2e"
13 | },
14 | "private": true,
15 | "dependencies": {
16 | "@angular/animations": "~7.2.0",
17 | "@angular/common": "~7.2.0",
18 | "@angular/compiler": "~7.2.0",
19 | "@angular/core": "~7.2.0",
20 | "@angular/forms": "~7.2.0",
21 | "@angular/http": "^7.2.15",
22 | "@angular/platform-browser": "~7.2.0",
23 | "@angular/platform-browser-dynamic": "~7.2.0",
24 | "@angular/router": "~7.2.0",
25 | "angular-traversal": "^1.1.0",
26 | "core-js": "^2.5.4",
27 | "rxjs": "~6.3.3",
28 | "tslib": "^1.9.0",
29 | "zone.js": "~0.8.26",
30 | "z-schema": "^3.24.1"
31 | },
32 | "devDependencies": {
33 | "@angular-devkit/build-angular": "~0.13.0",
34 | "@angular-devkit/build-ng-packagr": "~0.13.0",
35 | "@angular/cli": "~7.3.6",
36 | "@angular/compiler-cli": "~7.2.0",
37 | "@angular/language-service": "~7.2.0",
38 | "@types/jasmine": "~2.8.8",
39 | "@types/jasminewd2": "~2.0.3",
40 | "@types/jest": "^24.0.11",
41 | "@types/node": "~8.9.4",
42 | "codelyzer": "~4.5.0",
43 | "jest": "^24.8.0",
44 | "jest-preset-angular": "^7.0.1",
45 | "mrs-developer": "^1.1.0",
46 | "ng-packagr": "^4.2.0",
47 | "protractor": "~5.4.0",
48 | "ts-node": "~7.0.0",
49 | "tsickle": ">=0.34.0",
50 | "tslib": "^1.9.3",
51 | "tslint": "~5.11.0",
52 | "typescript": "~3.2.2"
53 | },
54 | "jest": {
55 | "preset": "jest-preset-angular",
56 | "setupFilesAfterEnv": [
57 | "/src/setupJest.ts"
58 | ],
59 | "testPathIgnorePatterns": [
60 | "/node_modules/",
61 | "test.ts"
62 | ]
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/projects/plone-restapi-angular/README.md:
--------------------------------------------------------------------------------
1 | # PloneRestapiAngular
2 |
3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 7.2.0.
4 |
5 | ## Code scaffolding
6 |
7 | Run `ng generate component component-name --project plone-restapi-angular` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project plone-restapi-angular`.
8 | > Note: Don't forget to add `--project plone-restapi-angular` or else it will be added to the default project in your `angular.json` file.
9 |
10 | ## Build
11 |
12 | Run `ng build plone-restapi-angular` to build the project. The build artifacts will be stored in the `dist/` directory.
13 |
14 | ## Publishing
15 |
16 | After building your library with `ng build plone-restapi-angular`, go to the dist folder `cd dist/plone-restapi-angular` and run `npm publish`.
17 |
18 | ## Running unit tests
19 |
20 | Run `ng test plone-restapi-angular` to execute the unit tests via [Karma](https://karma-runner.github.io).
21 |
22 | ## Further help
23 |
24 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
25 |
--------------------------------------------------------------------------------
/projects/plone-restapi-angular/ng-package.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3 | "dest": "../../dist/plone-restapi-angular",
4 | "lib": {
5 | "entryFile": "src/public-api.ts"
6 | }
7 | }
--------------------------------------------------------------------------------
/projects/plone-restapi-angular/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@plone/restapi-angular",
3 | "version": "2.2.0",
4 | "repository": {
5 | "type": "git",
6 | "url": "git+https://github.com/plone/plone.restapi-angular.git"
7 | },
8 | "author": "Plone Community",
9 | "license": "MIT",
10 | "bugs": {
11 | "url": "https://github.com/plone/plone.restapi-angular/issues"
12 | },
13 | "homepage": "https://github.com/plone/plone.restapi-angular#readme",
14 | "peerDependencies": {
15 | "@angular/common": "^7.2.0",
16 | "@angular/core": "^7.2.0",
17 | "angular-traversal": "^1.1.0"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/projects/plone-restapi-angular/src/lib/components/breadcrumbs.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 | import { By } from '@angular/platform-browser';
3 | import {
4 | HttpClientTestingModule
5 | } from '@angular/common/http/testing';
6 | import { Injectable, EventEmitter } from '@angular/core';
7 | import { APP_BASE_HREF } from '@angular/common';
8 | import { Traverser, TraversalModule, Resolver, Marker, Normalizer, Target } from 'angular-traversal';
9 | import {
10 | TypeMarker,
11 | PloneViews,
12 | RESTAPIResolver,
13 | FullPathNormalizer,
14 | } from '../traversal';
15 |
16 | import { ConfigurationService } from '../services/configuration.service';
17 | import { APIService } from '../services/api.service';
18 | import { CommentsService } from '../services/comments.service';
19 | import { NavigationService } from '../services/navigation.service';
20 | import { AuthenticationService } from '../services/authentication.service';
21 | import { ResourceService } from '../services/resource.service';
22 | import { Services } from '../services';
23 | import { Breadcrumbs } from './breadcrumbs';
24 | import { LoadingService } from '../services/loading.service';
25 | import { CacheService } from '../services/cache.service';
26 | import { of } from 'rxjs';
27 |
28 | @Injectable()
29 | class MockResourceService {
30 |
31 | resourceModified = new EventEmitter();
32 | breadcrumbs(path: string) {
33 | return of([
34 | {
35 | "title": "A folder",
36 | "url": "http://fake/Plone/a-folder"
37 | },
38 | {
39 | "title": "test",
40 | "url": "http://fake/Plone/a-folder/test"
41 | }
42 | ]);
43 | }
44 | }
45 |
46 | describe('Breadcrumbs', () => {
47 | let component: Breadcrumbs;
48 | let fixture: ComponentFixture;
49 |
50 | beforeEach(async(() => {
51 | TestBed.configureTestingModule({
52 | declarations: [Breadcrumbs],
53 | imports: [HttpClientTestingModule, TraversalModule],
54 | providers: [
55 | APIService,
56 | AuthenticationService,
57 | ConfigurationService,
58 | {
59 | provide: 'CONFIGURATION', useValue: {
60 | BACKEND_URL: 'http://fake/Plone',
61 | }
62 | },
63 | CacheService,
64 | CommentsService,
65 | LoadingService,
66 | NavigationService,
67 | TypeMarker,
68 | RESTAPIResolver,
69 | PloneViews,
70 | Services,
71 | Traverser,
72 | { provide: Resolver, useClass: RESTAPIResolver },
73 | { provide: Marker, useClass: TypeMarker },
74 | { provide: APP_BASE_HREF, useValue: '/' },
75 | { provide: Normalizer, useClass: FullPathNormalizer },
76 | { provide: ResourceService, useClass: MockResourceService },
77 | ],
78 | })
79 | .compileComponents();
80 | }));
81 |
82 | beforeEach(() => {
83 | fixture = TestBed.createComponent(Breadcrumbs);
84 | component = fixture.componentInstance;
85 | fixture.detectChanges();
86 | component.services.resource.resourceModified.emit();
87 | });
88 |
89 | it('should create', () => {
90 | expect(component).toBeTruthy();
91 | });
92 |
93 | it('should provide links', () => {
94 | component.onTraverse({ contextPath: '/', context: {} });
95 | expect(component.links.length).toBe(2);
96 | });
97 |
98 | it('should have active class on last link', () => {
99 | let activeLink: HTMLElement;
100 | component.onTraverse({ contextPath: '/a-folder/test', path: '/a-folder/test', context: {} });
101 | fixture.detectChanges();
102 | activeLink = fixture.debugElement.query(By.css('.active')).nativeElement;
103 | expect(activeLink.innerHTML).toContain('test');
104 | });
105 | });
106 |
--------------------------------------------------------------------------------
/projects/plone-restapi-angular/src/lib/components/breadcrumbs.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { Services } from '../services';
3 | import { TraversingComponent } from '../traversing';
4 | import { NavLink } from '../interfaces';
5 | import { Target } from 'angular-traversal';
6 |
7 |
8 | @Component({
9 | selector: 'plone-breadcrumbs',
10 | template: `
11 |
12 |