Skip to content

Commit

Permalink
feat: checkpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
YiqingQu committed Nov 20, 2023
1 parent 0aae5fe commit bc4ebac
Show file tree
Hide file tree
Showing 22 changed files with 621 additions and 245 deletions.
Binary file added media/group/Certificate - Yiqing Qu.pdf
Binary file not shown.
Binary file added media/group/Survey Design - Yiqing Qu.pdf
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file added media/idata_files/new_dir/IRB_Scavenger_Hunt.docx
Binary file not shown.
Binary file not shown.
Binary file added media/idata_files/wrfinput_d0x.nc
Binary file not shown.
3 changes: 2 additions & 1 deletion myportal/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
from pathlib import Path

GLOBUS_INDEX_NAME = "schema-org-index"
OLD_GLOBUS_INDEX_NAME = "schema-org-index-v1"

RMQ_NAME = "geoedf-all"
RMQ_HOST = 'rabbitmq-server'
RMQ_HOST_IP = '172.17.0.2'
RMQ_HOST_IP = '172.17.0.3'
# RMQ_HOST = 'some-rabbit'
RMQ_USER = 'guest'
RMQ_PASS = 'guest'
Expand Down
35 changes: 34 additions & 1 deletion myportal/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
# LOGIN_URL = '/login/globus'
ACCOUNT_LOGOUT_REDIRECT_URL = '/accounts/login/'
LOGIN_REDIRECT_URL = '/accounts/profile/'
ACCOUNT_DEFAULT_HTTP_PROTOCOL = 'https'
ACCOUNT_DEFAULT_HTTP_PROTOCOL = 'https' # todo local

# This dictates which scopes will be requested on each user login
SOCIAL_AUTH_GLOBUS_SCOPE = [
Expand All @@ -74,6 +74,39 @@
PROJECT_TITLE = 'GeoEDF Resource Data Portal'
SEARCH_INDEXES = {
'schema-org-index': {
'uuid': 'dfbccff7-36f8-43e2-9e6e-c38059184985',
'name': 'GeoEDF Index',
'template_override_dir': 'geoedf-index',
'fields': [
('extension', fields.extension),
('size_bytes', fields.size_bytes),
('name', fields.name),
('id', fields.identifier),
],
'facets': [ # limit of 3 facets
{
'name': 'Creator',
'field_name': '[email protected]',
'size': 10,
'type': 'terms'
},
{
'name': 'Tags',
'field_name': 'tags',
'size': 10,
'type': 'terms'
},
{
'name': 'Extension',
'field_name': 'extension',
'size': 10,
'type': 'terms'
},


],
},
'schema-org-index-v1': {
'uuid': '15a6acc8-3a23-42ed-98cf-a32833acaae3',
'name': 'Schema.org Json Index',
'template_override_dir': 'schema-org-index',
Expand Down
8 changes: 8 additions & 0 deletions myportal/static/css/file-manager.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,11 @@ ul li {
.modal {
z-index: 99999 !important;
}

tr:hover {
background-color: #f5f5f5;
}

i:hover {
cursor: pointer;
}
443 changes: 340 additions & 103 deletions myportal/templates/file-management/file-manager.html

Large diffs are not rendered by default.

31 changes: 31 additions & 0 deletions myportal/templates/file-management/subdirectories.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{% load static file_extension %}

{% for subdirectory in directory.directories %}
{% if subdirectory.directories %}
<li
id="collapse{{ directory.id }}"
class="ms-{{ depth }} collapse show"
>
<i class="fa-solid fa-folder"></i>
<a
data-bs-toggle="collapse"
href="#collapse{{ subdirectory.id }}"
role="button"
aria-expanded="false"
aria-controls="collapse{{ subdirectory.id }}"
onclick="window.location.href = '{% url 'file-manage' subdirectory.path|encoded_path %}';"
>
{{ subdirectory.name }}
</a>
</li>
{% include 'file-management/subdirectories.html' with directory=subdirectory depth=depth|add:"20" %}
{% else %}
<li
id="collapse{{ directory.id }}"
class="ms-{{ depth }} collapse show"
>
<i class="fa-solid fa-folder"></i>
<a href="{% url 'file-manage' subdirectory.path|encoded_path %}">{{ subdirectory.name }}</a>
</li>
{% endif %}
{% endfor %}
6 changes: 4 additions & 2 deletions myportal/views/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from django.urls import path, include, re_path
from myportal.views import api_account, api_resource
from myportal.views.views import temp_view, file_detail, mysearch, GetAccountProfile, FileManager, delete_file, \
upload_file, download_file, save_info
from myportal.views.file_manager_views import FileManager, delete_file, download_file, upload_file, save_info, \
create_directory
from myportal.views.views import temp_view, file_detail, mysearch, GetAccountProfile
from globus_portal_framework.urls import register_custom_index

register_custom_index('custom_search', ['schema-org-index'])
Expand Down Expand Up @@ -33,4 +34,5 @@
path('file/download/<str:file_path>/', download_file, name='download_file'),
path('file/upload/', upload_file, name='upload_file'),
path('file/update/<str:file_path>/', save_info, name='save_info'),
path('file/create-directory/', create_directory, name='create_directory'),
]
198 changes: 198 additions & 0 deletions myportal/views/file_manager_views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
import csv
import datetime
import json
import os

import requests
from allauth.socialaccount.models import SocialToken
from django.conf import settings
from django.contrib.auth.models import AnonymousUser
from django.contrib.sites.models import Site
from django.http import HttpResponseBadRequest, JsonResponse, HttpResponse, Http404
from django.views import View
from drf_yasg import openapi
from globus_portal_framework import gsearch
from globus_portal_framework.apps import get_setting
from globus_portal_framework.gsearch import post_search, get_search_query, get_search_filters, get_template, \
get_subject, get_index
from django.shortcuts import render, redirect
from django.contrib.sites.shortcuts import get_current_site
from django.utils.functional import SimpleLazyObject

from myportal.constants import GLOBUS_INDEX_NAME, FILES_ROOT
from myportal.utils import generate_nested_directory
from django.shortcuts import render, redirect
from django.core.files.storage import FileSystemStorage


class FileManager(View):
def get_breadcrumbs(self, request):
path_components = [component for component in request.path.split("/") if component]
breadcrumbs = []
url = ''

for component in path_components:
url += f'/{component}'
if component == "file-manager":
component = "media"
breadcrumbs.append({'name': component, 'url': url})

return breadcrumbs

def convert_csv_to_text(self, csv_file_path):
with open(csv_file_path, 'r') as file:
reader = csv.reader(file)
rows = list(reader)

text = ''
for row in rows:
text += ','.join(row) + '\n'

return text

def get_files_from_directory(self, directory_path):
files = []
directories = []
for filename in os.listdir(directory_path):
file_path = os.path.join(directory_path, filename)
if os.path.isfile(file_path):
try:
# print(' > file_path ' + file_path)
_, extension = os.path.splitext(filename)
if extension.lower() == '.csv':
csv_text = self.convert_csv_to_text(file_path)
else:
csv_text = ''

last_modified_time = os.path.getmtime(file_path)
file_size = os.path.getsize(file_path)
# print("os.sep" + os.sep)
files.append({
'file': file_path.split(os.sep + 'media' + os.sep)[1],
'filename': filename,
'file_path': file_path,
'visibility': 'private',
'last_modified_time': datetime.datetime.fromtimestamp(last_modified_time),
'size': file_size,
'csv_text': csv_text
})
continue
except Exception as e:
print(' > ' + str(e))
if os.path.isdir(file_path):
try:
last_modified_time = os.path.getmtime(file_path)
# file_size = os.path.getsize(file_path)
# print("os.sep" + os.sep)
directories.append({
'dir': file_path.split(os.sep + 'media' + os.sep)[1],
'dirname': filename,
'dir_path': file_path,
'visibility': 'private',
'last_modified_time': datetime.datetime.fromtimestamp(last_modified_time),
})
continue
except Exception as e:
print(' > ' + str(e))

return files, directories

def get(self, request, directory=settings.MEDIA_ROOT, *args, **kwargs):
media_path = os.path.join(settings.MEDIA_ROOT)

directories = generate_nested_directory(media_path, media_path)
selected_directory = directory

files = []
dirs = []
selected_directory_path = os.path.join(media_path, selected_directory)
if os.path.isdir(selected_directory_path):
files, dirs = self.get_files_from_directory(selected_directory_path)

breadcrumbs = self.get_breadcrumbs(request)
context = {
'directories': directories,
'files': files,
'dirs': dirs,
'selected_directory': selected_directory,
'segment': 'file_manager',
'breadcrumbs': breadcrumbs
}
print(context)
return render(request, 'file-management/file-manager.html', context)


def delete_file(request, file_path):
path = file_path.replace('%slash%', '/')
absolute_file_path = os.path.join(settings.MEDIA_ROOT, path)
os.remove(absolute_file_path)
print("File deleted", absolute_file_path)
return redirect(request.META.get('HTTP_REFERER'))


def download_file(request, file_path):
path = file_path.replace('%slash%', '/')
absolute_file_path = os.path.join(settings.MEDIA_ROOT, path)
print("[download_file]", absolute_file_path)

if os.path.exists(absolute_file_path):
with open(absolute_file_path, 'rb') as fh:
response = HttpResponse(fh.read(), content_type="application/vnd.ms-excel")
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(absolute_file_path)
return response
raise Http404


def upload_file(request):
if request.method == 'POST' and request.FILES['file']:
if 'file' in request.FILES:
uploaded_file = request.FILES['file']
else:
return JsonResponse({'error': 'file not in FILES'}, status=400)

directory = request.POST.get('directory')

fs = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, directory)) # saves to the 'files' directory under MEDIA_ROOT
filename = fs.save(uploaded_file.name, uploaded_file)
file_url = fs.url(filename) # You can get the file URL if needed

# return JsonResponse({'message': 'File uploaded successfully!'})
return redirect(request.META.get('HTTP_REFERER'))


def create_directory(request):
if request.method == 'POST':
print("create_directory", request)

# Get the current directory and the name of the new directory from the POST data
selected_directory = request.POST.get('current_directory')
directory_name = request.POST.get('directory_name')

# Sanitize and validate the input (very important)
if not directory_name or '..' in directory_name or '/' in directory_name:
# Return an error response or redirect with an error message
return HttpResponse("Invalid directory name", status=400)

# Construct the full path of the new directory
new_directory_path = os.path.join(settings.MEDIA_ROOT, selected_directory, directory_name)

# Create the directory
os.makedirs(new_directory_path, exist_ok=True)

return redirect(request.META.get('HTTP_REFERER'))

# If the request method is not POST, redirect or return an error
return HttpResponse("Method not allowed", status=405)


def save_info(request, file_path):
path = file_path.replace('%slash%', '/')
# if request.method == 'POST':
# FileInfo.objects.update_or_create(
# path=path,
# defaults={
# 'info': request.POST.get('info')
# }
# )

return redirect(request.META.get('HTTP_REFERER'))
Loading

0 comments on commit bc4ebac

Please sign in to comment.