Руководства
Введение в веб-платформу Falcon Space. C чего начать?Мануал для начинающего разработчика Falcon SpaceВидео о создании сайтов на Falcon SpaceВопросы и ответы для тех, кто начал разрабатывать на Falcon SpaceТиповые ситуации для админа-разработчика в панели управления Как создать таблицу на сайте по шагамКак создать форму на сайте по шагамКак создать дашборд в личном кабинете пользователяПример создания системы по учету Кадры (HR) на сайтеКак улучшить свой код - заметки по ревизии кодаКак сделать аналитический отчет или таблицу на сайтеПодробное описание процесса создания формы Обратная связьСоздание системы уведомлений из внешних источников (через API)Как отслеживать историю действий пользователя или историю событий по объекту системыКак сделать отслеживание посещений сайта конкретными людьми?Как сделать перевод сайта на другой язык для нетехнического специалистаКак сделать функционал оценки полезности материалаСоздание из под editor структуры личных кабинетов (роли, страницы)Улучшение адаптивности страниц под мобильные устройстваСоблюдение порядка в проекте в процессе сопровождения сайтаКак считать показатели год-к-году (YoY) в отчете по периодамКак добирать данные по объекту из внешних источников по API
Основа Falcon SpaceОсновные компонентыВозможностиКоммуникация пользователейДизайн, стилизация, юзабилити
Гид по стилям Falcon SpaceРуководство по юзабилити сайтов на Falcon SpaceЭлементы стилизации в разметке страниц кабинетов на Falcon SpaceУправление темами сайта. Как создать новую тему дизайна сайтаКак внедрять готовую верстку в страницуКак внедрить форму настроек внешнего вида сайтаГорячие клавиши Falcon SpaceСоздание своей темы для сайтаОграничения по изменению дизайнаКак сделать дизайн сайта со скругленными элементами (или без скруглений)Как сделать свою верхнюю полоску сайта (customHeader)Как внедрить новый шрифтКак через CSS управлять стилями конкретных страницКак показать элемент увеличенным при наведении (например ячейка таблицы)Изменение стилизации через CSSКак поменять столбцы местами на смартфоне (order-1 order-md-2)Как сделать анимацию иконокАнимация элементов. Как работать с анимациейДобавление анимацииУправление анимацией для форм, таблицКастомные CSS файлы для страницыПанели с тенью и со скруглением Как внедрить свой CSS на каждой странице порталаКак сделать основное меню горизонтальнымКак убрать все тени и сделать дизайн плоскимКастом разметка верхней панели (TopMakeup)Интерфейс кабинета - это не методы репозитория CRUD!Как сделать липкую панель сверху страницыКак сделать основное меню белымВывод справа на странице float панелиКак поменять степень затемнения фона у диалогового окнаУправление иконкой в окне alert справа вверху окнаКак стилизовать иконкуВывод на экран денежных сумм (отображение рублей, валюты) - as-moneyКак увеличить картинку на страницеВизуализация воронки на основе данныхКак сделать модальное окно определенной шириныПанели показа подсказок (для базовых инструкций по странице)Как сделать левое меню по умолчанию свернутым?
Лендинги
Работа с лендингами (lands)Как создать новый лендинг?Как максимально быстро создать лендинг на базе Falcon SpaceКак внедрить лендинг со своим шаблоном и стилямиКак создать сайт полностью на лендингах?Как устроен механизм лендингов внутриКак переместить лендинг на главную страницу (или на любую другую)Как сделать набор типовых лендингов (например, карточки товаров)?Как сделать копию лендинга с другим адресом или перенести лендинг на другой сайтКак использовать много раз одну секцию в разных лендахКак отключить секцию лендинга или менять их порядок на лендингеКак задать высоту/подложку секции лендингаКак для ленда подключить скрипты или CSSКак прописать SEO параметры для лендаКак создать свой шаблон новой секции лендинга?Как редактировать секцию лендингаГде посмотреть список лендингов?Как сделать меню лендинга или меню сайта на лендахКак сделать подстановочными фавикон, seo title у лендингаКак сделать так, чтобы PWA работал для лендингов
Универсальный APIИнтеграции
Подключение к удаленным серверам SQL Server через Linked ServerZapier интеграция на платформе Falcon SpaceПрием платежей через Яндекс.КассуИнтеграция с Робокассой (платежный шлюз)Пополнение средств через Yookassa (Юкасса)Прием платежей на сайте через CloudPaymentsИнтеграция с платежным шлюзом LifePayУведомление от ТБанка по операциям с расчетным счетомИнтернет-эквайринг Тинькоф БанкИнтеграция API DaData.ru подсказки по адресамИнтеграция коллтрекинга МАНГО ОФИС (режим Площадка)Интеграция API Курсы валют Центрального Банка РФИнтеграция API Почта РФИнтеграция API Служба доставки СДЭК (CDEK)Интеграция API Служба доставки Деловые линииИнтеграция API IpGeoBase Город по IP-адресуИнтеграция API DaData.ru Город по IP-адресуКак вычислить расстояние между 2 геоточками через Google MapsКак сделать интеграцию с Мой СкладКак сделать вебхук для передачи данных с Тильды на Falcon SpaceСканирование штрихкодов и QR кодов через камеру смартфонаПолучение данных контрагента по ИННВнедрение подсказок dadata на сайтВывод точек на карте Яндекс. Интеграция с Яндекс КартыИнтеграция с телефонией Zadarma.comПолучение данных о контрагенте - интеграция ЗаЧестныйБизнесИнтеграция с AMO CRMИмпорт контактов в CRM из Google КонтактыВход/регистрация через ВКонтакте(vk.com)Интеграция CRM с онлайн чатом на сайте (Replain)Как связать yandex metrika clientID с пользователем сайта?Как сделать обработку входящей почты (создание клиента в CRM из Email)Интеграция сайта с ChatGPT (openAI)Интеграция с Яндекс МетрикаИнтеграция с Youtube. Получение роликов каналаИнтеграция с Ozon, Wildberries - извлечение статистикиИнтеграция с API Яндекс Вебмастер
КаталогиНавигацияДокументыДополнительные компонентыПродвижение, SEOСистемные моменты
Отслеживание изменений хранимых процедур и страниц (logChanges)Логирование изменений объектов на примере хранимых процедурРабота с редактором кода в личном кабинете разработчикаЛогирование событий в приложении (trace)Действия в браузере actions JSONКак быстро перенести решение (таблицы, формы, страницы) на другую базу?Настройка диалоговых окон и alert окошекМелкие удобства для разработчика в личном кабинетеКак отследить и ограничить большое количество однородных запросов на сайтеИзменение процедуры поиска, процедуры общих элементов Layout, процедуры периодического запускаКак изменить длительность показа сообщенийФорма обратной связи по ошибкам, предложениям suggestionКак разграничивать права на уровне бизнес-логики хранимых процедурБезопасная обработка данных и проверка доступа в хранимых процедурахИспользование типовой разметки в виде сниппетов для решения различных задачКак логировать клики на определенных элементах в системеОбработка старых браузеров (сообщение об устаревшем браузере)Безопасность. Как скрыть некоторые заголовки (http headers) в запросахОтображение сообщения об offline (Нет сети)Рабочее место разработчика через терминалОбновляемые метки времени в сообщениях на сайтеПодсказка по интерфейсам хранимых процедур компонентовЗащита от CSRF атак через дополнительный токен в формахДополнительные параметры в @parameters (во многих хранимых процедурах)Как логировать события в Falcon в другую базу (чтобы ограничить рост основной базы данных)Сообщение об использовании куки (Cookies)Как искать код некоего компонента (таблицы, формы и т.д.) на страницеКак сделать так, чтобы почта отправлялась асинхронно без задержекРабота со сниппетами кодаУниверсальная кнопка действия as_submitРежим показа таблицы/формы в alert окнеРеализация системы анализа IP посетителей
Системное администрированиеHOWTO
Как сделать отдельный универсальный поискМодальная ссылка (as-modal)Как идентифицировать анонимного пользователя (по куки)?Дашборды. Как вызвать коллбек после загрузки дашбордаКак вынести правила редиректа в отдельный файл configСтраницы. Как сделать редирект на другую страницу при загрузкеСтраницы. Как изменить текст на главнойСтраницы. Как использовать дополнительные параметры на страницеСтраницы. Как выводить списковые данные в теле страницы (repeater)Страницы. Настройки страницы для формирования главного менюСтраницы. Мне нужен в URL параметр itemID, но там передается из-за сущностей InstanceIDСтраницы. Как сделать мастер описания функционала страницыКак добавить событие в календарь GoogleКак сделать кнопку определенного действияКак сделать горячие клавиши для событий (нажатие кнопки)Как показывать баланс пользователя вверху кабинета?Где взять фото пользователяКак сделать поддомены с разными языками для сайтаКак управлять страницей “404 Страница не найдена”Отслеживание всех действий пользователя в системеКак выводить денежные данныеКак дать возможность некоторым ролям вводить html в формах?Что делать если открытая вкладка (tab) сбрасывается при перезагрузке страницы?Как реализовать создание периодического отчета на почтуПопап (popup) окна - показ модальной формы по событию или таймаутуКак быстро просматривать типовые отчеты с возможностью редактирования SQLКак максимизировать показатели Google PageSpeed для сайта на Falcon SpaceКак реализовать окно уведомления об использовании куки (cookies)Вывод на странице штрихкода (barcode) и QR кодаКак в тексте сделать ссылки кликабельнымиКак внедрить на сайте автоопределение города с возможностью выбораКак внедрить оглавление в текстКак вставить универсальный поиск в любое место страницыКак определить координаты lat lng пользователя в текущий моментКак сделать сортировку дерева с Drag-and-DropКак обновить часть страницы по клику на кнопкеЗагрузка дашборда по ссылке as-dashboard-linkКак запретить копировать текст с сайта. Как добавлять ссылку копирайта в текст при копировании с сайтаКак изменить шаблоны хранимых процедур для Формы, Таблицы и др.Определение местоположения пользователя по IP через API (as-ip)Форма Нашли ошибку по Ctrl+EnterКак определить откуда пришел пользователь на сайт? Фиксация источника посещения пользователем сайтаКак сделать ссылку, которая скроллит к элементу на страницеКак показать/скрыть область на странице по ссылке - as-collapseКак сделать обновление интрефейса у другого пользователя по некоему событию
Таблицы
Как сделать таблицу в модальном окне (открывается в диалоговом окне)Как реализовать подтаблицу (вложенная таблица), подформу в таблицеКак связать 2 таблицы Загрузка таблицы по ссылкеКак связать таблицу и редактирование сущности (зависимая страница)Как использовать комментарии в таблицахКак добавить в фильтре значение Не выбрано со значениемКак установить ширину колонки в таблице Как добавить диапазон даты или чисел (слайдер) в фильтрКак сделать операции только для некоторых строкКак делать различный набор столбцов одной таблицы для разных ролейКак убрать показ количества строк результата в заголовке таблицы? Как сделать сортировку в таблицеКак сделать Editable для галочки (Да/Нет) в AS CRUDКак редактировать колонку с датойКак скрыть строчные операции в таблице для определенных строкКак добавить коллбек после загрузки таблицыОтображение таблиц на смартфонеКак работать с галочками в таблицеЧастые ошибки при настройке таблицы (почему не работает таблица)Как обновить подтаблицу после выполнения некой операцииКак обрабатывать групповые операции через модальную формуКак создать предустановленные фильтры для таблицыКак сделать сворачивание таблицы (collapse table)Как убрать старые dict процедуры в формах и таблицахКак сделать фильтр с деревом галочекКак отключить сохранение состояния таблицы (фильтры)Как сделать ссылку на всю строку таблицыКак передать через URL значение фильтраКак сделать обрезание ячеек таблицыСортировка строк в таблицеСоздание сущности с учетом значений фильтровОптимизация запроса SQL - извлечение данных для таблицыКастомная разметка в таблицеРежим кастом вывода через JS (custom)Как настроить дополнительные шапку и подвал у таблицыКак сделать зависимые фильтры в таблицеИмпорт данных в формате файлов txt, csv через таблицуКак гибко управлять видимостью столбцов таблицыКак сделать раскрытие подстроки через любую ссылкуРежим быстрой фильтрации строк без обращения на серверВыпадающая панель рядом с названием таблицы dropdownPanelКак убрать при загрузке установку фокуса ввода на фильтр (data-nofocus)?Как сделать аналитику по периодам (таблица с интервалами дат)Кастомизация вида операций таблицыСтилизация фильтров таблицы
Формы
Как вывести форму во всплывающем окне рядом с кнопкой (popover)Загрузка формы по ссылкеКак принимать в форму не 1 параметр (itemID), а несколько входящих параметров? data-param-p1Как сделать модальную форму Как добавить коллбек после загрузки формы и после сохранения формы.Как показывать на форме прогресс заполнения (прогресс заполнения формы)Как сделать форму в виде мастера шаговКак сделать подтверждение действия в СМС (SMS) в формеКак установить поля в форме по умолчанию при загрузкеКак показывать изменяющуюся информацию при изменении полейФормы. Как сделать в форме более 1 кнопки действий (несколько кнопок действий на форме)Как правильно обрабатывать цены (дробные числа) на формеКак передать в форму скрытый параметрКак в форме добавить примеры заполнения полей (example)Как выбрать значение списка через справочник в модальном окнеКак сделать окно подтверждения действия формыДинамическое изменение itemID у формы в зависимости от других элементов страницыКак скрывать/показывать, обновлять область на странице при изменении поля формыКак добавить новый элемент, если в списке на форме его нетКак перезагрузить страницу после сохранения формыКак вывести списковые данные или таблицу внутри формыКак сделать зависимые поля в форме (Страна, Город)Как сделать кастомную HTML разметку для формы (jsRender)Как создать кастом форму с подтверждением действия по Email или SMSУстановка фоновой панели для формыКак сделать задержку при сохранении формы (saveDelay)Подсказки-ограничители длины для полей в формеКак динамически изменять тип поля формыКак сохранить значение поля в браузере, чтобы каждый раз его не вбивать при загрузке (оставлять последнее сохраненное). Запоминание поля формы в браузереКак выводить разные данные на одной форме для разных ролейКак сделать форму с сохранением состоянияКак сделать поля с анимацией значенийИспользование Google Recaptcha в формахКак обновить таблицу после сохранения формы в модальном окнеКак указать произвольную маску для поля ввода в формеКастом проверка полей формы через JSКак в выборе даты (datepicker) задать доступные датыКак создать форму для редактирования сущностиЗагрузка формы в выпадающем окне (dropdown)Добавление смайликов (emoji) в поля формКак у формы сделать progress bar при загрузке формыРабота с датами в формахПоказ количества символов рядом с полем в формеКнопка очистки формы ResetКонтроль заполнения ключевых форм на сайтеКак сделать форму с простым подтверждением действия (confirm)Как поменять соотношение длины метки и поляКак при сохранении формы вывести сообщение printlog, а не alert
Поля формы
Поле Список поиска значения (autocomplete, search-select) Как в форме вывести список галочек (множественный выбор поля)Как сделать списки select и chosen с категориями (optgroup)Как сделать выбор адреса и сохранение координат места (lat,lng).Установка графика работы (поле формы weekTime)Как в форму в SaveItem передать некий скрытый параметр (например Куки или параметр URL)Как работать с полем типа Слайдер (ползунок)Как использовать в форме поле Выбор файлов. Типы полей формы files, remoteFile, fileContentКак редактировать текст элементов  HTML в Rich-редактореУправление настройками поля через options_ поляВставка ссылок по шаблону (ютуб ссылка, patternString)Как использовать Флажки и выбор радио с картинкойКак работать с полем ТаймерКак сделать выбор цвета в формеКак вывести дерево с выбором галочекКак выводить и сохранять множественный список через chosen поле.Обработка даты из поля datetime-localРедактор текста - код поля формы html2Как работать с полем Дробное числоКак настроить выбор вариантов для поля Интервал датВыбор из элементов с табуляцией - поле формы tabsТип поля imageCheckbox (флажок-картинка)Поле формы Градиент (gradient)
Загрузка файлов, картинок
Работа с ресурсами. Загрузка картинок, файловУправление файлами на сервере (файловый менеджер)Загрузка на форме текстовых файлов и обработка их в процедуре SaveItemКак добавить в колонку таблицы управление файламиЗагрузка файлов с drop областью и гибкой разметкой (компонент as-files)Как приводить картинки к заданным размерам при загрузке на сайтИмпорт и парсинг файла CSVЧем отличается код типа ресурса от типа объектаКак получить ссылку на ресурсКак установить права доступа на менеджер ресурсов?Как загружать фото с обрезкой Как увеличить размер подгружаемых файлов (как загружать большие файлы)Передача файлов по FTPКак искать битые ресурсы, картинкиПодбор оптимальных параметров менеджера ресурсовПодгружаемые файлыМассовая загрузка картинок в систему ресурсовНе грузится файл через менеджер ресурсовФайлы загружаются на сервер, но при скачивании выходит ошибка 404.3 (загрузка ODT, Проблема с MIME типами)Поддержка Webp формата для оптимизации картинокМассовая оптимизация картинок в менеджерах ресурсовНе выводятся картинки на сайте (401, 403 ошибка при загрузке картинок)Как установить JS callback после выполнения crop картинкиНе отображается картинка юзера справа вверхуКак изменить текст "Нет файлов" в as-resourceManager?Обработка спецсимволов в названии файлов Как поставить водяной знак на картинку при загрузкеКак оптимизировать качество картинок при загрузке на сайтКак создавать для загружаемой картинки копии с разными размерамиКак загружать файл, когда задействовано диалоговое окноКак загрузить файл по конкретному путиКак сделать возможность грузить только 1 фотоКак поставить фильтр на типы файлов и ограничить форматы загрузки картинок?Как обработать событие после удаления или добавления файлов? Не выводятся картинки в менеджере ресурсов. Что делать?Как вставить менеджер ресурсов в форму с заданным itemID
HOWTO SQLHOWTO JSHOWTO ВерсткаРешение проблем

Выгода от использования Falcon Space

В 2-3 раза экономнее и быстрее, чем заказная разработка
Более гибкая, чем коробочные решения и облачные сервисы
Используйте готовые решения и изменяйте под свои потребности

Как улучшить свой код - заметки по ревизии кода

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

Основная часть касается кода на SQL, но эти советы и принципы также можно переложить и на другие языки. 

Хранимые процедуры MS SQL

Именование переменных 

Придерживайтесь некоего стандарта на проекте (неважно какой он будет, важно придерживаться единого стандарта). 

Название функции или процедуры - это глагол + объект (SaveFile). Название таблицы - это список сущностей в множественном числе (products). 

Используйте префиксы подсистем в именах, например msg_getFile

Таблицы называйте с префиксом подсистемы и в множественном числе ord_cartItems.

Мы используем для длинных названий lowerCamelCase с префиксом подсистем в начале. 

Не давайте имена связанные со временем - new_topSuppliers (лучше уж тогда дайте версию форме и назовите topSuppliers2).

Имя процедуры не должно вводить в заблуждение. Если процедура идет на чтение (GetItems), то не нужно в ней производить какие-то модификации данной сущности (например, запускаем обновление статуса данной сущности). Другой пример: isDb - это переводится как "Это база данных", а не признак того, что это дашборд.

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

Работа с SELECT

Идентификатор-колонку (id) лучше всегда ставить в самое начало. 

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

Плохой пример, который сложно читать и поддерживать: 

if isnull(@ppassword,'')='' begin select 0 Result,'Пароль не может быть пустым!' Msg return end

Не нужно делать многоэтажные подзапросы, лучше активно используемые данные в нескольких местах запроса получить через inner join

Не используйте функцию dbo.getUserRoles и другие тяжелые функции в where, order by, group by. В некоторых случаях заменяйте на join выборку по роли (иначе медленно работает на больших данных).

Учитывайте, что в подзапросе может быть больше 1 значения (хотя бы top 1 используйте)! 

-- так делать не нужно
where value >= (select startingPrice from ms_auctionItems where id = cast(@itemID as int))  
-- вместо этого вариант лучше использовать in
where userID = (select id from as_users where username=@username)  

Взять за правило именовать таблицу кратко (особенно при JOIN) и обращаться к ней при обращении к столбцам (это уменьшит вероятность коллизии при правке запроса и при добавлении новых столбцов в структуру БД): 

-- плохо
select name from products

--хорошо
select p.name from products p

Нет смысла использовать в where isnull (orderID, 0) = 0 , когда orderID это внешний ключ, orderID не может быть равен 0:

select code from as_coupons where isnull(orderID,0)<>0)

-- можно просто orderID is not null

Когда делаете конкатенацию строк для вывода - обязательно для отдельных параметров проверяем isnull (иначе есть риск, что вся строка будет NULL)

select isnull(x1, '') + ' ' + isnull(x2, '')

Оптимизация. Предпочитайте Exists вместо in, поскольку при применении EXISTS не происходит выборка строк, то его использование более оптимально и эффективно, чем использование оператора IN.

Безопасность 

Обязательно проверяйте, что у компонентов установлены поля Роли - это базово отсечет по роли доступ к данному компоненту

При проверке доступа опирайтесь только на @username, именно этот параметр в процедурах определяет кто именно сейчас работает с системой. Ни в коем случае не опирайтесь на входные бизнес-данные при проверке доступа (например, на orderID). Злоумышленник может изменить запрос вручную и передать чужой orderID. 

Нельзя просто делать исходя из того, что только какой-то роли доступен компонент: 

delete from as_cat_productAttrs where productID = @itemID

Человек может подставить любой itemID и таким образом удалить чужие данные!

Если где-то используете execute_sql - все переменные, которые в нем используются, должны быть проверены или обработаны (для избегания sql инъекций). Ни в коем случае в таких выражениях не должна использоваться строковая переменная, которая пришла извне (это может повлиять на тот код, который будет выполняться).

Если используете внешний iframe, то для повышения безопасности используйте этот атрибут - http://htmlbook.ru/html/iframe/sandbox

Строки 

Если часть строки будет null, то вся строка будет null. Поэтому используйте при конкатенации строк в одну для отдельных переменных isnull.

При приведении типов из строки используйте try_cast, try_convert вместо cast и convert. Этим вы избежите исключения (функция вернет null если нельзя привести тип к заданному).

При конкатенации строк таблицы в 1 строку с помощью For XML обязательно используйте NVARCHAR а не VARCHAR (иначе некоторые символы становятся нечитаемые). Если у вас некоторые символы выглядят как "?", то вероятно вы используете varchar (не поддерживает юникод) вместо NVARCHAR (поддерживает юникод). Проверьте типы данных для переменных, для столбцов, а также наличие знака N для строковых констант

select N'Строка с символами в юникод'

Структура кода процедур и функций 

В функциях @res обозначает выходную переменную и она всегда возвращается в конце функции.

Используйте try catch для обработки непредвиденных ситуаций (например, выдавая некий типовой результат ошибки в SELECT 1).

Используйте iif вместо case  (это более читаемо и выглядит компактнее в запросах select).

Подписывайте выходные SELECT такими комментариями (так вы не запутаетесь с порядком выходных select)

-- SELECT 2
select 1 Result, '' Msg

При написании кода сразу ставьте пары begin end. Этим снижается риск забыть закрыть парные скобки.

Для IF, While всегда используйте begin end - это упрощает чтение и снижает риски внесения ошибок при изменении кода. 

Соблюдайте отступы, отражающие иерархию кода и запросов (особенно в случае сложных подзапросов в where или select).

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

Всю обработку (шлифовка, trim, в нижний регистр и т.д.) входных параметров лучше сделать в самом начале и выдать негативный ответ пользователю при плохих данных, а не где-то в глубине кода процедуры. 

Мусор в коде процедуре лучше чистить (неактуальные комменты и код). Много мусора усложняет чтение и слежение за логикой процедуры.

insert/ update лучше сопровождать комментариями, что делаем по бизнес-логике (Обновляем текущего сотрудника)

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

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

Убирайте неактуальные комментарии (которые не добавляют понятности процедуре).

Очень длинные строки разбивайте на части (чтобы не нужно было прокручивать вправо).

Разное

Нельзя искать сущность по имени (например, статус). Имя может измениться. Нужно искать по кодовому имени (в крайнем случае по id, но это будет тогда "магическое число"). 

select @statusDoneID = id from fin_financeStatuses where name = 'Проведен' -- плохо

select @statusDoneID = id from fin_financeStatuses where code= 'done' -- хорошо

Стараемся не использовать магические числа (в крайнем случае их пояснять через комменты). 

Трассировку значений делайте через execute as_print '123', а не через insert into as_trace(...). Данные print выводятся на странице /start

Аккуратнее делайте приведение строки к строке (помните о размере)

declare @s nvarchar(max) = 'dae52ef9-12b1-4d58-97b3-54bc8e018f9f'
select try_cast(@s as nvarchar) -- НЕВЕРНО! dae52ef9-12b1-4d58-97b3-54bc8e
select try_cast(@s as nvarchar(200)) -- ВЕРНО dae52ef9-12b1-4d58-97b3-54bc8e018f9f

Используйте эти комментарии для типовых ситуаций: 

--IMPORTANT важное изменение в работающем проекте (на что обратить надо внимание либо временное решение)
--TODO - т.е. надо доделать
--OPT - надо оптимизировать в будущем (потенциальная утечка)

При работе с большими таблицами имеет смысл ставить некий ограничитель на извлечение данных (например, top 500). Иначе есть риск извлечения очень большого количества данных на страницу, что создаст лишнюю нагрузку на систему. 

Во вложенных процедурах не должно быть дополнительных выходных select, иначе это повлияет на обработку результатов основной процедуры (очередность выходных SELECT для компонента). Если нужны данные из вложенной процедуры, то можно их получать либо через параметр процедуры OUTPUT, либо через insert into table execute SP.

В системе не должно быть медленных частей (особенно если они часто используются). Иначе это в итоге может привести к падениям (когда юзер будет тыкать много раз на запуск тяжелой операции). Отрезайте, реструктурируйте все медленное. Для особо сложных случаев лучше сделать отдельную таблицу/форму с оптимизированным под этот случай запросом SQL.

Всегда перечисляйте столбцы для вставки для insert. (Позже может добавиться новый столбец и ваш insert будет падать если не были перечислены явно столбцы)

insert into as_codeRevisions(sp, text, created, createdBy )
select ...

Работа с компонентами платформы

Работа с формами

Не нужно помещать в data-itemID совершенно разные сущности (например, для Роли 1 там передается id товара, а для Роли 2 передается id заказа). 

Не нужно скрывать ненужную форму через класс hide или d-none. Нужно убирать ее из разметки если она не нужна - ведь она все равно загружается и занимает ресурсы

<div class="as-form mt-3 d-none" data-code="topSuppliers" data-itemid="0"></div> 

В форме в SaveItem используйте универсальный параметр @parameters, а не старый способ с @field полями (это удобнее для обработки, особенно в случае добавления новых полей).

В общем случае предпочитайте локальную переинициализацию в каком-то контейнере через '.pHtml' RefreshContainer, нежели полную перезагрузку страницы (через SuccessURL).

Не забывайте на формах, которые выводятся на многих страницах (например в подвале), ставить 1 DisableFocusOnLoad, чтобы при загрузке страницы эти формы не просили постоянно фокуса ввода.

-- Form GetItem SELECT 2
select  1 DisableFocusOnLoad


Если у вас нет таблиц/форм на странице, то не будут работать динамически добавленные элементы as-form-modal, as-table-modal
Необходимо неявно подгрузить скрипты таблицы/форм через расположение элементов на странице:

<a href="#" class="as-form-modal hide">For modal in search</a>
<a href="#" class="as-table-modal hide">For modal in search</a>

Избегайте активного использования dependmentCols (элементы пересоздаются при изменении родителя) и changeField. В случае возможных коллизий попробуйте менять timeout для checkFiled форм as.option("form.checkFieldDelay", 1500)

Не допускайте такую ситуацию: Кастомная разметка формы и вставка тега script в элементы такой формы. Если предполагается вставлять скрипты в некое поле, то форма обязательно должна быть без кастом разметки.

Работа с таблицами

Не вставляйте сниппет формы в ячейку таблицы. В этом случае она будет инициализирована N раз при каждой загрузке таблицы. Используйте модальные формы или подстроку таблицы. 

При выводе столбцов используйте isnull для столбца. Особенность компонента - если будет null в 1 строке для столбца, то он спрячет столбец. Поэтому использование isnull дает возможность избежать этого. 

В таблицах не забывайте ставить сортировку по умолчанию (когда пользователь зашел первый раз у него @sort не установлен). Пример:

...
order by
case when (@sort = 'created' and @direction = 'down') or isnull(@sort,'')='' then createdForSort end desc,

Если вы планируете использовать сокращенные ссылки типа products/12, а не /product?itemID=12, то используйте передачу параметра в снипете data-itemID='kak-uluchshit-svoy-kod---zametki-po-revizii-koda', не настройку у таблицы "Добавка к адресу URL" (в этом случае он не распознает itemID в строке /product/12).

В Getitems таблиц нельзя менять pageSize

В целом по компонентам

В общем случае старайтесь избегать суперуниверсальных форм/таблиц на 2+роли. В итоге это сложнее поддерживать, есть риски по безопасности (случайно забыть про обработку ситуации с какой-то ролью), сложнее тестировать (внесли изменения для одной роли, а тестировать теперь надо под всеми ролями). Также есть большой риск, что в будущем формы будут все больше и больше отличаться для разных ролей (и увязывать это между собой также будет все сложнее).  

  • Когда использовать отдельные формы/таблицы: роли сильно разные, цели использования сильно отличаются, развиваться скорее всего будут в разную сторону (например, Форма заказа для Поставщика и Покупателя).
  • Когда использовать одну форму для нескольких ролей: когда цель использования формы одинаковая, роли представляют одну сторону (например, форма модерации для Модератора и Админа).

Не смешивайте крупные блоки HTML кода и SQL. Простую верстку можно оставить в SQL, а для многострочных блоков лучше использовать html блоки (через процедуры as_block, as_htmlBlock).

Если много данных предполагается выводить на странице (например, у нас 4 000 категорий), то обязательно используйте компонент Таблица с пагинацией (плохой пример - дерево из 6000 элементов выгружается в компонент Дерево).

Придерживайтесь структуры процедур для компонентов. Не нужно их кардинально изменять по структуре, т.к. это усложнит поддержку такой процедуры.

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

Для уведомлений - не нужно в additional писать повтор того же, что и в text (лучше тогда оставить пустым additional. Иначе это заставляет пользователя смотреть детали, а там тот же текст, что он уже видел).

Если проект подразумевает в будущем локализацию, то сразу используйте для всех меток в sql функцию dbo.as_lang

select  dbo.as_lang('createSetting', 'Create setting', 'tbSettings', @langID)

Если у вас возникают подобные ошибки при выполнении Внешних действий, то скорее всего вы неправильно передаете выходные типы данных ((например, строка вместо 0)) или параметры имеют имя в неверном регистре (например Code вместо code): has some invalid arguments exception, Error parsing column 0

Работа со страницами

В большинстве случаев вместо /order?itemID=12 можно писать адрес /order/12. Адрес всегда начинается со слеша!  

Лучше избегать использования табов на странице (переключение вкладок). Первая причина - Пользователи забывают нажимать Save на одной из вкладок. Вторая - сразу грузятся несколько таблиц или форм, притом, что пользователь использует только одну. Альтернатива - модальные формы и таблицы, загрузка таблицы или формы по ссылке, отдельные страницы, подтаблицы.

Верстка и работа с HTML

Cледите за иерархией заголовков и структурой страниц, направленных на продвижение. У страницы должен быть 1 тег h1 и остальные теги h2-h6 должны определять скелет документа и иерархию контента на странице (например, не нужно делать в разделе с заголовком h3 подраздел с h2). 

Указывайте все классы адаптивности bootstrap, а не только col-md-9

<div class="col-md-9"></div> - плохо
<div class="col-12 col-sm-7 col-md-9 col-lg-10"></div> - хорошо

Не используйте класс col-xs-12 (вместо него надо col-12). Общая сумма в row должна быть 12 (а не 10). 

Не используйте картинки и другие ресурсы, как пути к совершенно другому сайту. Ссылайтесь только на ресурсы, которые принадлежат вашему проекту. Это снижает зависимость проекта от внешних изменений. 

Адреса к локальным ресурсам, страницам должны начинаться всегда со слеша. Например: /product

<div class="as-form mt-3 d-none" data-code="topSuppliers" data-itemid="0"></div> 

Не создавайте левые кастомные стили (для кнопок и др.). Используйте только стандартные bootstrap кнопки. По максимуму используйте стандартные стили bootstrap. CSS используйте только для дополнительного позиционирования. А стилизацию лучше выполнять за счет генерации новой темы сайта. 

Никогда не используйте inline стили прямо в разметке. По максимуму задействуйте классы Bootstrap. Если нужно еще что-то стилизовать через CSS, то вешаем на элемент уникальный класс (с префиксом по подсистеме) и в CSS страницы или глобальном CSS прописываем стиль для этого класса.

Никогда не меняйте глобальные стили для какой-то локальной задачи (это может негативно повлиять на разметку других страниц). Меняйте CSS только для своих кастомных классов. 

CSS стили не надо в форму вставлять (в кастом разметку формы вставлять теги style). Вставляйте их в страницу в поле кода для CSS.

На странице должен быть 1 h1. Соблюдайте иерархию заголовков (h2-h6 определяют структуру документа).

Используйте для кнопок в разметке тег а, а не button (с button замечена проблема анимации появления блоков при enableAnimation=1).

См. также Соблюдение порядка в проекте в процессе сопровождения сайта.

Falcon Space - функциональная веб-платформа разработки на узком стеке MS SQL/Bootstrap. Вводная по Falcon Space
Насколько полезной была статья?

Google поиск по нашей документации

Нужна бесплатная консультация?
Планируете делать веб-проект?
Если видео Youtube плохо грузится, то попробуйте найти видео в ВК видео на канале Falcon Space
Сайт использует Cookie. Правила конфиденциальности OK
Подождите...