initial commit
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
# Generated by Django 5.2.13 on 2026-04-27 09:07
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='DownloadItem',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=200)),
|
||||
('platform', models.CharField(choices=[('windows', 'Windows'), ('macos', 'macOS'), ('linux', 'Linux')], max_length=20)),
|
||||
('version', models.CharField(max_length=50)),
|
||||
('download_url', models.URLField()),
|
||||
('description', models.TextField(blank=True)),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
('order', models.PositiveIntegerField(default=0)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Download Item',
|
||||
'verbose_name_plural': 'Download Items',
|
||||
'ordering': ['order', 'platform'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='FAQEntry',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('question', models.CharField(max_length=500)),
|
||||
('answer', models.TextField()),
|
||||
('order', models.PositiveIntegerField(default=0)),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'FAQ Entry',
|
||||
'verbose_name_plural': 'FAQ Entries',
|
||||
'ordering': ['order'],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,30 @@
|
||||
# Generated by Django 5.0.2 on 2026-05-04 09:13
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pages', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ContactSubmission',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=200)),
|
||||
('title', models.CharField(max_length=300)),
|
||||
('description', models.TextField()),
|
||||
('email', models.EmailField(blank=True, max_length=254)),
|
||||
('submitted_at', models.DateTimeField(auto_now_add=True)),
|
||||
('is_read', models.BooleanField(default=False)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Contact Submission',
|
||||
'verbose_name_plural': 'Contact Submissions',
|
||||
'ordering': ['-submitted_at'],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.0.2 on 2026-05-14 05:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pages', '0002_contactsubmission'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='faqentry',
|
||||
name='answer_format',
|
||||
field=models.CharField(choices=[('plain', 'Plain Text'), ('markdown', 'Markdown'), ('html', 'HTML')], default='plain', max_length=20),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,103 @@
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("pages", "0003_faqentry_answer_format"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="AboutSection",
|
||||
fields=[
|
||||
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
|
||||
(
|
||||
"section_type",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("hero", "Hero"),
|
||||
("intro", "Intro Card"),
|
||||
("grid", "Grid Cards"),
|
||||
("history", "History Block"),
|
||||
("custom", "Custom Content"),
|
||||
],
|
||||
default="custom",
|
||||
max_length=30,
|
||||
),
|
||||
),
|
||||
("badge", models.CharField(blank=True, max_length=100)),
|
||||
("title", models.CharField(blank=True, max_length=300)),
|
||||
(
|
||||
"subtitle",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
help_text="Used as subtitle in Hero and year in History.",
|
||||
max_length=500,
|
||||
),
|
||||
),
|
||||
("content", models.TextField(blank=True)),
|
||||
(
|
||||
"content_format",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("plain", "Plain Text"),
|
||||
("markdown", "Markdown"),
|
||||
("html", "HTML"),
|
||||
],
|
||||
default="markdown",
|
||||
max_length=20,
|
||||
),
|
||||
),
|
||||
("order", models.PositiveIntegerField(default=0)),
|
||||
("is_active", models.BooleanField(default=True)),
|
||||
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||
("updated_at", models.DateTimeField(auto_now=True)),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "About Section",
|
||||
"verbose_name_plural": "About Sections",
|
||||
"ordering": ["order"],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="AboutSectionItem",
|
||||
fields=[
|
||||
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
|
||||
(
|
||||
"section",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="items",
|
||||
to="pages.aboutsection",
|
||||
),
|
||||
),
|
||||
("badge", models.CharField(blank=True, max_length=100)),
|
||||
("title", models.CharField(blank=True, max_length=300)),
|
||||
(
|
||||
"content",
|
||||
models.TextField(
|
||||
blank=True,
|
||||
help_text="Description text or link label for History links.",
|
||||
),
|
||||
),
|
||||
("url", models.URLField(blank=True, help_text="Used for History block links.")),
|
||||
("image", models.ImageField(blank=True, null=True, upload_to="about/")),
|
||||
("image_alt", models.CharField(blank=True, max_length=200)),
|
||||
(
|
||||
"is_featured",
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text="Mark as featured item (e.g. large screenshot).",
|
||||
),
|
||||
),
|
||||
("order", models.PositiveIntegerField(default=0)),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "About Section Item",
|
||||
"verbose_name_plural": "About Section Items",
|
||||
"ordering": ["order"],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,49 @@
|
||||
# Generated by Django 5.0.2 on 2026-05-17 14:39
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pages', '0004_aboutsection_aboutsectionitem'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='HomepageSection',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('section_type', models.CharField(choices=[('features', 'Features'), ('screenshots', 'Screenshots Gallery'), ('products', 'Products'), ('problems', 'Problems / Value Proposition'), ('about_strip', 'About Strip')], max_length=30, unique=True)),
|
||||
('badge', models.CharField(blank=True, max_length=100)),
|
||||
('title', models.CharField(blank=True, max_length=300)),
|
||||
('description', models.TextField(blank=True)),
|
||||
('link_text', models.CharField(blank=True, help_text='CTA button label (About Strip).', max_length=100)),
|
||||
('link_url', models.CharField(blank=True, help_text='CTA button URL (About Strip).', max_length=300)),
|
||||
('order', models.PositiveIntegerField(default=0)),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Homepage Section',
|
||||
'verbose_name_plural': 'Homepage Sections',
|
||||
'ordering': ['order'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='HomepageSectionItem',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('icon', models.CharField(blank=True, help_text='Emoji or short symbol (e.g. ⚗️).', max_length=20)),
|
||||
('title', models.CharField(blank=True, max_length=300)),
|
||||
('content', models.TextField(blank=True)),
|
||||
('order', models.PositiveIntegerField(default=0)),
|
||||
('section', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='pages.homepagesection')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Homepage Section Item',
|
||||
'verbose_name_plural': 'Homepage Section Items',
|
||||
'ordering': ['order'],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.0.2 on 2026-05-17 14:59
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pages', '0005_homepage_sections'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='homepagesectionitem',
|
||||
name='image',
|
||||
field=models.ImageField(blank=True, help_text='Logo or image (used for Supporters cards).', null=True, upload_to='homepage/items/'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='homepagesection',
|
||||
name='section_type',
|
||||
field=models.CharField(choices=[('features', 'Features'), ('screenshots', 'Screenshots Gallery'), ('products', 'Products'), ('problems', 'Problems / Value Proposition'), ('about_strip', 'About Strip'), ('supporters', 'Supporters')], max_length=30, unique=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,34 @@
|
||||
# Generated by Django 5.0.2 on 2026-05-20 09:43
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pages', '0006_homepagesectionitem_image_supporters'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='HeroSection',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('badge', models.CharField(blank=True, help_text="Small label above the title (e.g. 'Developing since 2021').", max_length=200)),
|
||||
('title', models.CharField(blank=True, help_text="Main title line (e.g. 'Radiuma,').", max_length=300)),
|
||||
('title_highlight', models.CharField(blank=True, help_text="Second title line shown in gradient colour (e.g. 'A Powerful Workflow Generator').", max_length=300)),
|
||||
('subtitle', models.CharField(blank=True, help_text="Short line below the title (e.g. 'for Standardized Radiomics Analysis…').", max_length=500)),
|
||||
('description', models.TextField(blank=True, help_text='Longer paragraph below the subtitle.')),
|
||||
('primary_cta_text', models.CharField(blank=True, help_text='Primary button label.', max_length=100)),
|
||||
('primary_cta_url', models.CharField(blank=True, help_text='Primary button URL (relative or absolute).', max_length=300)),
|
||||
('secondary_cta_text', models.CharField(blank=True, help_text='Secondary (ghost) button label.', max_length=100)),
|
||||
('secondary_cta_url', models.CharField(blank=True, help_text='Secondary (ghost) button URL.', max_length=300)),
|
||||
('image', models.ImageField(blank=True, help_text='App preview screenshot shown on the right.', null=True, upload_to='hero/')),
|
||||
('image_alt', models.CharField(blank=True, help_text='Alt text for the preview image.', max_length=300)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Hero Section',
|
||||
'verbose_name_plural': 'Hero Section',
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,79 @@
|
||||
# Generated by Django 5.0.2 on 2026-05-25 12:55
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pages', '0007_hero_section'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CustomPage',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.CharField(max_length=200)),
|
||||
('slug', models.SlugField(max_length=200, unique=True)),
|
||||
('menu_label', models.CharField(blank=True, help_text='Nav label when shown in menu. Defaults to title.', max_length=100)),
|
||||
('meta_description', models.CharField(blank=True, max_length=300)),
|
||||
('show_in_nav', models.BooleanField(default=True)),
|
||||
('menu_order', models.PositiveIntegerField(default=0)),
|
||||
('is_published', models.BooleanField(default=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Custom Page',
|
||||
'verbose_name_plural': 'Custom Pages',
|
||||
'ordering': ['menu_order', 'title'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CustomPageSection',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('section_type', models.CharField(choices=[('hero', 'Hero'), ('intro', 'Intro Card'), ('grid', 'Grid Cards'), ('history', 'History Block'), ('custom', 'Custom Content'), ('features', 'Features Grid'), ('screenshots', 'Screenshots Gallery'), ('products', 'Products Grid'), ('problems', 'Problems / Value Proposition'), ('supporters', 'Supporters'), ('about_strip', 'About Strip'), ('faq', 'FAQ Accordion')], default='custom', max_length=30)),
|
||||
('badge', models.CharField(blank=True, max_length=100)),
|
||||
('title', models.CharField(blank=True, max_length=300)),
|
||||
('subtitle', models.CharField(blank=True, max_length=500)),
|
||||
('description', models.TextField(blank=True, help_text='Short intro text (homepage-style sections).')),
|
||||
('content', models.TextField(blank=True)),
|
||||
('content_format', models.CharField(choices=[('plain', 'Plain Text'), ('markdown', 'Markdown'), ('html', 'HTML')], default='markdown', max_length=20)),
|
||||
('link_text', models.CharField(blank=True, max_length=100)),
|
||||
('link_url', models.CharField(blank=True, max_length=300)),
|
||||
('order', models.PositiveIntegerField(default=0)),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sections', to='pages.custompage')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Custom Page Section',
|
||||
'verbose_name_plural': 'Custom Page Sections',
|
||||
'ordering': ['order'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CustomPageSectionItem',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('icon', models.CharField(blank=True, max_length=20)),
|
||||
('badge', models.CharField(blank=True, max_length=100)),
|
||||
('title', models.CharField(blank=True, max_length=300)),
|
||||
('content', models.TextField(blank=True)),
|
||||
('content_format', models.CharField(choices=[('plain', 'Plain Text'), ('markdown', 'Markdown'), ('html', 'HTML')], default='plain', max_length=20)),
|
||||
('url', models.URLField(blank=True)),
|
||||
('image', models.ImageField(blank=True, null=True, upload_to='pages/custom/')),
|
||||
('image_alt', models.CharField(blank=True, max_length=200)),
|
||||
('is_featured', models.BooleanField(default=False)),
|
||||
('order', models.PositiveIntegerField(default=0)),
|
||||
('section', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='pages.custompagesection')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Custom Page Section Item',
|
||||
'verbose_name_plural': 'Custom Page Section Items',
|
||||
'ordering': ['order'],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.0.2 on 2026-05-26 12:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pages', '0008_custom_pages'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='homepagesection',
|
||||
name='section_type',
|
||||
field=models.CharField(choices=[('features', 'Features'), ('screenshots', 'Screenshots Gallery'), ('products', 'Products'), ('problems', 'Problems / Value Proposition'), ('about_strip', 'About Strip'), ('supporters', 'Supporters')], max_length=30),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,33 @@
|
||||
# Generated by Django 5.0.2 on 2026-05-26 12:49
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pages', '0009_alter_homepagesection_section_type'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='homepagesectionitem',
|
||||
name='url',
|
||||
field=models.CharField(blank=True, help_text='Optional link; makes this item clickable.', max_length=300),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='custompagesection',
|
||||
name='section_type',
|
||||
field=models.CharField(choices=[('hero', 'Hero'), ('intro', 'Intro Card'), ('grid', 'Grid Cards'), ('history', 'History Block'), ('custom', 'Custom Content'), ('features', 'Features Grid'), ('screenshots', 'Screenshots Gallery'), ('products', 'Products Grid'), ('products_catalog', 'Products with Sub-products'), ('problems', 'Problems / Value Proposition'), ('supporters', 'Supporters'), ('about_strip', 'About Strip'), ('faq', 'FAQ Accordion')], default='custom', max_length=30),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='custompagesectionitem',
|
||||
name='url',
|
||||
field=models.CharField(blank=True, help_text='Optional link; makes this item clickable.', max_length=300),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='homepagesection',
|
||||
name='section_type',
|
||||
field=models.CharField(choices=[('features', 'Features'), ('screenshots', 'Screenshots Gallery'), ('products', 'Products'), ('products_catalog', 'Products with Sub-products'), ('problems', 'Problems / Value Proposition'), ('about_strip', 'About Strip'), ('supporters', 'Supporters')], max_length=30),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,48 @@
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
def set_custom_page_section_item_page(apps, schema_editor):
|
||||
CustomPageSectionItem = apps.get_model("pages", "CustomPageSectionItem")
|
||||
for item in CustomPageSectionItem.objects.select_related("section").iterator():
|
||||
item.page_id = item.section.page_id
|
||||
item.save(update_fields=["page_id"])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("pages", "0010_homepagesectionitem_url_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="aboutsectionitem",
|
||||
name="url",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
help_text="Optional link; makes this item clickable.",
|
||||
max_length=300,
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="custompagesectionitem",
|
||||
name="page",
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="section_items",
|
||||
to="pages.custompage",
|
||||
),
|
||||
),
|
||||
migrations.RunPython(set_custom_page_section_item_page, migrations.RunPython.noop),
|
||||
migrations.AlterField(
|
||||
model_name="custompagesectionitem",
|
||||
name="page",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="section_items",
|
||||
to="pages.custompage",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("pages", "0011_custompagesectionitem_page_aboutsectionitem_url"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="aboutsectionitem",
|
||||
name="icon",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
help_text="Emoji or short symbol (e.g. ⚗️).",
|
||||
max_length=20,
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,30 @@
|
||||
# Generated by Django 5.0.2 on 2026-06-07 13:23
|
||||
|
||||
import apps.pages.contact_uploads
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pages', '0012_aboutsectionitem_icon'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ContactSubmissionAttachment',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('file', models.FileField(storage=apps.pages.contact_uploads.ContactAttachmentStorage(), upload_to=apps.pages.contact_uploads.contact_attachment_upload_to)),
|
||||
('original_filename', models.CharField(max_length=255)),
|
||||
('uploaded_at', models.DateTimeField(auto_now_add=True)),
|
||||
('submission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attachments', to='pages.contactsubmission')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Contact Attachment',
|
||||
'verbose_name_plural': 'Contact Attachments',
|
||||
'ordering': ['uploaded_at'],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.2.13 on 2026-06-07 13:49
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pages', '0013_contact_submission_attachments'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='aboutsection',
|
||||
name='section_type',
|
||||
field=models.CharField(choices=[('hero', 'Hero'), ('intro', 'Intro Card'), ('grid', 'Grid Cards'), ('history', 'History Block'), ('custom', 'Custom Content'), ('supporters', 'Supporters')], default='custom', max_length=30),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='aboutsectionitem',
|
||||
name='image',
|
||||
field=models.ImageField(blank=True, help_text='Logo or image (used for Supporters cards).', null=True, upload_to='about/items/'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,141 @@
|
||||
# Generated by Django 5.2.13 on 2026-06-08 12:42
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pages', '0014_alter_aboutsection_section_type_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='PageVideo',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('video_source', models.CharField(blank=True, choices=[('youtube', 'YouTube / external link'), ('upload', 'Uploaded file')], default='youtube', max_length=20)),
|
||||
('video_url', models.CharField(blank=True, help_text='YouTube watch, embed, or youtu.be link.', max_length=500)),
|
||||
('video_file', models.FileField(blank=True, help_text='MP4, WebM, OGG, or MOV file.', upload_to='videos/')),
|
||||
('video_poster', models.ImageField(blank=True, help_text='Optional thumbnail shown before an uploaded video plays.', null=True, upload_to='videos/posters/')),
|
||||
('video_size', models.CharField(choices=[('sm', 'Small (480px)'), ('md', 'Medium (720px)'), ('lg', 'Large (960px)'), ('full', 'Full width')], default='md', max_length=10)),
|
||||
('video_aspect_ratio', models.CharField(choices=[('16/9', '16:9 (widescreen)'), ('4/3', '4:3 (standard)'), ('1/1', '1:1 (square)')], default='16/9', max_length=10)),
|
||||
('page', models.CharField(choices=[('contact', 'Contact'), ('faq', 'FAQ')], max_length=20)),
|
||||
('badge', models.CharField(blank=True, max_length=100)),
|
||||
('title', models.CharField(blank=True, max_length=300)),
|
||||
('description', models.TextField(blank=True)),
|
||||
('order', models.PositiveIntegerField(default=0)),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Page Video',
|
||||
'verbose_name_plural': 'Page Videos',
|
||||
'ordering': ['page', 'order'],
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='aboutsection',
|
||||
name='video_aspect_ratio',
|
||||
field=models.CharField(choices=[('16/9', '16:9 (widescreen)'), ('4/3', '4:3 (standard)'), ('1/1', '1:1 (square)')], default='16/9', max_length=10),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='aboutsection',
|
||||
name='video_file',
|
||||
field=models.FileField(blank=True, help_text='MP4, WebM, OGG, or MOV file.', upload_to='videos/'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='aboutsection',
|
||||
name='video_poster',
|
||||
field=models.ImageField(blank=True, help_text='Optional thumbnail shown before an uploaded video plays.', null=True, upload_to='videos/posters/'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='aboutsection',
|
||||
name='video_size',
|
||||
field=models.CharField(choices=[('sm', 'Small (480px)'), ('md', 'Medium (720px)'), ('lg', 'Large (960px)'), ('full', 'Full width')], default='md', max_length=10),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='aboutsection',
|
||||
name='video_source',
|
||||
field=models.CharField(blank=True, choices=[('youtube', 'YouTube / external link'), ('upload', 'Uploaded file')], default='youtube', max_length=20),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='aboutsection',
|
||||
name='video_url',
|
||||
field=models.CharField(blank=True, help_text='YouTube watch, embed, or youtu.be link.', max_length=500),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='custompagesection',
|
||||
name='video_aspect_ratio',
|
||||
field=models.CharField(choices=[('16/9', '16:9 (widescreen)'), ('4/3', '4:3 (standard)'), ('1/1', '1:1 (square)')], default='16/9', max_length=10),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='custompagesection',
|
||||
name='video_file',
|
||||
field=models.FileField(blank=True, help_text='MP4, WebM, OGG, or MOV file.', upload_to='videos/'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='custompagesection',
|
||||
name='video_poster',
|
||||
field=models.ImageField(blank=True, help_text='Optional thumbnail shown before an uploaded video plays.', null=True, upload_to='videos/posters/'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='custompagesection',
|
||||
name='video_size',
|
||||
field=models.CharField(choices=[('sm', 'Small (480px)'), ('md', 'Medium (720px)'), ('lg', 'Large (960px)'), ('full', 'Full width')], default='md', max_length=10),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='custompagesection',
|
||||
name='video_source',
|
||||
field=models.CharField(blank=True, choices=[('youtube', 'YouTube / external link'), ('upload', 'Uploaded file')], default='youtube', max_length=20),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='custompagesection',
|
||||
name='video_url',
|
||||
field=models.CharField(blank=True, help_text='YouTube watch, embed, or youtu.be link.', max_length=500),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepagesection',
|
||||
name='video_aspect_ratio',
|
||||
field=models.CharField(choices=[('16/9', '16:9 (widescreen)'), ('4/3', '4:3 (standard)'), ('1/1', '1:1 (square)')], default='16/9', max_length=10),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepagesection',
|
||||
name='video_file',
|
||||
field=models.FileField(blank=True, help_text='MP4, WebM, OGG, or MOV file.', upload_to='videos/'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepagesection',
|
||||
name='video_poster',
|
||||
field=models.ImageField(blank=True, help_text='Optional thumbnail shown before an uploaded video plays.', null=True, upload_to='videos/posters/'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepagesection',
|
||||
name='video_size',
|
||||
field=models.CharField(choices=[('sm', 'Small (480px)'), ('md', 'Medium (720px)'), ('lg', 'Large (960px)'), ('full', 'Full width')], default='md', max_length=10),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepagesection',
|
||||
name='video_source',
|
||||
field=models.CharField(blank=True, choices=[('youtube', 'YouTube / external link'), ('upload', 'Uploaded file')], default='youtube', max_length=20),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepagesection',
|
||||
name='video_url',
|
||||
field=models.CharField(blank=True, help_text='YouTube watch, embed, or youtu.be link.', max_length=500),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='aboutsection',
|
||||
name='section_type',
|
||||
field=models.CharField(choices=[('hero', 'Hero'), ('intro', 'Intro Card'), ('grid', 'Grid Cards'), ('history', 'History Block'), ('custom', 'Custom Content'), ('supporters', 'Supporters'), ('video', 'Video')], default='custom', max_length=30),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='custompagesection',
|
||||
name='section_type',
|
||||
field=models.CharField(choices=[('hero', 'Hero'), ('intro', 'Intro Card'), ('grid', 'Grid Cards'), ('history', 'History Block'), ('custom', 'Custom Content'), ('features', 'Features Grid'), ('screenshots', 'Screenshots Gallery'), ('products', 'Products Grid'), ('products_catalog', 'Products with Sub-products'), ('problems', 'Problems / Value Proposition'), ('supporters', 'Supporters'), ('about_strip', 'About Strip'), ('faq', 'FAQ Accordion'), ('video', 'Video')], default='custom', max_length=30),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='homepagesection',
|
||||
name='section_type',
|
||||
field=models.CharField(choices=[('features', 'Features'), ('screenshots', 'Screenshots Gallery'), ('products', 'Products'), ('products_catalog', 'Products with Sub-products'), ('problems', 'Problems / Value Proposition'), ('about_strip', 'About Strip'), ('supporters', 'Supporters'), ('video', 'Video')], max_length=30),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,33 @@
|
||||
# Generated by Django 5.2.13 on 2026-06-08 13:02
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pages', '0015_video_support'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='aboutsection',
|
||||
name='video_styled_background',
|
||||
field=models.BooleanField(default=False, help_text='Glass panel with ambient glow (similar to the Downloads section).'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='custompagesection',
|
||||
name='video_styled_background',
|
||||
field=models.BooleanField(default=False, help_text='Glass panel with ambient glow (similar to the Downloads section).'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepagesection',
|
||||
name='video_styled_background',
|
||||
field=models.BooleanField(default=False, help_text='Glass panel with ambient glow (similar to the Downloads section).'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='pagevideo',
|
||||
name='video_styled_background',
|
||||
field=models.BooleanField(default=False, help_text='Glass panel with ambient glow (similar to the Downloads section).'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,33 @@
|
||||
# Generated by Django 5.2.13 on 2026-06-08 13:14
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pages', '0016_video_styled_background'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='aboutsection',
|
||||
name='description_format',
|
||||
field=models.CharField(choices=[('plain', 'Plain Text'), ('markdown', 'Markdown'), ('html', 'HTML')], default='plain', max_length=20),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='custompagesection',
|
||||
name='description_format',
|
||||
field=models.CharField(choices=[('plain', 'Plain Text'), ('markdown', 'Markdown'), ('html', 'HTML')], default='plain', max_length=20),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepagesection',
|
||||
name='description_format',
|
||||
field=models.CharField(choices=[('plain', 'Plain Text'), ('markdown', 'Markdown'), ('html', 'HTML')], default='plain', max_length=20),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='pagevideo',
|
||||
name='description_format',
|
||||
field=models.CharField(choices=[('plain', 'Plain Text'), ('markdown', 'Markdown'), ('html', 'HTML')], default='plain', max_length=20),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,48 @@
|
||||
# Generated by Django 5.2.15 on 2026-06-20 23:06
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pages', '0017_video_description_format'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='homepagesection',
|
||||
name='title_highlight',
|
||||
field=models.CharField(blank=True, help_text="Second title line shown in accent colour (e.g. 'Outstanding Projects').", max_length=300),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepagesectionitem',
|
||||
name='image_alt',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepagesectionitem',
|
||||
name='project_status',
|
||||
field=models.CharField(blank=True, choices=[('', '—'), ('new', 'New'), ('ongoing', 'Ongoing'), ('done', 'Done')], help_text='Project filter category (Projects Showcase section).', max_length=10),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepagesectionitem',
|
||||
name='tags',
|
||||
field=models.CharField(blank=True, help_text='Comma-separated tags shown on project cards (e.g. Web Development, Publication).', max_length=300),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='herosection',
|
||||
name='title',
|
||||
field=models.CharField(blank=True, help_text="Main title line (e.g. 'Advanced Solutions').", max_length=300),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='homepagesection',
|
||||
name='section_type',
|
||||
field=models.CharField(choices=[('features', 'Features'), ('screenshots', 'Screenshots Gallery'), ('products', 'Products'), ('products_catalog', 'Products with Sub-products'), ('problems', 'Problems / Value Proposition'), ('projects', 'Projects Showcase'), ('experience', 'Experience / Benefits'), ('about_strip', 'About Strip'), ('supporters', 'Supporters'), ('video', 'Video')], max_length=30),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='homepagesectionitem',
|
||||
name='image',
|
||||
field=models.ImageField(blank=True, help_text='Card image or icon.', null=True, upload_to='homepage/items/'),
|
||||
),
|
||||
]
|
||||
Reference in New Issue
Block a user