Архив: Июль 2017

Акция «Космос Возможностей»: скидки на Битрикс24 от 12 до 30%

Битрикс24 предлагает вам безграничный «космос возможностей» для организации организации работы компании и управления продаж. Просто выберите тариф, который вам больше подходит и получите весь комплекс инструментов с повышенной скидкой – до 30%.

Источник: http://www.1c-bitrix.ru/about/life/news/6032675/

Акция «Космос Возможностей»: скидки на Битрикс24 от 12 до 30%

Битрикс24 предлагает вам безграничный «космос возможностей» для организации организации работы компании и управления продаж. Просто выберите тариф, который вам больше подходит и получите весь комплекс инструментов с повышенной скидкой – до 30%.

Источник: https://www.1c-bitrix.ru/about/life/news/6032675/

Как организовать REST API в Drupal 8 (Евгений Ильин) [DrupalCamp Краснодар 2016]

А теперь у нас мощный доклад от Евгения Ильина, который на Drupal Camp Краснодар 2016 рассказал о том, как организовать Rest Api на Drupal 8
Видео здесь: https://www.youtube.com/watch?v=Fsa8Dwu4Ewo (Не забудьте ПОДПИСАТЬСЯ!)
Репостим, отдаём свои лайки и естественно подписываемся на нашу группу, чтобы видеть и следующие доклады!

>> Все презентации с конференции “DrupalCamp Краснодар 2016″

Версия Drupal:  Drupal 8.* Drupal 7.* Ключевые слова:  DrupalCamp DrupalYug




email





facebook





linkedin





twitter





google+





pinterest
Форумы:  Drupal Юг 0 Спасибо

Источник: http://drupal.ru/node/134141

Интересный способ получить список категорий бренда в Drupal

Получение списка категорий бренда – с виду довольно тривиальная задача, но при её решении всплывают подводные камни. Давайте разберёмся: как правило, в интернет-магазинах товары классифицируются как минимум по двум словарям – каталог и бренд. Например, товар под названием “мобильный телефон” относится к термину “мобильные телефоны” из словаря “каталог” и к термину “Завод имени Ленина” из словаря “производители”. Довольно часто заказчик ставит перед разработчиком задачу отобразить на странице производителя все категории, в которых у производителя есть товары. Т.е. на странице “Завод имени Ленина” необходимо отобразить ссылки на разделы “мобильные телефоны”, “холодильники”, “ядерные боеголовки”. Любой, кто знаком с друпалом, но не сталкивался с решением этой задачи, с ходу скажет, что это решается за 1 минуту через Views. Однако, на самом деле всё не так просто. Сразу напрашивается алгоритм – выводим материалы, с контекстным фильтром по бренду, отображаем только поле “Каталог” и дело якобы в шляпе. Но ведь товаров могут быть тысячи, поэтому категории многократно продублируются, а поскольку вьюс сделан по нодам, то ни уникальность запроса, ни агрегация нам не помогут. Не поможет также и группировка полей, т.к. помимо поля группировки, надо вывести ещё что-нибудь. Можно конечно же раздраконить шаблон представления, убрать оттуда вывод $rows, оставить только заголовки, но это костыль, ведь вьюс всё равно будет собирать тысячи товаров, которые не будет выводить.

Именно поэтому я решил, что оптимально будет написать свой запрос в базу, чтобы получить айдишники нужных терминов, а далее уже как-нибудь их обработать – либо вывести кодом, либо передать айдишники во views, и там уже настроить вывод, как душе угодно. Сам запрос делается в таблицу taxonomy_index, а для того, чтобы получить термины другого словаря, мы просто приджойним эту таблицу к самой себе. Собственно, код:

<?php
// Select terms
  $query = db_select('taxonomy_index', 'ti');
  $query->innerJoin('taxonomy_index', 'ti2', 'ti.nid=ti2.nid');
  // Если вам не нужно название термина, то эту строку можно пропустить
  $query->innerJoin('taxonomy_term_data', 'td', 'td.tid=ti2.tid');
  $query->fields('ti2', array('tid'));
  // и эту тоже
  $query->fields('td', array('name'));
  $query->condition('ti.tid', $args[0]);
  $query->condition('ti2.tid', $args[0], '<>');
  $query->distinct();
  $terms = $query->execute()->fetchAll();
?>

Приведённый код я использовал в своём Custom Ctools content type, поэтому аргумент с айдишником бренда указан как $args[0], естественно, вы можете использовать это и в другом контексте, например, в кастомном модуле, блоке, шаблоне и т.д. Из полученных айдишников я сгенерировал ссылки вида catalog/%category/%brand, которые ведут на страницы с вьюсами с двумя контекстными фильтрами, чтобы показать товары, относящиеся одновременно и к указанной категории, и к бренду.

В общем, берите и пользуйтесь, а если у вас есть другие способы решения этой задачи, то готов услышать вас в комментариях.

Ссылка на первоисточник в моём блоге

Тип материала:  Предлагаю решение Версия Drupal:  Drupal 7.* Ключевые слова:  Drupal Таксономия




email





facebook





linkedin





twitter





google+





pinterest
Форумы:  FAQ 5 Спасибо

Источник: http://drupal.ru/node/134125

Системных администраторов поздравляю с профессиональным праздником

День системного администратора (также известен как День сисадмина) — праздник, который отмечается в последнюю пятницу июля с целью выражения признательности сотрудникам, выполняющим обязанности системных администраторов.

Это нелегкий, а порой даже незаметный обычному человеку и иногда даже неблагодарный труд.
Ибо хороший сисадмин, это когда пользователи и не подозревают что он есть))))

Мое вам уважение и благодарность за труд!
С днем Сисадмина!

Отдельный поклон команде, поддерживающей работоспособность нашего форума!






email





facebook





linkedin





twitter





google+





pinterest
2 Спасибо

Источник: http://drupal.ru/node/134091

Первое правило дизайна – никому не говорить о дизайне (Вадим Кендюхов) [DrupalCamp Краснодар 2016]

А сегодня у нас доклад Вадима Кендюхова о дизайне, куда, где и как правильно его применять. Ещё один доклад с Drupal Camp 2016 Краснодар, который достоин лайков, репостов и подписки на нашу группу!
Презентация лежит вот по этому адресу -> https://www.slideshare.net/DrupalYug/ss-73641529/1
Видео: https://www.youtube.com/watch?v=9WTMWqwvkbc

>> Все презентации с конференции “DrupalCamp Краснодар 2016″

Версия Drupal:  Drupal 8.* Drupal 7.* Ключевые слова:  DrupalCamp DrupalYug




email





facebook





linkedin





twitter





google+





pinterest
Форумы:  Drupal Юг 0 Спасибо

Источник: http://drupal.ru/node/134087

Как работать с конфигурациями в Drupal 8 (Александр Дубовской) [DrupalCamp Краснодар 2016]

Очередной доклад с DrupalCamp 2016 Краснодар от Александра Дубовского в котором он расскажет о том, как
работать с конфигурациями в Drupal.

Видео здесь: https://www.youtube.com/watch?v=oWM5xgp8NyU (Не забудьте ПОДПИСАТЬСЯ!)
Презентация: https://www.slideshare.net/DrupalYug/drupal-8-73641490
Лайки, репосты и подписка это то, что нужно не только нам, но и вам, ведь ещё так много интересных докладов!

>> Все презентации с конференции “DrupalCamp Краснодар 2016″

Версия Drupal:  Drupal 8.* Drupal 7.* Ключевые слова:  DrupalCamp DrupalYug




email





facebook





linkedin





twitter





google+





pinterest
Форумы:  Drupal Юг 2 Спасибо

Источник: http://drupal.ru/node/134064

Инструменты для SEO в CMS Drupal 7.x/8.x.x (Пётр Селфин) [DrupalCamp Краснодар 2016]

Какой бы крутой сайт не был сделан, все усилия будут напрасны, если его никто не посетит. А с помощью чего вывести сайт в топ я расскажу в своём докладе про инструменты SEO в Drupal.
Видео: https://www.youtube.com/watch?v=uEIrLr42OyE (Не забудьте ПОДПИСАТЬСЯ!)
Презентация: https://www.slideshare.net/DrupalYug/seo-cms-drupal

Лайки, репосты и подписка всё также радуют нас!

>> Все презентации с конференции “DrupalCamp Краснодар 2016″

Версия Drupal:  Drupal 8.* Drupal 7.* Ключевые слова:  DrupalCamp DrupalYug




email





facebook





linkedin





twitter





google+





pinterest
Форумы:  Drupal Юг 0 Спасибо

Источник: http://drupal.ru/node/134058

Drupal-школа – пятое занятие: связывание раздела на сайте и типа материала на Drupal 8

Практическое занятие по связыванию раздела на сайте и типа материала на Drupal 8.

Содержание: создание терма таксономии, связанной с разделами сайта; добавление поля для связи с разделом в нужный тип материала; добавление раздела в навигационное меню; настройка видимости поля раздела в материале.

Фрагмент занятия от 8.02.2017.

Drupal-школа – проект, посвященный обучению школьников (13 гимназия, г. Новосибирск) веб-разработке на основе CMS Drupal 8. Поддерживается администрацией школы, сибирским сообществом друпаллеров DrupalSib и группой компаний i20.

Версия Drupal:  Drupal 8.* Ключевые слова:  друпалшкола




email





facebook





linkedin





twitter





google+





pinterest
Форумы:  DrupalSib 1 Спасибо

Источник: http://drupal.ru/node/133906

Про RestFul в Drupal 8

Как-то мой друг сказал, что Drupal 8 – это ползающий ребенок, который не понимает, что происходит вокруг. За этим смешно наблюдать, но всегда нужно быть на чеку.

В общем-то, он прав. Но я бы хотел поделиться чем-то, что мне нравится и что уже успешно применено на практике.

Речь пойдет о RESTful Web Services API.

Эта новинка Drupal 8 дает возможность сторонним разработчикам использовать (и изменять) данные приложений. Например, взаимодействие с мобильными приложениями или фронтэнд построен таким образом, что от сервера требуются только данные, а отрисовка HTML происходит на клиенте.

Эти функции как-то в один момент сглаживают неуклюжесть младенца и сразу появляется желание понаблюдать за ним еще, не правда ли? Давайте разбираться дальше.

Методы HTTP

GET для получения данных (SELECT).

В случае “удачного” (или не содержащего ошибок) адреса, GET возвращается представление ресурса в формате XML или JSON (в зависимости от значения переменной _format) в сочетании с кодом состояния HTTP 200 (OK).
В случае наличия ошибок обычно возвращается код 404 (NOT FOUND) или 400 (BAD REQUEST).

По этому поводу есть отличный пример:

        GET http://example.com/api/v1/program/1?_format=json
        HEADERS: Content-Type: application/json POST для добавления данных (INSERT)

При успешном создании ресурса возвращается HTTP код 201, а также в заголовке ‘Location’ передается адрес созданного ресурса.

Пример:

        GET http://example.com/entity/user/?_format=json
        HEADERS:
                Content-Type: application/json
                Authorization: Basic XXXX
                X-CSRF-Token: XXXX  - получить его можно по этому пути http://example.com/rest/session/token
        BODY:
                {
                        "name":[{"value":"test"}],
                        "status":[{"value":"1"}],
                        "mail":[{"value":"

Приобретаем нужные стройматериалы и инструмент.

Все люди когда-нибудь обязательно помогали в строительстве дачи или коттеджа, а возможно делали отделку квартиры. Читать далее

Как строить ваш дом теплым?

Собственный дом – в настоящее время заветная мечта почти каждого. Читать далее

Дополнения браузеров для SEO оптимизатора

Многие сервисы, созданные для помощи в продвижении сайтов, выпускают дополнения для популярных проводников таких Mozilla FireFox и Google Chrome, рассмотрим некоторые из них.

Источник: https://dle-news.ru/blog/1724-dopolneniya-brauzerov-dlya-seo-optimizatora.html

Великолепный nuxt.js шаблон приложения vue.js и drupal 8 в одной коробке

Прелесть drupal в том, что это комбайн, с которым один человек может осилить непомерный груз фулстек разработки веб ресурса.

Мы же понимаем, что ни один здравомыслящий фронтэнд разработчик не будет планировать drupal для api,
но… Drupal тоже может)

В этом обзоре я рассмотрю установку каркаса проекта с акцентом на удобства разработчика.

Цель: локальная среда для фулстек разработки на базе drupal8 и vue.js

Выбрав ЯП, принимаем соответствующий менеджер зависимостей.

В этом примере применяются: php, js, ruby

Следовательно, используем composer, npm, bundler

Руби используем с одной целью, пакет foreman позволит запустить в одном сеансе наши локальные сервера разработчиков.

Создадим каталог проекта

mkdir application

Сфокусируем внимание на построении каркаса приложения.

Первой командой соберем фронтенд

vue init nuxt/starter app

Второй командой соберем бэкенд

composer create-project drupal-composer/drupal-project:8.x-dev api –stability dev –no-interaction

Создадим Gemfile и укажем в нем foreman

# Gemfile
gem ‘foreman’

Установим

bundle install

Настроим

# Procfile.dev
vue: npm –prefix $(pwd)/app run dev
drupal: drush rs –root=$(pwd)/api/web

Теперь у нас есть возможность запуска обоих приложений:

foreman start -f Procfile.dev

Создадим скрипт обертку для этой команды

mkdir bin
touch bin/server
echo "foreman start -f Procfile.dev" > bin/server
chmod +x bin/server

Запуск

./bin/server

Для обслуживания приложений приходиться перемещаться в их корневые каталоги.

Например для добавления в проект axios:

cd app
yarn add axios

Или, для добавления модулей и установки drupal:

cd ../api
composer require jsonapi simple_oauth devel
cd web
drush si –db-url=sqlite://sites/default/files/.ht.sqlite

В итоге получаем полное разделение:
отдельное серверное приложение на базе drupal 8 организует api для доступа клиентского приложения к данным,
отдельное клиентское приложение на базе nuxt.js обеспечивает интерфейс пользователя.


Документация для работы со стеком nuxt.js drupal8:

https://babeljs.io/learn-es2015/ https://ru.vuejs.org/v2/guide/ https://ru.nuxtjs.org/guide https://github.com/mzabriskie/axios https://github.com/drupal-composer/drupal-project https://www.youtube.com/watch?v=–ZL3EAhnwc&list=PLZOQ_ZMpYrZsyO-3IstImK1okrpfAjuMZ https://www.youtube.com/watch?v=rTcC0maPLSA&list=PLZOQ_ZMpYrZtqy5-o7KoDhM3n6M0duBjX

Исходный код примера в репозитории на GitLab:

https://gitlab.com/multpix/vue_drupal Тип материала:  Предлагаю решение Версия Drupal:  Drupal 8.* Ключевые слова:  Headless Vue.js Модули и темы:  jsonapi simple_oauth




email





facebook





linkedin





twitter





google+





pinterest
Форумы:  Установка и настройка 2 Спасибо

Источник: http://drupal.ru/node/133837

Что такое headless Drupal?


В последнее время идёт очень много разговоров о headless (иногда ещё его называют decoupled) Drupal. Давайте попробуем разобраться, что же это такое и какие преимущества это может нам дать. Headless означает “безголовый”, т.е. друпалу просто взяли и зачем-то оторвали голову, как в том анекдоте про змею:

«- Давайте отрубим ей хлебало!
- Нет, давайте лучше отрубим ей хвост!
- Точно! По самое хлебало!»

Этот анекдот весьма уместен в нашем контексте, ибо в концепции headless Drupal под головой понимается именно то, что многие привыкли называть “мордой”, т.е. весь слой темизации – сама тема и всё, что отвечает непосредственно за рендеринг html. Второе название этой концепции – decoupled – означает “разделённый”, что подразумевает, то, что функции рендеринга где-то всё же выполняются, но не в друпале. В общем, в headless-системах Drupal отдаёт данные не в виде HTML-страниц, а посредством REST-сервисов в форматах JSON, XML, HAL и т.д. Основные кейсы применения такого подхода приблизительно следующие:

– когда доступ к контенту осуществляется посредством мобильных приложений;
– когда контент изначально предназначен для отправки в другую систему (автоматизированный обмен данными);
– когда нужно сделать обычный сайт;

Если с первыми двумя пунктами всё понятно, то третий наверняка у многих вызывает вопросы, ведь нормально же работали годами, а тут какой-то хэдлес появился. Типичный кейс, когда такой подход будет наиболее выигрышным – это сайт с обилием динамических элементов страниц и с большим количеством форм, например, соцсеть или CRM-система. Однако даже для простеньких бложиков такой подход может дать множество преимуществ, но об этом чуть позже, сперва давайте разберёмся, что нужно для построения такой системы. Возможно, вы уже догадались, что фронтенд и бэкенд в таком случае будут двумя совершенно раздельными приложениями. По сути, это два разных сайта, расположенных в разных доменах (субдоменах)

Backend

В качестве бэкенда необходимо взять Drupal 8. Ни в коем случае не 7, т.к. там глубина интеграции с REST-сервисами изначально не такая большая, как в восьмёрке. Достаточно включить модуль Rest, входящий в ядро, и уже можно получать, создавать, удалять через REST любые сущности, а также создавать вьюсы в формате REST-экспорта. Однако, “родной” формат, в котором Drupal 8 выдаёт JSON, изначально не совсем удобен для работы, поэтому я также рекомендую установить модуль JSONAPI, с ним вам даже не понадобится включать Views, но это отдельная история, заслуживающая целой публикации (которую я планирую написать в ближайшее время).

Frontend

В качестве фронтенда берём любой актуальный javascript-фреймворк, например React или Vue. Для тех, кто любит мастерить велосипеды и составлять картину мира из миллионов маленьких фрагментов, предпочтителен React, для тех же, кто привык следовать чётко выверенным инструкциям, лучше выбрать Vue. Глобально же никакой особой разницы нет.

Сервер

Если вы ленивый идиот начинающий разработчик и привыкли деплоить сайты по FTP, то вы сможете разместить свой сайт на любом хостинге, правда о сервер-сайд рендеринге (SSR) придётся забыть. Если же вы привыкли пользоваться системой контроля версий, то вам будет необходим как минимум виртуальный сервер, чтобы вы смогли установить на нём Node.js – это позволит вам собирать фронтенд-приложение из исходников прямо на сервере с учётом всех переменных окружения.

В итоге получается приблизительно так: в домене site.com располагается файл index.html, который также подгружает скрипты и стили. Сами же данные забираются с домена backend.site.com и отображаются в вашем фронтенд-приложении. Роутинг (обработка ссылок) при этом происходит не на сервере, а во фронетнд-приложении, это называется клиентский роутинг. Т.е. по сути вы загружаете одну единственную HTML-страницу, которая сама решает, как отображать нужные данные. Именно поэтому такие приложения часто называют SPA – Single Page Application (одностраничное приложение). Яркие примеры таких приложений – Facebook, Gitter, LinkedIn.

Зачем мне всё это?

Самая важная проблема, стоящая на пути освоения новых технологий – это мотивация. Я постараюсь вам её дать Если в двух словах, то при построении сайтов по принципу headless Drupal + какой-нибудь современный js-фреймворк вы легко сможете делать сайты с реально крутым и быстрым интерфейсом. При этом для разработчика появляются следующие преимущества:

1. То, что раньше вы делали с помощью JQuery, теперь можно делать значительно быстрее. Ведь в JQuery для обработки какого-либо события приходилось отлавливать само событие и потом к нему цеплять логику обработки элементов страницы. С использованием современных фреймворков это не нужно, т.к. большинство из них поддерживают “реактивность” – это связанность отображения с данными. Т.е. если элемент выводит некий переменный текст, достаточно указать, что он выводит некую переменную, и затем, при обновлении значения переменной элемент перерисуется автоматически.

2. В разы ускоряется настройка самого друпала. Если вы используете JSONAPI, то всё, что вам нужно – это создать необходимые типы контента и добавить им нужные поля. И всё! Не нужно настраивать отображение, не нужно делать вьюсы. Буквально полчаса настройки и можно переходить к проектированию фронтенда.

3. Больше не нужно устанавливать или писать самому модули для “украшательств”. Больше не понадобится писать hook_form_alter, чтобы повесить на поле “.col-sm-3″. Больше не надо мучаться с AJAX-коллбэками. Для динамических форм вам больше не нужен богомерзкий “#states”.

4. Снижается нагрузка на сервер. При запросе данных через jsonapi часто происходит неполный бутстрап друпала, не вызываются функции темизации, не вызывается ничего лишнего, ведь при запросе ноды вы получите только ноду, а не кучу контента из хэдера, футера, сайдбаров, менюшек и т.д. А некоторые страницы фронтенд-приложение и вовсе сможет обрабатывать без запросов к серверу.

5. За этим будущее. Со временем люди забудут про спиннеры, перестанут пускать туман с запахом печенья, отнесут гироскутер на балкон или в подвал, но хайп вокруг SPA-приложений не утихнет ещё очень долго.

Я знаю, о чём вы сейчас подумали.

Действительно, если нам в друпале не нужно делать ничего, связанного с темизацией, то нам придётся сделать это в javascript. Однако, спешу вас заверить – это не так сложно, как кажется. Один из основных принципов разработки фронтенда на javascript – это использование готовых компонентов. Хотите галерею – вот вам готовая галерея, хотите графики строить – на выбор есть десятки компонентов разной степени навороченности, хотите всё сделать в стиле Material Design – получите полный сет стилизованных компонентов. Да, многие компоненты уже изначально поставляются со своими стилями, и бывает так, что на вёрстку практически не нужно тратить время. Кроме того, создавать собственные компоненты вовсе не сложно, равно как и совсем не сложно переопределить стили сторонних компонентов.

И традиционная ссылка на оригинал статьи в моём блоге

Тип материала:  Предлагаю решение Версия Drupal:  Drupal 8.* Ключевые слова:  Headless




email





facebook





linkedin





twitter





google+





pinterest
Форумы:  Установка и настройка 3 Спасибо

Источник: http://drupal.ru/node/133803

Что будет если соединить Drupal 8 и React.js узнали при переносе сайта

Эта статья о том, как уже существующий проект переносили на React.

Библиотека React считается быстрым из-за VirtualDOM. В компоненте есть метод render, который вызывается при каждом обновлении компонента. Затем результат рендера (здесь и далее под рендером будет иметься в виду именно вызов функции render компонента, а не рендер в реальный DOM) обрабатывается Реактом, сравнивается результат текущего рендера с результатом предыдущего и в реальный DOM вносятся только необходимые изменения, а не целиком. Учитывая, что операции с реальным DOM медленные, это должно быть быстрее.

React хорош тем, что его можно использовать с любым backend. При разворачивании проекта, запуск
npm run build приведет к созданию оптимизированной сборки приложения в build-папке.

В качестве документации был взят сайт https://facebook.github.io/react/.

Начнем мы с создания среды для успешной разработки на React.

npm install -g create-react-app
create-react-app my-app
 
cd my-app
npm start

Создали файл package.json, который является инструкцией/описанием для нашего проекта. Выглядит он таким образом:

{
  "name": "VelvetDev",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "axios": "^0.16.2",
    "jquery": "^3.2.1",
    "prop-types": "^15.5.10",
    "react": "^15.5.4",
    "react-dom": "^15.5.4",
    "react-popup": "^0.8.0",
    "react-slick": "^0.14.11",
    "react-validation": "^2.10.9",
    "slick-carousel": "^1.6.0",
    "validator": "^7.0.0"
  },
  "devDependencies": {
    "react-scripts": "1.0.7"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test –env=jsdom",
    "eject": "react-scripts eject"
  }
}

Заполним наш index.html файл

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <meta name="description" content="VelvetDev is a Drupal Development company that specialized in portals, social Network and E-commerce sites. Drupal is our passion. Drupal is our life. Drupal is our everything."/>
    <meta name="keywords" content=”drupal, drupal 7, drupal 8, php,
         development, site” />
 
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap-theme.min…>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css" />
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick-theme…. />
    <title>VelvetDev – Drupal Development company</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
    <div id="popupContainer"></div>
  </body>
</html>

Далее, запустим наш сайт с помощью команды npm start, это возможно, потому что у нас в файле package.json есть секция scripts, в которой прописана команда start.

Главный компонент App

Во главе всего приложения стоит большой начальник App/, который группирует все остальные компоненты и указывает им своим состоянием, когда нужно ре-рендерится. После инициализации приложения App/ проводит загрузку данных и обновляет содержимое страницы.

Наш сайт разделили на компоненты. App.js является главным родительским документом, в котором будем писать код. А также в нем мы импортируем код из других файлов, по которым был разбит сайт.

Файл app.js выглядит следующим образом:

import React, {Component} from ‘react’;
import ‘./App.css’;
import Header from ‘./components/Header/Header’;
import Welcome from ‘./components/Welcome/Welcome’;
import Services from ‘./components/Services/Services’;
import WhatWeDo from ‘./components/WhatWeDo/WhatWeDo’;
import Team from ‘./components/Team/Team’;
import Contacts from ‘./components/Contacts/Contacts’;
import Footer from ‘./components/Footer/Footer’;
import axios from ‘axios’;
 
const baseUrl = ‘YUOR_SITE’;
const suffixUrl = ‘YOUR_SUFFIX’;
 
class App extends Component {
 
  constructor(props) {
    super(props);
    this.state = {
      configData: {},
      xCSRFToken: ”
    };
  };
 
  componentDidMount() {
    axios.get(baseUrl + suffixUrl + ‘/jsonapi/config_pages/front_page’)
      .then(res => {
        if (res.status === 200) {
          const configData = res.data.data[0].attributes;
          this.setState({configData: configData});
        }
      });
    axios.get(baseUrl + suffixUrl + ‘/session/token’)
      .then(res => {
        if (res.status === 200) {
          this.setState({xCSRFToken: res.data});
        }
      });
  }
 
  render() {
    return (
      <div className="App">
        <Header configData={ this.state.configData }
                baseUrl={ baseUrl }
                xCSRFToken={ this.state.xCSRFToken } />
        <div className="wrapper">
          <div className="container-fluid">
            <Welcome configData={ this.state.configData } />
            <Services configData={ this.state.configData }
                      baseUrl={ baseUrl }
                      source={suffixUrl + "/api/v1/services"} />
            <WhatWeDo configData={ this.state.configData }
                      baseUrl={ baseUrl }
                      source={suffixUrl + "/api/v1/projects"} />
            <Team configData={ this.state.configData }
                  baseUrl={ baseUrl }
                  source={suffixUrl + "/api/v1/teams"} />
            <Contacts configData={ this.state.configData }
                      baseUrl={ baseUrl + suffixUrl }
                      xCSRFToken={ this.state.xCSRFToken } />
            <Footer configData={ this.state.configData }
                    baseUrl={ baseUrl }
                    source={suffixUrl + "/api/v1/social-links"} />
          </div>
        </div>
      </div>
    );
  }

}
 
export default App;

Опишем используемые для создания Velvetdev методы и компоненты

Создание класса: class App extends Component.

       Состояние
Задавая свойство state для текущего класса, мы говорим реакту: “Это данные, за которыми стоит следить”. При изменении состояния React будет проводить свои магические манипуляции с виртуальным DOM и заново рендерить все изменившиеся элементы. При использовании свойства state необходимо придерживаться одного простого правила: состояние задается присваиванием всего один раз при инициализации компонента. Другими словами, не стоит присваивать значения напрямую, а вместо этого использовать функцию setState. Событие onChange меняет состояние.

setStateng> изменяет состояние компонента и сообщает React, что этот компонент и его дочерние элементы должны быть повторно отображены с обновленным состоянием. Это основной метод, который мы используем для обновления пользовательского интерфейса в ответ на обработчики событий и ответы сервера.

Внутри этого класса мы создали конструктор, которому необходимо передать аргумент, содержащий все эти настройки (чаще всего называют просто props).

У каждого компонента могут быть свойства. Они хранятся в this.props, и передаются компоненту как атрибуты. В свойство можно передать любой javascript примитив, объект, переменную и даже выражение. Значение свойства должно быть взято в фигурные скобки.

Ключевое слово this будет относиться к экземпляру компонента внутри которого находится.

getInitialState() вызывается один раз перед монтированием компонента. Возвращаемое значение будет использоваться в качестве начального значения this.state.

       Рендеринг

Мы создали компонент. Но React пока не знает, что с ним делать. Чтобы увидеть результат нашей работы необходимо сообщить библиотеке react-dom, что надо это отрендерить и показать. Делается это с помощью функции render, которую мы предварительно изъяли из библиотеки: первым параметром функция принимает компонент, который нужно отрендерить, вторым — DOM элемент (или элементы) в которых нужно отрендерить данный компонент.

       Валидация

Валидация нужна для блока контакты. Код этого блока выглядит следующим образом:

import React, {Component} from ‘react’;
import Validation from ‘react-validation’;
import axios from ‘axios’;
import Popup from ‘react-popup’;
 
class ContactForm extends Component {
 
  constructor(props) {
    super(props);
    this.state = {
      email: ”,
      name: ”,
      message: ”,
    };
    this.onChange = this.onChange.bind(this);
    this.onSubmit = this.onSubmit.bind(this);
  }
 
  onChange(event) {
    let fieldName = event.target.name;
    let stateObject = {};
    stateObject[fieldName] = event.target.value;
    this.setState(stateObject);
  }
 
  onSubmit(event) {
    event.preventDefault();
    const self = this;
    const url = this.props.baseUrl + ‘/entity/contact_message?_format=json’;
    const data = {
      "name": [{"value": this.state.name}],
      "mail": [{"value": this.state.email}],
      "subject": [{"value": this.state.message.split(‘ ‘)[0]}],
      "contact_form": [{"target_id": "contact"}],
      "uid": [{"target_id": "0"}],
      "message": [{"value":  this.state.message}]
    };
    axios.get(this.props.baseUrl + ‘/session/token’)
      .then(res => {
        if (res.status === 200) {
          const instance = axios.create({
            headers: {‘X-CSRF-Token’: res.data}
          });
          instance.post(url, data)
            .then(function (response) {
              if (response.status === 201) {
                Popup.alert(‘Your message has been successfully sent!’);
                self.setState({
                  email: ”,
                  name: ”,
                  message: ”,
                });
              }
            }).catch(function (error) {
            console.log(error);
            Popup.alert(‘Error!’);
          });
        }
      });
  }
 
  render() {
    return <Validation.components.Form ref={c => {
      this.form = c
    }} className="contact-form" onSubmit={this.onSubmit}>
      <div className="col-md-8">
        <div className="contacts-form form-group">
          <div className="form-group border row">
            <div className="col-md-5 half-block top row ">
              <label className="col-sm-4 half-left text-left">
                Name*
              </label>
              <div className="col-sm-8 half-right">
                <Validation.components.Input className="form-control border"
                                             onChange={this.onChange}
                                             value={this.state.name}
                                             errorClassName=‘error’
                                             placeholder="Name" name=‘name’
                                             validations={[‘required’]}/>
              </div>
            </div>
            <div className="col-md-2">
            </div>
            <div className="col-md-5 half-block top row">
              <label className="col-sm-4 half-left text-left">
                Email*
              </label>
              <div className="col-sm-8 half-right">
                <Validation.components.Input className="form-control border"
                                             onChange={this.onChange}
                                             errorClassName=‘error’
                                             value={this.state.email}
                                             placeholder="Email" name=‘email’
                                             validations={[‘required’, ‘email’]}/>
              </div>
            </div>
            <div className="col-md-12 whole-block row">
              <label className="col-sm-4 col-form-label whole-left text-left">
                Message*
              </label>
              <div className="col-sm-8 half-center">
                <Validation.components.Textarea className="form-control border"
                                                onChange={this.onChange}
                                                value={this.state.message}
                                                placeholder="Hi"
                                                errorClassName="error"
                                                name=‘message’
                                                validations={[‘required’]}/>
              </div>
            </div>
            <div className="col-md-12 col-null">
              <Validation.components.Button
                className="btn btn-lg btn-primary btn-block text-uppercase send left">Submit</Validation.components.Button>
            </div>
          </div>
        </div>
      </div>
    </Validation.components.Form>;
  }
 
}
 
export default ContactForm;

Непросто проверять формы с помощью React. Причина – односторонний стиль потока данных. В этом случае мы не можем легко влиять на формы с входов. React-validation предоставляет несколько компонентов, которые «подключены» к форме через метод ввода, прикрепленный компонентом Form.
ПРИМЕЧАНИЕ. Всегда нужно передавать name и validations реквизиты. Они необходимы.
Для использования валидации мы установили react-validation:

npm install react-validation

Компоненты и реквизит

React-validation обеспечивает components объект, который содержит Form, Input, Select, Textarea и Button компоненты. Все они – только пользовательские обертки вокруг собственных компонентов. Они могут принимать любые действительные атрибуты и несколько дополнительных:

containerClassName – Input, Select и Textarea: react-validation обертывает нативные компоненты дополнительным блоком. Эта опора добавляет className к обертке. errorContainerClassName: Модификатор ошибки обертки className. validations- Input, Select и Textarea: принимает массив строк проверки, который ссылается на ключи объекта правил. errorClassName – Input, Select, Button и Textarea: добавляет переданное значение className на появлениях ошибок.

Компонент формы

       Validation.components.Form

Самый важный компонент, который обеспечивает сердцевину проверки реакции. Он в основном смешивает привязку между самой формой и дочерними компонентами проверки реакции через context. Любые действительные реквизиты могут быть легко перенесены на Form такие onSubmit и method.
Form Предоставляет четыре общедоступных метода:

validate(name)- проверяет ввод с переданным именем. Разница между этим методом и проверкой по умолчанию заключается в том, что validate маркирует ввод как isUsed и isChanged. name — имя соответствующего компонента. showError(name [,hint])- помогает обрабатывать ошибки асинхронного API. hint – необязательный подсказку для показа. Может быть строкой (ключ ошибки, ex ‘required’) или функция, которая возвращает подсказку (jsx). hideError(name) – скрывает ошибку соответствующего компонента. validateAll()- проверяет все компоненты проверки реакции. Возвращает карту (ключ: имя поля prop, значение: Array не прошел правила проверки) недопустимых полей.

       Mounting: componentDidMount

componentDidMount()

Вызывается один раз, только на клиенте (не на сервере), сразу же после того, как происходит инициализация рендеринга. На данном этапе в жизненном цикле компонент имеет представление DOM, к которому мы можем получить доступ с помощью this.getDOMNode().

       Array.prototype.map()

Для нашего сайта использовались массивы, для хранения объектов. Поэтому нам пригодился такой метод как map().
Метод map() создаёт новый массив с результатом вызова указанной функции для каждого элемента массива. Метод map вызывает переданную функцию callback один раз для каждого элемента, в порядке их появления и конструирует новый массив из результатов её вызова. Функция callback вызывается только для индексов массива, имеющих присвоенные значения, включая rel=”nofollow”>undefined. Она не вызывается для пропущенных элементов массива (то есть для индексов, которые никогда не были заданы, которые были удалены или которым никогда не было присвоено значение.

Функция callback вызывается с тремя аргументами: значением элемента, индексом элемента и массивом, по которому осуществляется проход.
Если в метод map был передан параметр thisArg, при вызове callback он будет использоваться в качестве значения this. В противном случае в качестве значения this будет использоваться значение
undefined . В конечном итоге, значение this, наблюдаемое из функции callback, определяется согласно обычным правилам определения this, видимого из функции.

Метод map не изменяет массив, для которого он был вызван (хотя функция callback может это делать).

Диапазон элементов, обрабатываемых методом map, устанавливается до первого вызова функции callback. Элементы, добавленные в массив после начала выполнения метода map, не будут посещены функцией callback. Если существующие элементы массива изменяются функцией callback, их значения, переданные в функцию, будут значениями на тот момент времени, когда метод map посетит их; удалённые элементы посещены не будут.
Код из блока Team, где использовался данный метод:

<Slider {…settings}>
            {
              this.state.team.map(function (el, key) {
                return (
                  <div key={key}>
                    <TeamItem
                      image={ self.props.baseUrl + el.user_picture }
                      name={el.first_name}
                      position={el.position}
                    />
                  </div>
                );
              })
            }
</Slider>

Мы использовали у родительского элемента атрибут key. Если объяснить предельно просто: реакту нужна уникальность, чтобы все его механизмы работали корректно. По “ключу” он будет понимать с каким именно дочерним узлом мы работаем и какому родителю он принадлежит.

       React-axios

Данный метод используется для получения данных.
Axios.get является асинхронной функцией, которая означает, что остальная часть кода будет выполнена. И когда ответ сервера будет получен, функция then будет выполнена.

Код из блока WhatWeDo, где использовался данный метод:

  componentDidMount() {
    axios.get(this.props.baseUrl + this.props.source)
      .then(res => {
        if (res.status === 200) {
          this.setState({ projects:res.data });
        }
      });
  } d8.png448.3 КБ Тип материала:  Предлагаю решение Версия Drupal:  Drupal 8.* Ключевые слова:  Drupal8 create-react-app scss перенос сайта




email





facebook





linkedin





twitter





google+





pinterest
1 Спасибо

Источник: http://drupal.ru/node/133787

Обновление Drupal (новая версия Drupal 8.3.5)

Newsletter:  Новости Друпал


Примечания к выпуску:
Обновления с безопасностью отсутствуют

Выпущена готовая к использованию версия Drupal 8.3.5.
Переводчикам следует обратить внимание на несколько незначительных изменений со времени последней версии.
Узнайте больше о Drupal 8.

Ключевые слова:  Drupal 8.3.5 0 Спасибо

Источник: http://drupal.ru/node/133784

© 2009 Обзор CMS