Skip to content

Commit

Permalink
feature: implement file manager, WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
mutantsan committed Jan 28, 2024
1 parent 19d9cc0 commit 733f90b
Show file tree
Hide file tree
Showing 10 changed files with 414 additions and 0 deletions.
Empty file.
139 changes: 139 additions & 0 deletions ckanext/file_manager/collection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
from __future__ import annotations

from typing import Any

from dominate import tags

import ckan.plugins.toolkit as tk
import sqlalchemy as sa

from ckanext.collection.types import InputFilter, LinkFilter
from ckanext.collection.utils import Filters, StatementSaData

from ckanext.ap_main.collection.base import (
ApCollection,
ApColumns,
BulkAction,
RowAction,
ApHtmxTableSerializer,
)

from ckanext.files.model import File


class FileManagerCollection(ApCollection[Any]):
SerializerFactory = ApHtmxTableSerializer.with_attributes(
record_template="file_manager/record.html"
)

ColumnsFactory = ApColumns.with_attributes(
names=[
"bulk-action",
"name",
"path",
"kind",
"uploaded_at",
"extras",
"row_actions",
],
sortable={"name", "kind", "uploaded_at"},
searchable={"name"},
labels={
"bulk-action": tk.literal(
tags.input_(
type="checkbox",
name="bulk_check",
id="bulk_check",
data_module="ap-bulk-check",
data_module_selector='input[name="id"]',
)
),
"name": "Name",
"path": "Path",
"kind": "Type",
"uploaded_at": "Uploaded At",
"extras": "Extras",
"row_actions": "Actions",
},
width={"name": "20%", "path": "20%"},
serializers={
"uploaded_at": [("date", {})],
"extras": [("json_display", {})],
},
)

DataFactory = StatementSaData.with_attributes(
model=File,
use_naive_filters=True,
use_naive_search=True,
statement=sa.select(
File.id.label("bulk-action"),
File.id.label("id"),
File.name.label("name"),
File.path.label("path"),
File.kind.label("kind"),
File.uploaded_at.label("uploaded_at"),
File.extras.label("extras"),
),
)

FiltersFactory = Filters.with_attributes(
static_actions=[
BulkAction(
name="bulk-action",
type="bulk_action",
options={
"label": "Action",
"options": [
{"value": "1", "text": "Remove selected files"},
],
},
),
RowAction(
name="edit",
type="row_action",
options={
"endpoint": "",
"label": "",
"icon": "fa fa-pencil",
"params": {
"data-module-path": "$id",
"entity_type": "$type",
"view": "edit",
},
},
),
RowAction(
name="view",
type="row_action",
options={
"endpoint": "ap_content.entity_proxy",
"label": "View",
"params": {
"entity_id": "$id",
"entity_type": "$type",
"view": "read",
},
},
),
],
static_filters=[
InputFilter(
name="q",
type="input",
options={
"label": "Search",
"placeholder": "Search",
},
),
LinkFilter(
name="clear",
type="link",
options={
"label": "Clear",
"endpoint": "file_manager.list",
"kwargs": {},
},
),
],
)
49 changes: 49 additions & 0 deletions ckanext/file_manager/plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from __future__ import annotations

import ckan.plugins as p
import ckan.plugins.toolkit as tk

import ckanext.ap_main.types as ap_types
from ckanext.ap_main.interfaces import IAdminPanel

from ckanext.collection.interfaces import ICollection, CollectionFactory

from ckanext.file_manager.collection import FileManagerCollection


@tk.blanket.blueprints
class FileManagerPlugin(p.SingletonPlugin):
p.implements(p.IConfigurer)
p.implements(IAdminPanel, inherit=True)
p.implements(ICollection, inherit=True)

# IConfigurer

def update_config(self, config_):
tk.add_template_directory(config_, "templates")
tk.add_public_directory(config_, "public")
tk.add_resource("assets", "file_manager")

# IAdminPanel

def register_config_sections(
self, config_list: list[ap_types.SectionConfig]
) -> list[ap_types.SectionConfig]:
config_list.append(
ap_types.SectionConfig(
name="Files",
configs=[
ap_types.ConfigurationItem(
name="File manager",
blueprint="file_manager.list",
info="Manage uploaded files",
)
],
)
)
return config_list

# ICollection

def get_collection_factories(self) -> dict[str, CollectionFactory]:
return {"file-manager": FileManagerCollection}
38 changes: 38 additions & 0 deletions ckanext/file_manager/templates/file_manager/list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{% extends 'admin_panel/base.html' %}

{% import 'macros/autoform.html' as autoform %}
{% import 'macros/form.html' as form %}
{% import 'admin_panel/macros/form.html' as ap_form %}

{% block ap_main_class %} ap-log-list {% endblock %}

{% block breadcrumb_content %}
<li>{% link_for _("File manager"), request.endpoint %}</li>
{% endblock breadcrumb_content %}

{% block ap_content %}
<div class="file-manager--manage mb-2">
<button
type="button"
class="btn btn-success"
data-bs-toggle="modal"
data-bs-target="#upload-file">
{{ _("Upload file")}}
</button>
</div>

<form action="{{ h.url_for('file_manager.upload') }}" method="POST" id="ap-cron-add" enctype="multipart/form-data">
{% snippet 'file_manager/upload_file_modal.html' %}
</form>

<div class="row g-3">
{% if collection.data.total %}
{{ collection.serializer.render() | safe }}
{% else %}
<p>
{{ _("No files found") }}
<a href="{{ request.path }}">{{ _("Clear the search") }}</a>
</p>
{% endif %}
</div> <!-- row -->
{% endblock ap_content %}
30 changes: 30 additions & 0 deletions ckanext/file_manager/templates/file_manager/record.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{% extends "collection/serialize/ap_htmx_table/record.html" %}

{% block value %}
{% if column == "row_actions" %}
<a
data-module="ap-tooltip fm-copy-url"
title="{{ _('Copy file URL')}}"
class="btn btn-black">
<i class="fas fa-copy"></i>
</a>

<a
data-module="ap-tooltip fm-copy-url"
title="{{ _('Download file')}}"
class="btn btn-primary">
<i class="fas fa-download"></i>
</a>


<a
data-module="ap-tooltip" title="{{ _('Remove a file') }}"
class="btn btn-danger"
href="{{ h.url_for('file_manager.delete', file_id=data.id) }}"
hx-swap="none" hx-trigger="click" hx-post="{{ h.url_for('file_manager.delete', file_id=data.id) }}">
<i class="fa fa-trash-alt"></i>
</a>
{% else %}
{{ super() }}
{% endif %}
{% endblock value %}
22 changes: 22 additions & 0 deletions ckanext/file_manager/templates/file_manager/upload_file_modal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{% import 'macros/form.html' as form %}

<!-- Modal -->
<div class="modal fade" id="upload-file" tabindex="-1" class="upload-file-modal" aria-labelledby="upload-file-label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="upload-file-label">{{ _("Upload file")}}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> <!-- .modal-header -->

<div class="modal-body">
{% snippet 'file_manager/upload_file_modal_form.html', data={} %}
</div> <!-- .modal-body -->

<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ _("Cancel") }}</button>
<button type="submit" class="btn btn-primary">{{ _("Upload") }}</button>
</div> <!-- .modal-footer -->
</div> <!-- .modal-content -->
</div> <!-- .modal-dialog -->
</div> <!-- .modal -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<input
type="file"
id="upload"
name="upload"
accept=".doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document" />
Loading

0 comments on commit 733f90b

Please sign in to comment.