понедельник, 26 августа 2013 г.

CamlJs 2.0

В предыдущем посте я писал немного о том, как мне удалось улучшить условия разработки CamlJs: про внутренний переход на TypeScript, введение юнит-тестов и визуального diff'а. Благодаря этим внутренним усовершенствованиям, мне удалось быстро привести проект в порядок, добавить в него существенные улучшения и выпустить релиз 2.0, который выходит сегодня, ура! :)

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

Зачем нужен CamlJs


Итак, проект CamlJs позволяет формировать строку Caml Query на стороне клиента (в JavaScript) для использования совместно с SP.CamlQuery или SPServices. CamlJs привносит следующие основные преимущества перед использованием просто строк с XML:
  1. Читаемость. Захардкоженный XML в коде выглядит жутковато и громоздко, запросы написанные на CamlJs читать намного проще и они гораздо компактнее.



  2. Защита от опечаток. XML - это по сути "magic string", в котором очень легко сделать опечатку. SharePoint в этом случае возвращает, как водится, совершенно безумные, вводящие в заблуждение сообщения об ошибках. Чтобы понять, что на самом деле ты где-то просто забыл закрывающую кавычку или что-то в этом духе, приходится тратить кучу времени...
  3. Intellisense. CamlJs дает intellisense и inline подсказки, благодаря чему даже люди, не в совершенстве знающие CAML Query, могут составлять сложные запросы без ошибок.
  4. Обработка SharePoint-овских "багофич". Например, многие ли из вас знают, что при попытке применить условие <Includes> для MultiLookup полей указывающих на поле типа DateTime SharePoint вернет ошибку? :) А CamlJs знает это - и еще кучу тонкостей, которые я собрал за долгие годы работы с CAML Query...

Что нового в версии 2.0


Версия 2.0 существенно улучшена по сравнению с 1.0. При этом, синтаксически версии оставлены максимально совместимыми.
  1. Поддержка скобочных выражений и генерации частей запросов. CamlJs 1.0 не поддерживал возможности создания скобочных выражений. Все операции в запросах генерились строго в порядке справа налево, и более-менее сложную логику с множеством вложенных Or и And реализовать было, к сожалению, невозможно :( Теперь это исправлено за счет введения операторов All и Any.
  2. Значительно улучшен Intellisense. Теперь набор возможных сравнений для поля зависит от типа этого поля, т.е. например к полям Integer нельзя применить сравнение Contains и т.д.
  3. Изменена обработка Lookup-полей. Теперь элемент LookupField поддерживает методы Id() и ValueAs<type>(), которые уже в свою очередь возвращают корректный набор операций. Например, если у вас есть Lookup-поле "City", которое ссылается на текстовое поле "Title" в таблице "Cities", то чтобы получить все записи у которых город начинается на "М", надо использовать запрос LookupField("City").ValueAsText().BeginsWith("M").
  4. Улучшен элемент UserField. Помимо изменений связанных с изменениями Lookup-полей (а User-поле это как известно частный случай Lookup-а), функционал элемента Membership теперь реализуется несколькими функциями элемента UserField. Кроме того, для удобства, была добавлен метод "EqualToCurrentUser()", который функционально эквивалентен конструкции "EqualTo(CamlBuilder.CamlValues.UserId)".
  5. Улучшен элемент DateRangesOverlap. К сожалению, выяснилось что этот элемент невозможно использовать вместе с SP.CamlQuery, поскольку CSOM игнорирует тэг QueryOptions, а для DateRangesOverlap нужно задавать QueryOptions/CalendarDate и QueryOptions/ExpandRecurrence. Однако, остается возможность использовать DateRangesOverlap хотя бы вместе с SPServices.
  6. Добавлен новый элемент BooleanField для полей типа Boolean.
  7. Добавлен новый элемент UrlField для полей типа URL.
  8. DateField и DateTimeField теперь конвертируют дату (Date) к правильному формату.
Также, проект теперь написан на TypeScript и покрыт юнит-тестами, благодаря чему можно гарантировать повышенные стабильность и правильность работы.

Наконец, проект теперь доступен через Nuget (добавляет camljs.js в папку Scripts вашего проекта):

PM> Install-Package CamlJs
Определения для TypeScript также доступны через Nuget:

PM> Install-Package camljs.TypeScript.DefinitelyTyped


Миграция с версии 1.0 на 2.0


Логика работы системы осталась в основном прежней, никакие старые элементы не были удалены или переименованы, поэтому как правило, миграция НЕ требуется. Однако, т.к. синтаксис стал немного более строгим, возможно потребуется что-то подкорректировать. Если у вас возникли проблемы с запросами из версии 1.0, смело пишите в комментарии, решим.

Также, обратите пожалуйста внимание на то, что элементы Membership и LookupIdField теперь помечены как "deprecated" и будут убраны в следующем большом релизе. Рекомендуется переписать запросы с их использованием на эквивалентные конструкции LookupField("...").Id() и UserField("...").IsInCurrentUserGroups() и т.д.

Заключение


В SharePoint 2013 роль JavaScript неимоверно возросла. Появилась необходимость создания комплексных JavaScript-решений, работающих полностью на стороне клиента. В этих условиях, приобретают повышенное значение всевозможные инструменты и расширения для клиентских операций, в том числе и разрабатываемый мною opensource-проект CamlJs.

Надеюсь, CamlJs поможет вам улучшить ваши JavaScript-решения и упростить реализацию задач, связанных с генерацией сложных запросов к спискам. Удачи!

3 комментария:

  1. Андрей спасибо большое за проделанную работу. Это отличный подарок

    ОтветитьУдалить
  2. Юзаю вашу библиотеку. Спастбо!
    Конечно пришлось немного опытным путём дойти до некоторых вещей - на codeplex в описании немного однообразные примеры. Не нашёл как объединить часть or часть and
    Например
    CamlBuilder.Expression().Any(
    CamlBuilder.Expression().All(
    CamlBuilder.Expression().DateField('Finish').GreaterThanOrEqualTo(beginDate),
    CamlBuilder.Expression().DateField('Finish').LessThanOrEqualTo(endDate)
    ),
    CamlBuilder.Expression().All(
    CamlBuilder.Expression().DateField('Start').GreaterThanOrEqualTo(beginDate),
    CamlBuilder.Expression().DateField('Start').LessThanOrEqualTo(endDate)
    ),
    CamlBuilder.Expression().All(
    CamlBuilder.Expression().DateField('Finish').GreaterThanOrEqualTo(endDate),
    CamlBuilder.Expression().DateField('Start').LessThanOrEqualTo(beginDate)
    )
    )

    ОтветитьУдалить
  3. Андрей библиотека супер!
    спасибо большое, использую и для создания CAML-query и для добавления условий в имеющийся xml
    (это вообще убойная фича!).
    маленькое дополнение - в процессе использования столкнулся с падением
    на вызове - SP.XmlWriter
    решил проблему, обернув скрипты в SP.SOD.executeFunc('sp.runtime.js', 'SP.XmlWriter', function(){...})
    спасибо!

    ОтветитьУдалить

Внимание! Реклама и прочий спам будут беспощадно удаляться.