usethesource: Add prototype "upload offer for source"
This commit is contained in:
parent
a2f38653fb
commit
770f4f6c26
6 changed files with 117 additions and 2 deletions
|
@ -1,6 +1,6 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
from .models import Comment
|
from .models import Comment, SourceOffer
|
||||||
|
|
||||||
|
|
||||||
class CommentForm(forms.ModelForm):
|
class CommentForm(forms.ModelForm):
|
||||||
|
@ -17,3 +17,14 @@ class CommentForm(forms.ModelForm):
|
||||||
|
|
||||||
class DownloadForm(forms.Form):
|
class DownloadForm(forms.Form):
|
||||||
agree = forms.BooleanField(label="I understand that the goal of this process is to determine compliance with FOSS licenses, and that in downloading the source code candidate and/or firmware image, I am assisting SFC as a volunteer to investigate that question. I, therefore, promise and represent that I will not copy, distribute, modify, or otherwise use this source code candidate and/or firmware image for any purpose other than to help SFC evaluate the source code candidate for compliance with the terms of FOSS licenses, including but not limited to any version of the GNU General Public License. Naturally, if I determine in good faith that portions of the source code candidate and/or firmware image are subject to a FOSS license and are compliant with it, I may copy, distribute, modify, or otherwise use those portions in accordance with the FOSS license, and I take full responsibility for that determination and subsequent use.")
|
agree = forms.BooleanField(label="I understand that the goal of this process is to determine compliance with FOSS licenses, and that in downloading the source code candidate and/or firmware image, I am assisting SFC as a volunteer to investigate that question. I, therefore, promise and represent that I will not copy, distribute, modify, or otherwise use this source code candidate and/or firmware image for any purpose other than to help SFC evaluate the source code candidate for compliance with the terms of FOSS licenses, including but not limited to any version of the GNU General Public License. Naturally, if I determine in good faith that portions of the source code candidate and/or firmware image are subject to a FOSS license and are compliant with it, I may copy, distribute, modify, or otherwise use those portions in accordance with the FOSS license, and I take full responsibility for that determination and subsequent use.")
|
||||||
|
|
||||||
|
|
||||||
|
class SourceOfferForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = SourceOffer
|
||||||
|
fields = ['vendor', 'device', 'photo']
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.fields['photo'].widget.attrs['capture'] = 'camera'
|
||||||
|
self.fields['photo'].widget.attrs['accept'] = 'image/*'
|
||||||
|
|
30
conservancy/usethesource/migrations/0009_sourceoffer.py
Normal file
30
conservancy/usethesource/migrations/0009_sourceoffer.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# Generated by Django 4.2.11 on 2024-07-22 08:59
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('usethesource', '0008_comment_attribute_to'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SourceOffer',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.AutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='ID',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('vendor', models.CharField(max_length=50, verbose_name='Vendor name')),
|
||||||
|
('device', models.CharField(max_length=50, verbose_name='Device name')),
|
||||||
|
('photo', models.ImageField(upload_to='usethesource/offers')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
|
@ -67,3 +67,9 @@ class Comment(models.Model):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['id']
|
ordering = ['id']
|
||||||
|
|
||||||
|
|
||||||
|
class SourceOffer(models.Model):
|
||||||
|
vendor = models.CharField('Vendor name', max_length=50)
|
||||||
|
device = models.CharField('Device name', max_length=50)
|
||||||
|
photo = models.ImageField(upload_to='usethesource/offers')
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
{% extends "usethesource/base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Upload an offer for source - Software Freedom Conservancy{% endblock %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
{{ block.super }}
|
||||||
|
<script src="https://unpkg.com/htmx.org@1.9.6"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{{ block.super }}
|
||||||
|
|
||||||
|
<section class="mt4 mb3">
|
||||||
|
<h2 class="f2 lh-title ttu mt0">Upload an offer for source</h2>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<form id="form" hx-encoding="multipart/form-data" hx-post="{% url 'usethesource:upload_offer' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.non_field_errors }}
|
||||||
|
<div class="mv2">
|
||||||
|
{{ form.vendor.errors }}
|
||||||
|
<label for="{{ form.vendor.id_for_label }}" class="db mb1">Vendor:</label>
|
||||||
|
{{ form.vendor }}
|
||||||
|
</div>
|
||||||
|
<div class="mv2">
|
||||||
|
{{ form.device.errors }}
|
||||||
|
<label for="{{ form.device.id_for_label }}" class="db mb1">Device:</label>
|
||||||
|
{{ form.device }}
|
||||||
|
</div>
|
||||||
|
<div class="mv2">
|
||||||
|
{{ form.photo.errors }}
|
||||||
|
<label for="{{ form.photo.id_for_label }}" class="db mb1">Photo:</label>
|
||||||
|
{{ form.photo }}
|
||||||
|
</div>
|
||||||
|
<progress id="progress" class="htmx-indicator" value="0" max="100"></progress>
|
||||||
|
<div class="mv1">
|
||||||
|
<button type="submit" class="white bg-green b db pv2 ph3 bn mb2">Send</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
form = document.querySelector('#form');
|
||||||
|
let progress = document.querySelector('#progress');
|
||||||
|
form.addEventListener('htmx:xhr:progress', function(evt) {
|
||||||
|
console.log('progress', evt.detail.loaded/evt.detail.total * 100);
|
||||||
|
progress.value = evt.detail.loaded/evt.detail.total * 100;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock content %}
|
|
@ -13,4 +13,5 @@ urlpatterns = [
|
||||||
path('delete-comment/<int:comment_id>/<show_add>/', views.delete_comment, name='delete_comment'),
|
path('delete-comment/<int:comment_id>/<show_add>/', views.delete_comment, name='delete_comment'),
|
||||||
path('add-button/<slug:slug>/', views.add_button, name='add_button'),
|
path('add-button/<slug:slug>/', views.add_button, name='add_button'),
|
||||||
path('ccirt-process/', views.ccirt_process, name='ccirt_process'),
|
path('ccirt-process/', views.ccirt_process, name='ccirt_process'),
|
||||||
|
path('offer/', views.upload_offer, name='upload_offer'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -3,7 +3,7 @@ from django.core.exceptions import PermissionDenied
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
|
|
||||||
from .models import Candidate, Comment
|
from .models import Candidate, Comment
|
||||||
from .forms import CommentForm, DownloadForm
|
from .forms import CommentForm, DownloadForm, SourceOfferForm
|
||||||
from .emails import make_comment_email
|
from .emails import make_comment_email
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,3 +91,21 @@ def add_button(request, slug):
|
||||||
|
|
||||||
def ccirt_process(request):
|
def ccirt_process(request):
|
||||||
return render(request, 'usethesource/ccirt_process.html', {})
|
return render(request, 'usethesource/ccirt_process.html', {})
|
||||||
|
|
||||||
|
|
||||||
|
def handle_uploaded_file(f):
|
||||||
|
with open("some/file/name.txt", "wb+") as destination:
|
||||||
|
for chunk in f.chunks():
|
||||||
|
destination.write(chunk)
|
||||||
|
|
||||||
|
def upload_offer(request):
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = SourceOfferForm(request.POST, request.FILES)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
return render(request, 'usethesource/upload_success_partial.html')
|
||||||
|
else:
|
||||||
|
return render(request, 'usethesource/upload_offer.html', {'form': form})
|
||||||
|
else:
|
||||||
|
form = SourceOfferForm()
|
||||||
|
return render(request, 'usethesource/upload_offer.html', {'form': form})
|
||||||
|
|
Loading…
Reference in a new issue