package org.olat.admin.sysinfo; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.olat.NewControllerFactory; import org.olat.admin.sysinfo.gui.LargeFilesLockedCellRenderer; import org.olat.admin.sysinfo.gui.LargeFilesNameCellRenderer; import org.olat.admin.sysinfo.gui.LargeFilesRevisionCellRenderer; import org.olat.admin.sysinfo.gui.LargeFilesSendMailCellRenderer; import org.olat.admin.sysinfo.gui.LargeFilesSizeCellRenderer; import org.olat.admin.sysinfo.gui.LargeFilesTrashedCellRenderer; import org.olat.admin.sysinfo.model.LargeFilesTableContentRow; import org.olat.admin.sysinfo.model.LargeFilesTableModel; import org.olat.admin.sysinfo.model.LargeFilesTableModel.LargeFilesTableColumns; import org.olat.core.commons.persistence.SortKey; import org.olat.core.commons.services.vfs.VFSMetadata; import org.olat.core.commons.services.vfs.VFSRepositoryService; import org.olat.core.commons.services.vfs.VFSRevision; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.DateChooser; import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement; import org.olat.core.gui.components.form.flexible.elements.FlexiTableSortOptions; import org.olat.core.gui.components.form.flexible.elements.FormLink; import org.olat.core.gui.components.form.flexible.elements.IntegerElement; import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; import org.olat.core.gui.components.form.flexible.elements.SingleSelection; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormEvent; import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.ExtendedFlexiTableSearchController; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.text.TextFactory; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.closablewrapper.CalloutSettings; import org.olat.core.gui.control.generic.closablewrapper.CloseableCalloutWindowController; import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; import org.olat.core.gui.util.CSSHelper; import org.olat.core.id.Identity; import org.olat.core.util.Formatter; import org.olat.core.util.mail.ContactList; import org.olat.core.util.mail.ContactMessage; import org.olat.modules.co.ContactFormController; import org.springframework.beans.factory.annotation.Autowired; public class LargeFilesController extends FormBasicController implements ExtendedFlexiTableSearchController { public static final String[] TRASHED_KEYS = new String[]{ "trashed", "notTrashed", "both" }; public static final String[] REVISION_KEYS = new String[]{ "revisions", "files", "both" }; public static final String[] LOCKED_KEYS = new String[]{ "locked", "notlocked", "both" }; private final AtomicInteger counter = new AtomicInteger(); private FlexiTableElement largeFilesTableElement; private LargeFilesTableModel largeFilesTableModel; private MultipleSelectionElement types; private SingleSelection trashedSelection; private SingleSelection revisionSelection; private SingleSelection lockedSelection; private DateChooser createdAtNewerChooser; private DateChooser createdAtOlderChooser; private DateChooser editedAtNewerChooser; private DateChooser editedAtOlderChooser; private DateChooser lockedAtNewerChooser; private DateChooser lockedAtOlderChooser; private IntegerElement downloadCountMinEl; private IntegerElement revisionCountMinEl; private IntegerElement maxResultEl; private IntegerElement maxSizeEl; private FormLink searchButton; private FormLink resetButton; private List<LargeFilesTableContentRow> rows; private boolean enabled = true; private CloseableModalController cmc; private ContactFormController contactCtrl; private CloseableCalloutWindowController pathInfoCalloutCtrl; @Autowired private VFSRepositoryService vfsRepositoryService; public LargeFilesController(UserRequest ureq, WindowControl wControl) { super(ureq, wControl, "large_files"); initForm(ureq); updateModel(); } public void updateModel() { rows = new ArrayList<>(); if(revisionSelection.getSelectedKey() != REVISION_KEYS[0]) { List<VFSMetadata> files = vfsRepositoryService.getLargestFiles(maxResultEl.getIntValue(), createdAtNewerChooser.getDate(), createdAtOlderChooser.getDate(), editedAtNewerChooser.getDate(), editedAtOlderChooser.getDate(), lockedAtNewerChooser.getDate(), lockedAtOlderChooser.getDate(), trashedSelection.getSelectedKey(), revisionSelection.getSelectedKey(), lockedSelection.getSelectedKey(), downloadCountMinEl.getIntValue(), new Long(revisionCountMinEl.getIntValue()), maxSizeEl.getIntValue() ); for(VFSMetadata file:files) { LargeFilesTableContentRow contentRow = new LargeFilesTableContentRow(file); String[] path = contentRow.getPath().split("/"); StringBuilder sb = new StringBuilder(path[0]); sb.append("/").append(path[1]); if(path.length > 2) { sb.append("/..."); } FormLink pathInfo = uifactory.addFormLink("pathinfo_" + counter.incrementAndGet() , "pathInfo", sb.toString(), null, null, Link.NONTRANSLATED); pathInfo.setUserObject(contentRow); contentRow.setPathInfo(pathInfo); rows.add(contentRow); } } if(revisionSelection.getSelectedKey() != REVISION_KEYS[1]) { List<VFSRevision> revisions = vfsRepositoryService.getLargestRevisions(maxResultEl.getIntValue(), createdAtNewerChooser.getDate(), createdAtOlderChooser.getDate(), editedAtNewerChooser.getDate(), editedAtOlderChooser.getDate(), lockedAtNewerChooser.getDate(), lockedAtOlderChooser.getDate(), trashedSelection.getSelectedKey(), revisionSelection.getSelectedKey(), lockedSelection.getSelectedKey(), downloadCountMinEl.getIntValue(), new Long(revisionCountMinEl.getIntValue()), maxSizeEl.getIntValue()); for(VFSRevision revision:revisions) { LargeFilesTableContentRow contentRow = new LargeFilesTableContentRow(revision); String[] path = contentRow.getPath().split("/"); StringBuilder sb = new StringBuilder(path[0]); sb.append("/").append(path[1]); if(path.length > 2) { sb.append("/..."); } FormLink pathInfo = uifactory.addFormLink("pathinfo_" + counter.incrementAndGet() , "pathInfo", sb.toString(), null, null, Link.NONTRANSLATED); pathInfo.setUserObject(contentRow); contentRow.setPathInfo(pathInfo); rows.add(contentRow); } } Collections.sort(rows, (row1,row2) -> { return row2.getSize().intValue() - row1.getSize().intValue(); }); if(maxResultEl.getIntValue() != 0 && maxResultEl.getIntValue() < rows.size()) { rows = rows.subList(0, maxResultEl.getIntValue()); } largeFilesTableModel.setObjects(rows); largeFilesTableElement.reset(true, true, true); } private void resetForm() { createdAtNewerChooser.reset(); createdAtOlderChooser.reset(); lockedAtNewerChooser.reset(); lockedAtOlderChooser.reset(); editedAtNewerChooser.reset(); editedAtOlderChooser.reset(); revisionCountMinEl.reset(); downloadCountMinEl.reset(); trashedSelection.reset(); lockedSelection.reset(); revisionSelection.reset(); maxResultEl.reset(); maxSizeEl.reset(); updateModel(); } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { FormLayoutContainer largefFilesTitle = FormLayoutContainer.createVerticalFormLayout("largeFilesTitle", getTranslator()); formLayout.add(largefFilesTitle); largefFilesTitle.setFormTitle(translate("largefiles.title")); FormLayoutContainer leftContainer = FormLayoutContainer.createDefaultFormLayout_6_6("filter_left", getTranslator()); leftContainer.setRootForm(mainForm); formLayout.add(leftContainer); FormLayoutContainer rightContainer = FormLayoutContainer.createDefaultFormLayout_6_6("filter_right", getTranslator()); leftContainer.setRootForm(mainForm); formLayout.add(rightContainer); FormLayoutContainer filterButtonLayout = FormLayoutContainer.createButtonLayout("filter_buttons", getTranslator()); leftContainer.setRootForm(mainForm); formLayout.add(filterButtonLayout); // Left part of the filter createdAtNewerChooser = uifactory.addDateChooser("largefiles.filter.created.newer", "largefiles.filter.created.newer", null, leftContainer); editedAtNewerChooser = uifactory.addDateChooser("largefiles.filter.edited.newer", "largefiles.filter.edited.newer", null, leftContainer); lockedAtNewerChooser = uifactory.addDateChooser("largefiles.filter.locked.newer", null, leftContainer); revisionCountMinEl = uifactory.addIntegerElement("largefiles.filter.revision.count.min", "largefiles.filter.revision.count.min", 0, leftContainer); downloadCountMinEl = uifactory.addIntegerElement("largefiles.filter.download.count.min", "largefiles.filter.download.count.min", 0, leftContainer); maxResultEl = uifactory.addIntegerElement("largefiles.filter.results.max", 100, leftContainer); maxSizeEl = uifactory.addIntegerElement("largefiles.filter.size.min", 0, leftContainer); // Right part of the filter createdAtOlderChooser = uifactory.addDateChooser("largefiles.filter.created.older", "largefiles.filter.created.older", null, rightContainer); editedAtOlderChooser = uifactory.addDateChooser("largefiles.filter.edited.older", "largefiles.filter.edited.older", null, rightContainer); lockedAtOlderChooser = uifactory.addDateChooser("largefiles.filter.locked.older", null, rightContainer); String[] trashedValues = new String[] { translate("largefiles.filter.trashed.only"), translate("largefiles.filter.trashed.not"), translate("largefiles.filter.trashed.both") }; trashedSelection = uifactory.addRadiosHorizontal("largefiles.filter.trashed", "largefiles.filter.trashed", rightContainer, TRASHED_KEYS, trashedValues); trashedSelection.select(TRASHED_KEYS[2], true); String[] revisionValues = new String[] { translate("largefiles.filter.revision.only"), translate("largefiles.filter.revision.not"), translate("largefiles.filter.revision.both") }; revisionSelection = uifactory.addRadiosHorizontal("largefiles.filter.revision", "largefiles.filter.revision", rightContainer, REVISION_KEYS, revisionValues); revisionSelection.select(REVISION_KEYS[2], true); String[] lockedValues = new String[] { translate("largefiles.filter.locked.only"), translate("largefiles.filter.locked.not"), translate("largefiles.filter.locked.both") }; lockedSelection = uifactory.addRadiosHorizontal("largefiles.filter.locked", rightContainer, LOCKED_KEYS, lockedValues); lockedSelection.select(LOCKED_KEYS[2], true); // Filter buttons searchButton = uifactory.addFormLink("largefiles.filter.button.search", filterButtonLayout, Link.BUTTON); searchButton.setCustomEnabledLinkCSS("btn btn-primary"); resetButton = uifactory.addFormLink("largefiles.filter.button.reset", filterButtonLayout, Link.BUTTON); // Tabled FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); DefaultFlexiColumnModel column; columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.key)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.uuid)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, true, LargeFilesTableColumns.name, new LargeFilesNameCellRenderer())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, true, LargeFilesTableColumns.size, new LargeFilesSizeCellRenderer())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, LargeFilesTableColumns.path)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.age)); column = new DefaultFlexiColumnModel(false, LargeFilesTableColumns.trashed, new LargeFilesTrashedCellRenderer()); column.setIconHeader(CSSHelper.getIconCssClassFor(CSSHelper.CSS_CLASS_TRASHED)); columnsModel.addFlexiColumnModel(column); column = new DefaultFlexiColumnModel(false, LargeFilesTableColumns.revision, new LargeFilesRevisionCellRenderer()); column.setIconHeader(CSSHelper.getIconCssClassFor(CSSHelper.CSS_CLASS_REVISION)); columnsModel.addFlexiColumnModel(column); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.revisionNr)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.revisionComment)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.fileCategory)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.fileType)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.downloadCount)); DefaultFlexiColumnModel sendMail = new DefaultFlexiColumnModel(false, LargeFilesTableColumns.sendMail, "sendMail", new LargeFilesSendMailCellRenderer()); sendMail.setIconHeader(CSSHelper.getIconCssClassFor(CSSHelper.CSS_CLASS_MAIL)); columnsModel.addFlexiColumnModel(sendMail); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.author, "selectAuthor")); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.license)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.language)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.source)); column = new DefaultFlexiColumnModel(false, LargeFilesTableColumns.locked, new LargeFilesLockedCellRenderer()); column.setIconHeader(CSSHelper.getIconCssClassFor(CSSHelper.CSS_CLASS_LOCKED)); columnsModel.addFlexiColumnModel(column); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.lockedAt)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.lockedBy, "selectLockedBy")); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.creator)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.publisher)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.pubDate)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.createdAt)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.lastModifiedAt)); largeFilesTableModel = new LargeFilesTableModel(columnsModel, getLocale()); largeFilesTableElement = uifactory.addTableElement(getWindowControl(), "large_files", largeFilesTableModel, getTranslator(), formLayout); FlexiTableSortOptions sortOptions = new FlexiTableSortOptions(); sortOptions.setDefaultOrderBy(new SortKey(LargeFilesTableColumns.size.name(), false)); sortOptions.setFromColumnModel(true); largeFilesTableElement.setSortSettings(sortOptions); largeFilesTableElement.setAndLoadPersistedPreferences(ureq, "admin-large-files-list"); largeFilesTableElement.setSearchEnabled(false); largeFilesTableElement.setExportEnabled(true); } @Override protected void doDispose() { } @Override protected void formOK(UserRequest ureq) { updateModel(); } @Override protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { if(source == largeFilesTableElement) { if(event instanceof SelectionEvent) { SelectionEvent te = (SelectionEvent) event; String cmd = te.getCommand(); LargeFilesTableContentRow contentRow = largeFilesTableModel.getObject(te.getIndex()); if("selectAuthor".equals(cmd)) { if (contentRow.getAuthor() != null) { openUser(ureq, contentRow.getAuthor().getKey()); } } else if("selectLockedBy".equals(cmd)) { if (contentRow.getLockedBy() != null) { openUser(ureq, contentRow.getLockedBy().getKey()); } } else if("sendMail".equals(cmd)) { if (contentRow.getAuthor() != null) { contactUser(ureq, contentRow.getAuthor()); } } } } else if(source == searchButton) { updateModel(); } else if(source == resetButton) { resetForm(); } else if(source instanceof FormLink) { FormLink link = (FormLink) source; if("pathInfo".equals(link.getCmd())) { removeAsListenerAndDispose(pathInfoCalloutCtrl); LargeFilesTableContentRow row = (LargeFilesTableContentRow) link.getUserObject(); System.out.println(link.getUserObject()); CalloutSettings settings = new CalloutSettings(false); pathInfoCalloutCtrl = new CloseableCalloutWindowController(ureq, getWindowControl(), TextFactory.createTextComponentFromString("pathInfo", row.getPath(), "", true, null), link.getFormDispatchId(), "", true, "", settings); listenTo(pathInfoCalloutCtrl); pathInfoCalloutCtrl.activate(); } } super.formInnerEvent(ureq, source, event); } @Override protected void event(UserRequest ureq, Controller source, Event event) { if (source == cmc) { cleanUp(); } else if (source == contactCtrl) { cmc.deactivate(); cleanUp(); } } private void cleanUp() { removeAsListenerAndDispose(cmc); removeAsListenerAndDispose(contactCtrl); removeAsListenerAndDispose(pathInfoCalloutCtrl); cmc = null; contactCtrl = null; pathInfoCalloutCtrl = null; } private void contactUser(UserRequest ureq, Identity user) { removeAsListenerAndDispose(cmc); ContactMessage cmsg = new ContactMessage(getIdentity()); String fullName = user.getUser().getFirstName() + " " + user.getUser().getLastName(); ContactList contactList = new ContactList(fullName); contactList.add(user); cmsg.addEmailTo(contactList); cmsg.setSubject("Too large files in your personal folder"); StringBuilder sb = new StringBuilder(); String bodyStart = translate("largefiles.mail.start", new String[] {user.getUser().getFirstName() + user.getUser().getLastName()}); String bodyFiles = "<ul>"; String bodyEnd = translate("largefiles.mail.end"); for(LargeFilesTableContentRow row:rows) { if (row.getAuthor() == user) { bodyFiles += "<li><b>" + Formatter.formatBytes(row.getSize()) + "</b> - " +row.getName() + "</li>"; } } bodyFiles += "</ul>"; cmsg.setBodyText(bodyStart + bodyFiles + bodyEnd); contactCtrl = new ContactFormController(ureq, getWindowControl(), true, false, false, cmsg, null); listenTo(contactCtrl); cmc = new CloseableModalController(getWindowControl(), "close", contactCtrl.getInitialComponent()); cmc.activate(); listenTo(cmc); } @Override public void setEnabled(boolean enable) { this.enabled = enable; } @Override protected boolean validateFormLogic(UserRequest ureq) { if(!enabled) return true; return true; } @Override public List<String> getConditionalQueries() { return Collections.emptyList(); } private void openUser(UserRequest ureq, Long userKey) { NewControllerFactory.getInstance().launch("[UserAdminSite:0][usearch:0][table:0][Identity:" + userKey.toString() + "]", ureq, getWindowControl()); } }