145 lines
12 KiB
Plaintext
145 lines
12 KiB
Plaintext
<cfsilent>
|
||
<cfimport prefix="m" taglib="lib"/>
|
||
<cfimport prefix="c" taglib="lib/controls"/>
|
||
<cfimport prefix="d" taglib="lib/data"/>
|
||
<cfimport prefix="layout" taglib="layout"/>
|
||
</cfsilent><m:silent silent="No">
|
||
|
||
<cffunction name="hideNonPositive">
|
||
<cfargument name="a"/>
|
||
<cfreturn (a GT 0)? a : ""/>
|
||
</cffunction>
|
||
|
||
<m:prepare_ls entity="area" pageInfoOut="pageInfo" trackOut="tr"/>
|
||
|
||
<m:filter_settings target="#pageInfo.entity#_ls">
|
||
<m:filterparam filter=#filter# param="quickfilter" ftype="string" prefix="%" suffix="%" expression="((p.project like ?) OR (p.customer like ?) OR (p.customer_alias like ?) OR (p.area_class_type like ?) OR (p.division like ?) OR (p.performer_short like ?))" default=""/>
|
||
</m:filter_settings>
|
||
<cfset pageInfo.settings.filter=#filter#/>
|
||
|
||
<cftry>
|
||
<cfquery name="qRead" datasource="#request.DS#">
|
||
select
|
||
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
|
||
<d:field title="ID" cfSqlType="CF_SQL_INTEGER">m.area_id</d:field>
|
||
<d:field title="Код группы">m.area_code</d:field>
|
||
<d:field title="Аналитический код">m.analytic_code</d:field>
|
||
<d:field title="Группа (RUS)">m.area</d:field>
|
||
<d:field title="Группа (ENG)">m.area_en</d:field>
|
||
<d:field title="Абстр. услуг">(select count(*) from abstract_service a where a.area_id=m.area_id) as as_cnt</d:field>
|
||
<d:field title="Вариантов услуг">(select count(*) from abstract_service a join service s on (a.abstract_service_id=s.abstract_service_id) where a.area_id=m.area_id) as svc_cnt</d:field>
|
||
</d:field_set>
|
||
from area m
|
||
where 1=1 <m:filter_build filter=#pageInfo.settings.filter#/>
|
||
order by <m:order_build sortArray=#pageInfo.settings.sort.sortArray# fieldCount=#fieldCount#/>
|
||
</cfquery>
|
||
|
||
|
||
<cfcatch type="database">
|
||
<m:ls_catch catch=#cfcatch# status=#pageInfo.status#/>
|
||
</cfcatch>
|
||
</cftry>
|
||
|
||
<cfquery name="qCountTotal" datasource="#request.DS#">
|
||
select count(*) as cnt from area where 1=1
|
||
</cfquery>
|
||
|
||
</m:silent><!---
|
||
-----------------------------------------------------------------------------------------
|
||
-----------------------------------------------------------------------------------------
|
||
-----------------------------------------------------------------------------------------
|
||
---><cfif isDefined("output_xls")>
|
||
<layout:xml qRead=#qRead# titleMap=#titleMap# filename="#pageInfo.entity#.xml"/>
|
||
<cfabort/>
|
||
</cfif><cfif isDefined("output_json")>
|
||
<layout:json qRead=#qRead# titleMap=#titleMap# filename="#pageInfo.entity#.json"/>
|
||
<cfabort/>
|
||
</cfif><!---
|
||
---><layout:page section="header" pageInfo=#pageInfo#>
|
||
|
||
<layout:attribute name="title">
|
||
<cfoutput><b>Группы услуг</b></cfoutput>
|
||
</layout:attribute>
|
||
<layout:attribute name="controls">
|
||
<!---skip filter link, filter is not implemented--->
|
||
<!---<layout:language_switch/>--->
|
||
</layout:attribute>
|
||
</layout:page>
|
||
|
||
<cfif pageInfo.readPermitted() AND !pageInfo.status.errorState>
|
||
|
||
<layout:grid_summary
|
||
recordCount=#qRead.recordCount#
|
||
totalCount=#qCountTotal.cnt#
|
||
footerOut="gridFooter"
|
||
excelLink="Yes"
|
||
jsonLink="Yes"
|
||
/>
|
||
|
||
|
||
<!--- так довольно громоздко, но можно обойтись без Dynamic Evaluation --->
|
||
<cfset queryAddColumn(qRead,'f_link_view_edit')/>
|
||
<cfset titleMap.f_link_view_edit={ordinal=#StructCount(titleMap)+1#}/><!--- *** Это легко забыть, потому что TitleMap никак не сцеплен с qRead. Напрашивается: упаковать их в одну обертку (но тогда обращение станет длиннее). Еще идея - назвать qRead и TitleMap так, чтобы была видна их связь. --->
|
||
<!--- <cfdump var=#titleMap#/> --->
|
||
<cfset queryAddColumn(qRead,'f_link_del')/>
|
||
<cfset titleMap.f_link_del={ordinal=0}/>
|
||
<!--- <cfdump var=#titleMap#/> --->
|
||
<cfoutput query=#qRead# startRow=#pageInfo.nStart# maxRows=#pageInfo.recordsPerPage#><!--- *** Здесь некомфортное дублирование startRow, maxRows с вызовом c:table ниже, причем в c:table оно закопано в модуль, и аргументы называются по-разному... но мы хотим немного сэкономить и не обрабатывать весь резалтсет --->
|
||
<cfsavecontent variable="qRead.f_link_view_edit">
|
||
<a href="#pageInfo.entity#.cfm?#pageInfo.entity#_id=#area_id#&#tr.fwx#" name="#area_id#" <cfif pageInfo.writePermitted()>title="редактировать" class="edit"<cfelse>title="просмотр" class="view"</cfif>></a>
|
||
</cfsavecontent>
|
||
<cfsavecontent variable="qRead.f_link_del">
|
||
<cfif pageInfo.writePermitted()><a href="#pageInfo.entity#_del.cfm?#pageInfo.entity#_id=#area_id#&#tr.fwx#" name="#area_id#" class="del" title="удалить"></a></cfif>
|
||
</cfsavecontent>
|
||
</cfoutput>
|
||
|
||
<c:table query=#qRead# recordsPerPage=#pageInfo.recordsPerPage# nStart=#pageInfo.nStart# titleMap=#titleMap# sortArray=#pageInfo.settings.sort.sortArray# class="worktable wide">
|
||
<c:column width="1%" sortable="false"><!---*** class="c" не пробрасывается --->
|
||
<c:th><c:link_add canWrite=#pageInfo.writePermitted()# entity=#pageInfo.entity# fwx=#tr.fwx#/></c:th>
|
||
<c:td field="f_link_view_edit" class="c"/>
|
||
<!--- <a href="#CALLER.pageInfo.entity#.cfm?#CALLER.pageInfo.entity#_id=#area_id#&#CALLER.tr.fwx#" name="#area_id#" <cfif pageInfo.writePermitted()>title="редактировать" class="edit"<cfelse>title="просмотр" class="view"</cfif>></a> --->
|
||
</c:column>
|
||
<c:column width="3%" field="area_id"/>
|
||
<c:column width="5%" field="area_code"/>
|
||
<c:column width="5%" field="analytic_code"/>
|
||
<c:column width="20%" field="area"/>
|
||
<c:column width="20%" field="area_en"/>
|
||
<c:column width="5%" field="as_cnt" formatter=#hideNonPositive#><c:td class="c"/></c:column>
|
||
<c:column width="5%" field="svc_cnt" formatter=#hideNonPositive#><c:td class="c"/></c:column>
|
||
<c:column width="1%" sortable="false">
|
||
<c:td field="f_link_del" class="c"/>
|
||
</c:column>
|
||
</c:table>
|
||
|
||
<cfoutput>#gridFooter#</cfoutput>
|
||
|
||
</cfif>
|
||
<layout:page section="footer"/>
|
||
|
||
<!---*** критика синтаксиса: CALLER в данном контексте выглядит ужасно. Когда применять #service_id#, когда ##service_id##
|
||
Может быть, стоит отказаться от пользовательского тега и обратиться к более ровному способу форматирования.
|
||
Например (явно плохая идея, но для примера) печатать таблицу, а потом ее парсить и переформатировать... некоторые это могли сделать на клиенте.
|
||
На самом деле все, что нужно нам из скоупа CALLER, уже определено в момент вызова тега, и мы можем заменить CALLER на <cfoutput>. Это тоже неуклюже. То есть тащить весь CALLER внутрь как бы избыточно (не говоря о том, что можно словить каких-то сложносочиненных глюков)
|
||
Сортировка должна происходить на сервере БД, иначе паджинатор бесполезен. Вытаскивать резалтсет на сервер приложений и там его сортировать выглядит очень плохим решением (еще глупее сортировать на клиенте). Для корректной сортировки нужно делать композицию колонок на сервере, что не очень хорошо, например, с нуллами надо обращаться осторожно (вот аргумент в пользу NOT NULL), и синтаксис становится зависим от диалекта SQL. Возможный вариант, если у нас композиция из 2 колонок, сортировать по обеим. Либо отказаться от сортировки по композитной колонке, что кажется проще всего.
|
||
|
||
Контекст query выглядит естественно, но эта простота вводит в заблуждение - на вид обычный синтаксис, а функции недоступны (паковать в реквест еще то удовольствие), контекст страницы недоступен, ищи его через CALLER - догадаться невозможно.
|
||
|
||
Можно передавать внутрь тега все, что может понадобиться - функции, переменные?
|
||
Можно придумать собственный синтаксис, заменяющий cfif
|
||
--->
|
||
<!--- тонкости
|
||
в примере ниже
|
||
Атрибуты тега вычисляются до вызова, в контексте вызывающей страницы, а содержимое обрабатывается самим тегом в его контексте (собственно, мы сказали ему так делать). Но при чтении исходника это совсем не очевидно и может порвать мозг.
|
||
Можно, конечно, обрабатывать исключение и подставлять контекст вызывающей страницы? Как заставить тег видеть контекст вызывающей страницы? Попробовал взять весь тег в cfoutput. В результате перестал видеть поля query. Откатился.
|
||
Печаль в том, что мы в одном месте (чего и хотели - чтобы рядом) получаем контекст вызывающей страницы и контекст query, поля которого хотим называть неквалифицированными именами.
|
||
Вариант: действуем в 2 прохода, сначала формируем структуру, а потом рендерим ее. В принципе, с учетом пагинации, может потреблять памяти меньше, чем сам query
|
||
<c:th><c:link_add canWrite=#pageInfo.writePermitted()# entity=#pageInfo.entity# fwx=#tr.fwx#/><cfoutput>#pageInfo.entity#</cfoutput>#pageInfo.entity#</c:th> --->
|
||
<!--- Хотелось бы:
|
||
чтобы контекст страницы был явно доступен во всех вложенных тегах. >> The custom tag's Caller scope is a reference to the calling page's Variables scope (добавить все из CALLER в Variables? А не зациклимся?
|
||
чтобы итератор работал прозрачно, как в cfoutput query
|
||
Как обойтись без динамического исполнения? Для всех форматтеров снаружи объявлять closure? нечитабельно.
|
||
Хотя читабельность простыней ниже - так себе
|
||
В общем, получается пока плохо
|
||
? полиморфизм i18(measure_short) - как бы избежать отдельной далекой декларации длинного списка похожих функций. Можно полю придать признак языка? Соглашение с суффиксами? Это уже какая-то морфология получается!
|
||
|
||
---> |