diff --git a/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.api.php b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.api.php new file mode 100644 index 0000000..a563f32 --- /dev/null +++ b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.api.php @@ -0,0 +1,21 @@ +getAccessControlHandler('node'); + $access = $access_handler->createAccess('article'); + + foreach ($jsonapi_response['data'] as $key => $item) { + if ($item['type'] == 'articles') { + $jsonapi_response['data'][$key]['attributes']['editable'] = $access; // append attributes to display edit link in front end. + } + } + } +} \ No newline at end of file diff --git a/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.services.yml b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.services.yml new file mode 100644 index 0000000..77b44a2 --- /dev/null +++ b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.services.yml @@ -0,0 +1,8 @@ +services: + jsonapi_assessment.response_subscriber: + class: Drupal\jsonapi_assessment\EventSubscriber\ResponseSubscriber + arguments: [ '@module_handler' ] + tags: + - { name: event_subscriber } + calls: + - [ setRouteMatch, [ '@current_route_match' ] ] diff --git a/drupal/web/modules/custom/jsonapi_assessment/src/EventSubscriber/ResponseSubscriber.php b/drupal/web/modules/custom/jsonapi_assessment/src/EventSubscriber/ResponseSubscriber.php new file mode 100644 index 0000000..f20b0da --- /dev/null +++ b/drupal/web/modules/custom/jsonapi_assessment/src/EventSubscriber/ResponseSubscriber.php @@ -0,0 +1,113 @@ +moduleHandler = $moduleHandler; + } + + /** + * Create a new instance. + * + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container + * The container. + * + * @return \Drupal\jsonapi_assessment\EventSubscriber\ResponseSubscriber + * The new instance. + */ + public static function create(ContainerInterface $container) { + return new self( + $container->get('module_handler') + ); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + $events[KernelEvents::RESPONSE] = ['onResponse']; + + return $events; + } + + /** + * Set route match service. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match service. + */ + public function setRouteMatch(RouteMatchInterface $route_match) { + $this->routeMatch = $route_match; + } + + /** + * This method is called the KernelEvents::RESPONSE event is dispatched. + * + * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event + * The filter event. + */ + public function onResponse(FilterResponseEvent $event) { + if (!$this->routeMatch->getRouteObject()) { + return; + } + + if ( + $this->routeMatch->getRouteName() === 'jsonapi.resource_list' || + Routes::isJsonApiRequest($this->routeMatch->getRouteObject() + ->getDefaults()) + ) { + + $response = $event->getResponse(); + $content = $response->getContent(); + + $jsonapi_response = json_decode($content, TRUE); + + if (!is_array($jsonapi_response)) { + return; + } + + // call the hook aler + $this->moduleHandler->alter('jsonapi_response', $jsonapi_response, $response); + $response->setContent(json_encode($jsonapi_response)); + } + } + +} diff --git a/react/api/article.js b/react/api/article.js index ea0b667..a352df7 100644 --- a/react/api/article.js +++ b/react/api/article.js @@ -8,9 +8,10 @@ import request from '../utils/request'; */ export const getAll = () => new Promise((resolve, reject) => { request - .get('/api/articles') + .get('/api/articles/') .query({ 'fields[node--article]': 'id', + 'include': 'image' }) // Tell superagent to consider any valid Drupal response as successful. // Later we can capture error codes if needed. @@ -28,3 +29,27 @@ export const getAll = () => new Promise((resolve, reject) => { reject(error); }); }); + +export const getById = (id) => new Promise((resolve, reject) => { + console.log(id); + request + .get('/api/articles/' + id) + .query({ + }) + // Tell superagent to consider any valid Drupal response as successful. + // Later we can capture error codes if needed. + .ok((resp) => resp.statusCode) + .then((response) => { + console.log(response.body); + resolve({ + // eslint-disable-next-line max-len + article: response.statusCode === 200 ? transforms.articleDetail(response.body.data) : {}, + statusCode: response.statusCode, + }); + }) + .catch((error) => { + // eslint-disable-next-line no-console + console.error('Could not fetch the article detail.', error); + reject(error); + }); +}); diff --git a/react/pages/index.js b/react/pages/index.js index 4836264..6bba2b5 100644 --- a/react/pages/index.js +++ b/react/pages/index.js @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import * as articleApi from '../api/article'; +import Link from "next/link" class HomePage extends React.Component { static async getInitialProps() { @@ -15,6 +16,7 @@ class HomePage extends React.Component { } catch (e) { // Pass status code as internal properly. It is being checked inside of // render() method of _app.js. + console.log(e); initialProps.statusCode = 500; } @@ -23,12 +25,19 @@ class HomePage extends React.Component { render() { const { articles } = this.props; + return (
Home page is working!

List of articles from Drupal:
); @@ -37,8 +46,10 @@ class HomePage extends React.Component { HomePage.propTypes = { articles: PropTypes.arrayOf(PropTypes.shape({ - title: PropTypes.string, id: PropTypes.string, + title: PropTypes.string, + body: PropTypes.string, + editable: PropTypes.bool })), };