Integrating r1936 - ccm-cms: Added new Reports tab to the content center, initially with 'Content Section Summar' report.
git-svn-id: https://svn.libreccm.org/ccm/trunk@248 8810af33-2d31-482b-a856-94f89814c4dfmaster
parent
dcce15da7c
commit
1815a1f7f6
|
|
@ -0,0 +1,68 @@
|
||||||
|
//
|
||||||
|
// Copyright (C) 2009 Permeance Technologies Pty Ltd. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
|
||||||
|
model com.arsdigita.cms;
|
||||||
|
|
||||||
|
query getContentSectionSummary {
|
||||||
|
BigDecimal folderId;
|
||||||
|
String folder;
|
||||||
|
BigDecimal subfolderCount;
|
||||||
|
|
||||||
|
do {
|
||||||
|
SELECT ci.item_id as folder_id,
|
||||||
|
ci.name AS folder,
|
||||||
|
(SELECT COUNT(*)-1
|
||||||
|
FROM cms_items ci2
|
||||||
|
WHERE ci2.type_id is null
|
||||||
|
START WITH ci2.item_id = ci.item_id
|
||||||
|
CONNECT BY PRIOR ci2.item_id = ci2.parent_id
|
||||||
|
) AS subfolder_count
|
||||||
|
FROM content_sections cs,
|
||||||
|
cms_items ci
|
||||||
|
WHERE ci.section_id = cs.section_id
|
||||||
|
AND cs.section_id = :sectionId
|
||||||
|
AND ci.type_id is null
|
||||||
|
AND ci.master_id is null
|
||||||
|
AND ((ci.parent_id = cs.root_folder_id) or (ci.item_id = cs.root_folder_id))
|
||||||
|
order by ci.name
|
||||||
|
} map {
|
||||||
|
folderId = folder_id;
|
||||||
|
folder = folder;
|
||||||
|
subfolderCount = subfolder_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query getContentTypeCountPerFolder {
|
||||||
|
String contentType;
|
||||||
|
Long typeCount;
|
||||||
|
|
||||||
|
do {
|
||||||
|
SELECT ct.label as content_type,
|
||||||
|
COUNT(*) as type_count
|
||||||
|
FROM content_types ct,
|
||||||
|
(SELECT *
|
||||||
|
FROM cms_items ci
|
||||||
|
START WITH ci.parent_id = :folderId
|
||||||
|
CONNECT BY PRIOR ci.item_id = ci.parent_id and ci.language is null) ci
|
||||||
|
WHERE ci.type_id = ct.type_id
|
||||||
|
GROUP BY ct.label
|
||||||
|
} map {
|
||||||
|
contentType = content_type;
|
||||||
|
typeCount = type_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -823,3 +823,18 @@ Thank you for using {3}.\n
|
||||||
cms.contentassets.ui.description=Description
|
cms.contentassets.ui.description=Description
|
||||||
cms.ui.content_check_alert.subject=Content Check Alert
|
cms.ui.content_check_alert.subject=Content Check Alert
|
||||||
cms.ui.content_check_alert.body=Dear Author\n\nYou are listed as the Content Owner for the following {0} web page(s). Please check if they need amending or updating in any way:\n\n{1}\nIf you have any amendments or questions please email the appropriate web editor:\n\nsally.editor@aplaws.org (Council & Democracy, Environment, Education)\njohn.editor@aplaws.org (Community & Living, Business, Social Care)\nfrank.editor@aplaws.org (Council & Democracy, Environment, Education)\n\nYou can contact webmanager@aplaws.org with any questions about this email\n
|
cms.ui.content_check_alert.body=Dear Author\n\nYou are listed as the Content Owner for the following {0} web page(s). Please check if they need amending or updating in any way:\n\n{1}\nIf you have any amendments or questions please email the appropriate web editor:\n\nsally.editor@aplaws.org (Council & Democracy, Environment, Education)\njohn.editor@aplaws.org (Community & Living, Business, Social Care)\nfrank.editor@aplaws.org (Council & Democracy, Environment, Education)\n\nYou can contact webmanager@aplaws.org with any questions about this email\n
|
||||||
|
#
|
||||||
|
# Reports section
|
||||||
|
#
|
||||||
|
cms.ui.reports=Reports
|
||||||
|
cms.ui.reports.header=Reports
|
||||||
|
cms.ui.reports.intro=Please select a report.
|
||||||
|
# Columns for ContentSectionSummary report
|
||||||
|
cms.ui.reports.css.emptyResult=No matching content items found.
|
||||||
|
cms.ui.reports.css.reportName=Content Section Summary
|
||||||
|
cms.ui.reports.css.contentSection=Content Section
|
||||||
|
cms.ui.reports.css.folder=Folder
|
||||||
|
cms.ui.reports.css.subfolderCount=Subfolders
|
||||||
|
cms.ui.reports.css.contentType=Content Type
|
||||||
|
cms.ui.reports.css.draft=Draft
|
||||||
|
cms.ui.reports.css.live=Live
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
|
||||||
private ContentTypeAdminPane m_typePane;
|
private ContentTypeAdminPane m_typePane;
|
||||||
private UserAdminPane m_userAdminPane;
|
private UserAdminPane m_userAdminPane;
|
||||||
private ContentSoonExpiredPane m_csePane;
|
private ContentSoonExpiredPane m_csePane;
|
||||||
|
private ReportPane m_reportPane;
|
||||||
|
|
||||||
private static class TitlePrinter implements PrintListener {
|
private static class TitlePrinter implements PrintListener {
|
||||||
public void prepare(PrintEvent e) {
|
public void prepare(PrintEvent e) {
|
||||||
|
|
@ -173,6 +174,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
|
||||||
m_typePane = getContentTypeAdminPane();
|
m_typePane = getContentTypeAdminPane();
|
||||||
m_userAdminPane = getUserAdminPane();
|
m_userAdminPane = getUserAdminPane();
|
||||||
m_csePane = getCSEPane();
|
m_csePane = getCSEPane();
|
||||||
|
m_reportPane = getReportPane();
|
||||||
|
|
||||||
// The panes
|
// The panes
|
||||||
m_tabbedPane = createTabbedPane();
|
m_tabbedPane = createTabbedPane();
|
||||||
|
|
@ -204,6 +206,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
|
||||||
m_tabbedPane.setTabVisible(state, m_rolePane, sm.canAccess(user,SecurityConstants.STAFF_ADMIN));
|
m_tabbedPane.setTabVisible(state, m_rolePane, sm.canAccess(user,SecurityConstants.STAFF_ADMIN));
|
||||||
// csePane: should check permission
|
// csePane: should check permission
|
||||||
m_tabbedPane.setTabVisible(state, m_csePane, true);
|
m_tabbedPane.setTabVisible(state, m_csePane, true);
|
||||||
|
// TODO Check for reportPane as well
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -313,6 +316,13 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
|
||||||
return m_csePane;
|
return m_csePane;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ReportPane getReportPane() {
|
||||||
|
if (m_reportPane == null) {
|
||||||
|
m_reportPane = new ReportPane();
|
||||||
|
}
|
||||||
|
return m_reportPane;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the specified component, with the specified tab name, to
|
* Adds the specified component, with the specified tab name, to
|
||||||
* the tabbed pane only if it is not null.
|
* the tabbed pane only if it is not null.
|
||||||
|
|
@ -359,6 +369,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
|
||||||
tab(pane, "cms.ui.content_types", getContentTypeAdminPane());
|
tab(pane, "cms.ui.content_types", getContentTypeAdminPane());
|
||||||
tab(pane, "cms.ui.user_admin", getUserAdminPane());
|
tab(pane, "cms.ui.user_admin", getUserAdminPane());
|
||||||
tab(pane, "cms.ui.cse", getCSEPane());
|
tab(pane, "cms.ui.cse", getCSEPane());
|
||||||
|
tab(pane, "cms.ui.reports", getReportPane());
|
||||||
|
|
||||||
return pane;
|
return pane;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009 Permeance Technologies Pty Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.arsdigita.cms.ui;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.Label;
|
||||||
|
import com.arsdigita.bebop.List;
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.ParameterSingleSelectionModel;
|
||||||
|
import com.arsdigita.bebop.SingleSelectionModel;
|
||||||
|
import com.arsdigita.bebop.event.ChangeEvent;
|
||||||
|
import com.arsdigita.bebop.event.ChangeListener;
|
||||||
|
import com.arsdigita.bebop.list.ListModel;
|
||||||
|
import com.arsdigita.bebop.list.ListModelBuilder;
|
||||||
|
import com.arsdigita.bebop.parameters.StringParameter;
|
||||||
|
import com.arsdigita.cms.ui.report.ContentSectionSummaryTable;
|
||||||
|
import com.arsdigita.cms.ui.report.Report;
|
||||||
|
import com.arsdigita.cms.ui.report.ReportListModel;
|
||||||
|
import com.arsdigita.toolbox.ui.ActionGroup;
|
||||||
|
import com.arsdigita.toolbox.ui.Section;
|
||||||
|
import com.arsdigita.util.LockableImpl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pane that shows selectable reports and their results.
|
||||||
|
* A selectable list of reports is shown on the left-hand side, a selected report is shown as
|
||||||
|
* body.
|
||||||
|
*
|
||||||
|
* @author <a href="https://sourceforge.net/users/thomas-buckel/">thomas-buckel</a>
|
||||||
|
* @author <a href="https://sourceforge.net/users/tim-permeance/">tim-permeance</a>
|
||||||
|
*/
|
||||||
|
public class ReportPane extends BaseAdminPane {
|
||||||
|
|
||||||
|
private final SingleSelectionModel m_selectionModel;
|
||||||
|
private final java.util.List<Report> m_availableReports;
|
||||||
|
|
||||||
|
public ReportPane() {
|
||||||
|
m_availableReports = getReports();
|
||||||
|
|
||||||
|
m_selectionModel = new ParameterSingleSelectionModel(new StringParameter(List.SELECTED));
|
||||||
|
m_selectionModel.addChangeListener(new SelectionListener());
|
||||||
|
setSelectionModel(m_selectionModel);
|
||||||
|
|
||||||
|
List m_reports = new List(new ReportListModelBuilder(m_availableReports));
|
||||||
|
m_reports.setSelectionModel(m_selectionModel);
|
||||||
|
|
||||||
|
final ReportsListSection reportsListSection = new ReportsListSection(m_reports);
|
||||||
|
setLeft(reportsListSection);
|
||||||
|
|
||||||
|
// Register the actual components of the reports for later usage
|
||||||
|
for (Report report : m_availableReports) {
|
||||||
|
getBody().add(report.getComponent());
|
||||||
|
}
|
||||||
|
|
||||||
|
setIntroPane(new Label(gz("cms.ui.reports.intro")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return List of available reports.
|
||||||
|
*/
|
||||||
|
private java.util.List<Report> getReports() {
|
||||||
|
java.util.List<Report> reports = new ArrayList<Report>();
|
||||||
|
reports.add(new Report("cms.ui.reports.css.reportName", new ContentSectionSummaryTable()));
|
||||||
|
// Add other reports as required
|
||||||
|
|
||||||
|
Collections.sort(reports, new Comparator<Report>() {
|
||||||
|
@Override
|
||||||
|
public int compare(Report r1, Report r2) {
|
||||||
|
return r1.getName().compareTo(r2.getName());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return reports;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the report model that matches the given key.
|
||||||
|
* @param key Key to match.
|
||||||
|
* @return Report model that matches that given key, null if no matching report was found.
|
||||||
|
*/
|
||||||
|
private Report getReportByKey(String key) {
|
||||||
|
for (Report report : m_availableReports) {
|
||||||
|
if (report.getKey().equals(key)) {
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UI section for left-hand list of reports.
|
||||||
|
*/
|
||||||
|
private class ReportsListSection extends Section {
|
||||||
|
ReportsListSection(List reports) {
|
||||||
|
setHeading(gz("cms.ui.reports.header"));
|
||||||
|
ActionGroup group = new ActionGroup();
|
||||||
|
setBody(group);
|
||||||
|
group.setSubject(reports);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SelectionListener for selected report. It shows the selected report in the body of this
|
||||||
|
* component.
|
||||||
|
*/
|
||||||
|
private class SelectionListener implements ChangeListener {
|
||||||
|
|
||||||
|
public final void stateChanged(final ChangeEvent e) {
|
||||||
|
|
||||||
|
final PageState state = e.getPageState();
|
||||||
|
|
||||||
|
getBody().reset(state);
|
||||||
|
|
||||||
|
if (m_selectionModel.isSelected(state)) {
|
||||||
|
Report selectedReport = getReportByKey(m_selectionModel.getSelectedKey(state).toString());
|
||||||
|
if (selectedReport != null) {
|
||||||
|
getBody().push(state, selectedReport.getComponent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ListModelBuilder creating a ReportListModel for a list of reports.
|
||||||
|
*/
|
||||||
|
private static class ReportListModelBuilder extends LockableImpl implements ListModelBuilder {
|
||||||
|
|
||||||
|
private java.util.List<Report> reports;
|
||||||
|
|
||||||
|
private ReportListModelBuilder(java.util.List<Report> reports) {
|
||||||
|
this.reports = reports;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ListModel makeModel(final List list,
|
||||||
|
final PageState state) {
|
||||||
|
return new ReportListModel(reports);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,263 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009 Permeance Technologies Pty Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.arsdigita.cms.ui.report;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.Table;
|
||||||
|
import com.arsdigita.bebop.table.AbstractTableModelBuilder;
|
||||||
|
import com.arsdigita.bebop.table.TableModel;
|
||||||
|
import com.arsdigita.cms.CMS;
|
||||||
|
import com.arsdigita.cms.Folder;
|
||||||
|
import com.arsdigita.persistence.DataCollection;
|
||||||
|
import com.arsdigita.persistence.DataQuery;
|
||||||
|
import com.arsdigita.persistence.DataQueryDataCollectionAdapter;
|
||||||
|
import com.arsdigita.persistence.Session;
|
||||||
|
import com.arsdigita.persistence.SessionManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TableModelBuilder that creates a model for the content section summary report.
|
||||||
|
*
|
||||||
|
* @author <a href="https://sourceforge.net/users/thomas-buckel/">thomas-buckel</a>
|
||||||
|
*/
|
||||||
|
public class ContentSectionSummaryReportTableModelBuilder extends AbstractTableModelBuilder
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableModel makeModel(Table t, PageState s)
|
||||||
|
{
|
||||||
|
Session session = SessionManager.getSession();
|
||||||
|
DataQuery query = session.retrieveQuery("com.arsdigita.cms.getContentSectionSummary");
|
||||||
|
query.setParameter("sectionId", CMS.getContext().getContentSection().getID());
|
||||||
|
return new CSSRModel(new DataQueryDataCollectionAdapter(query, "folder"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a table model by combining a list of top level folder (content items) with statistics about
|
||||||
|
* content items with in the folder in draft and live versions.
|
||||||
|
*/
|
||||||
|
private class CSSRModel implements TableModel
|
||||||
|
{
|
||||||
|
|
||||||
|
private final DataCollection m_folders;
|
||||||
|
|
||||||
|
private String m_folderName;
|
||||||
|
|
||||||
|
private BigDecimal m_subfolderCount;
|
||||||
|
|
||||||
|
private ContentTypeStatistics m_currentStatsRow;
|
||||||
|
|
||||||
|
private Iterator<ContentTypeStatistics> m_contentTypeStatIter;
|
||||||
|
|
||||||
|
CSSRModel(DataCollection folders)
|
||||||
|
{
|
||||||
|
m_folders = folders;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final int getColumnCount()
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combines an 'outer' iterator over the given DataCollection with an 'inner' iterator
|
||||||
|
* that contains rows for each row of the outer collection.
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final boolean nextRow()
|
||||||
|
{
|
||||||
|
if ((m_contentTypeStatIter == null) && m_folders.next())
|
||||||
|
{
|
||||||
|
m_folderName = (String) m_folders.get("folder");
|
||||||
|
m_subfolderCount = (BigDecimal) m_folders.get("subfolderCount");
|
||||||
|
Folder draftFolder = new Folder((BigDecimal) m_folders.get("folderId"));
|
||||||
|
|
||||||
|
m_contentTypeStatIter = retrieveContentTypeStats(draftFolder);
|
||||||
|
if (m_contentTypeStatIter.hasNext())
|
||||||
|
{
|
||||||
|
m_currentStatsRow = m_contentTypeStatIter.next();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Rather than recursing into nextRow() again, a m_currentStatsRow == null
|
||||||
|
// is rendered to show one row for the folder but with no content type or values.
|
||||||
|
m_contentTypeStatIter = null;
|
||||||
|
m_currentStatsRow = null;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (m_contentTypeStatIter != null)
|
||||||
|
{
|
||||||
|
if (m_contentTypeStatIter.hasNext())
|
||||||
|
{
|
||||||
|
m_currentStatsRow = m_contentTypeStatIter.next();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_contentTypeStatIter = null;
|
||||||
|
return nextRow();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_folders.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Object getKeyAt(final int column)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Object getElementAt(final int column)
|
||||||
|
{
|
||||||
|
switch (column)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return m_folderName;
|
||||||
|
case 1:
|
||||||
|
return m_subfolderCount.toString();
|
||||||
|
case 2:
|
||||||
|
return (m_currentStatsRow != null) ? m_currentStatsRow.getContentType() : "N/A";
|
||||||
|
case 3:
|
||||||
|
return (m_currentStatsRow != null) ? m_currentStatsRow.getDraftCount() : "N/A";
|
||||||
|
case 4:
|
||||||
|
return (m_currentStatsRow != null) ? m_currentStatsRow.getLiveCount() : "N/A";
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Illegal column index " + column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a list of content types used within a folder and for each content type
|
||||||
|
* the number of draft and live content items of this type.
|
||||||
|
*
|
||||||
|
* @param draftFolder Draft folder to retrieve stats for.
|
||||||
|
*
|
||||||
|
* @return Iterator over the retrieved statistics. Empty iterator with no results
|
||||||
|
* where found.
|
||||||
|
*/
|
||||||
|
private Iterator<ContentTypeStatistics> retrieveContentTypeStats(Folder draftFolder)
|
||||||
|
{
|
||||||
|
|
||||||
|
Session session = SessionManager.getSession();
|
||||||
|
|
||||||
|
// Query the number of content items per content type for drafts
|
||||||
|
DataQuery query = session.retrieveQuery("com.arsdigita.cms.getContentTypeCountPerFolder");
|
||||||
|
query.setParameter("folderId", draftFolder.getID());
|
||||||
|
DataCollection types = new DataQueryDataCollectionAdapter(query, "types");
|
||||||
|
Map<String, Long> draftContentTypeCounts = new HashMap<String, Long>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (types.next())
|
||||||
|
{
|
||||||
|
draftContentTypeCounts.put((String) types.get("contentType"), (Long) types.get("typeCount"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
types.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's a live version of the folder, query the number of content items per content type for it
|
||||||
|
// and merge both draft and live numbers
|
||||||
|
List<ContentTypeStatistics> result = new ArrayList<ContentTypeStatistics>();
|
||||||
|
Folder liveFolder = (Folder) draftFolder.getLiveVersion();
|
||||||
|
if (liveFolder != null)
|
||||||
|
{
|
||||||
|
query = session.retrieveQuery("com.arsdigita.cms.getContentTypeCountPerFolder");
|
||||||
|
query.setParameter("folderId", liveFolder.getID());
|
||||||
|
types = new DataQueryDataCollectionAdapter(query, "types");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (types.next())
|
||||||
|
{
|
||||||
|
String contentType = (String) types.get("contentType");
|
||||||
|
long draftCount = (draftContentTypeCounts.get(contentType) != null) ? draftContentTypeCounts
|
||||||
|
.get(contentType) : 0;
|
||||||
|
long liveCount = (Long) types.get("typeCount");
|
||||||
|
result.add(new ContentTypeStatistics(contentType, draftCount, liveCount));
|
||||||
|
draftContentTypeCounts.remove(contentType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
types.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all draft stats that haven't been merged
|
||||||
|
for (Map.Entry<String, Long> draftCount : draftContentTypeCounts.entrySet())
|
||||||
|
{
|
||||||
|
result.add(new ContentTypeStatistics(draftCount.getKey(), draftCount.getValue(), 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.iterator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value object that holds content type statistics for a folder.
|
||||||
|
*/
|
||||||
|
private static class ContentTypeStatistics
|
||||||
|
{
|
||||||
|
|
||||||
|
private final String m_contentType;
|
||||||
|
|
||||||
|
private final long m_draftCount;
|
||||||
|
|
||||||
|
private final long m_liveCount;
|
||||||
|
|
||||||
|
public ContentTypeStatistics(String contentType, long draftCount, long liveCount)
|
||||||
|
{
|
||||||
|
m_contentType = contentType;
|
||||||
|
m_draftCount = draftCount;
|
||||||
|
m_liveCount = liveCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentType()
|
||||||
|
{
|
||||||
|
return m_contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getDraftCount()
|
||||||
|
{
|
||||||
|
return m_draftCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLiveCount()
|
||||||
|
{
|
||||||
|
return m_liveCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009 Permeance Technologies Pty Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.arsdigita.cms.ui.report;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.Label;
|
||||||
|
import com.arsdigita.bebop.Table;
|
||||||
|
import com.arsdigita.cms.util.GlobalizationUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table component for content section summary report.
|
||||||
|
*
|
||||||
|
* @author <a href="https://sourceforge.net/users/thomas-buckel/">thomas-buckel</a>
|
||||||
|
*/
|
||||||
|
public class ContentSectionSummaryTable extends Table
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final String[] s_fixedReportColumns = new String[] { lz("cms.ui.reports.css.folder"),
|
||||||
|
lz("cms.ui.reports.css.subfolderCount"), lz("cms.ui.reports.css.contentType"),
|
||||||
|
lz("cms.ui.reports.css.draft"), lz("cms.ui.reports.css.live"), };
|
||||||
|
|
||||||
|
public ContentSectionSummaryTable()
|
||||||
|
{
|
||||||
|
super(new ContentSectionSummaryReportTableModelBuilder(), s_fixedReportColumns);
|
||||||
|
setEmptyView(new Label(lz("cms.ui.reports.css.emptyResult")));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String lz(final String key)
|
||||||
|
{
|
||||||
|
return (String) GlobalizationUtil.globalize(key).localize();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009 Permeance Technologies Pty Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.arsdigita.cms.ui.report;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.Component;
|
||||||
|
import com.arsdigita.cms.util.GlobalizationUtil;
|
||||||
|
import com.arsdigita.globalization.GlobalizedMessage;
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UI model for a report.
|
||||||
|
* A report has a name and a component that displays the report.
|
||||||
|
*
|
||||||
|
* @author <a href="https://sourceforge.net/users/thomas-buckel/">thomas-buckel</a>
|
||||||
|
* @author <a href="https://sourceforge.net/users/tim-permeance/">tim-permeance</a>
|
||||||
|
*/
|
||||||
|
public class Report {
|
||||||
|
|
||||||
|
private final String m_key;
|
||||||
|
private final String m_name;
|
||||||
|
private final Component m_component;
|
||||||
|
|
||||||
|
public Report(String key, Component component) {
|
||||||
|
Assert.exists(key, "Key for report is required");
|
||||||
|
Assert.isTrue(key.length() > 0, "Key for report must not be empty");
|
||||||
|
Assert.exists(component, "Component for report is required");
|
||||||
|
|
||||||
|
m_key = key;
|
||||||
|
m_name = gz(m_key).localize().toString();
|
||||||
|
m_component = component;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return m_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component getComponent() {
|
||||||
|
return m_component;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final static GlobalizedMessage gz(final String key) {
|
||||||
|
return GlobalizationUtil.globalize(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009 Permeance Technologies Pty Ltd. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.arsdigita.cms.ui.report;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.list.ListModel;
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ListModel for Reports.
|
||||||
|
*
|
||||||
|
* @author <a href="https://sourceforge.net/users/thomas-buckel/">thomas-buckel</a>
|
||||||
|
* @author <a href="https://sourceforge.net/users/tim-permeance/">tim-permeance</a>
|
||||||
|
*/
|
||||||
|
public class ReportListModel implements ListModel {
|
||||||
|
|
||||||
|
private int m_index = -1;
|
||||||
|
private final List<Report> m_reports;
|
||||||
|
|
||||||
|
public ReportListModel(List<Report> reports) {
|
||||||
|
Assert.exists(reports);
|
||||||
|
m_reports = reports;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getElement() {
|
||||||
|
return m_reports.get(m_index).getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKey() {
|
||||||
|
return m_reports.get(m_index).getKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean next() {
|
||||||
|
m_index++;
|
||||||
|
return (m_reports.size() > m_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue