diff --git a/contracts/admin.py b/contracts/admin.py
index 1eb707c2867e341a0bb44c6f9b8e6607d989a431..64cc7eb142d381d6705c2111e9da99655316eaae 100644
--- a/contracts/admin.py
+++ b/contracts/admin.py
@@ -2,12 +2,13 @@ from django.contrib import admin
 
 from shared.admin import MarkdownxGuardedModelAdmin
 
-from .forms import ContractAdminForm
+from .forms import ContractAdminForm, SigneeAdminForm
 from .models import (
     Contract,
     Contractee,
     ContracteeRepresentative,
     ContracteeSignature,
+    ContractFile,
     ContractFilingArea,
     ContractIntent,
     ContractIssue,
@@ -23,13 +24,31 @@ class IndexHiddenModelAdmin(MarkdownxGuardedModelAdmin):
         return False
 
 
+# BEGIN Contracts
+
+
+class ContractFileInline(admin.TabularInline):
+    model = ContractFile
+    extra = 0
+
+
+class ContractIntentInline(admin.TabularInline):
+    model = ContractIntent
+    extra = 0
+
+
+class ContractIssueInline(admin.TabularInline):
+    model = Contract.issues.through
+    extra = 0
+
+
 class ContractAdmin(MarkdownxGuardedModelAdmin):
     form = ContractAdminForm
 
     fields = (
         "type",
         "subtype",
-        "signee_signature",
+        "signee_signatures",
         "contractee_signatures",
         "valid_start_date",
         "valid_end_date",
@@ -39,11 +58,8 @@ class ContractAdmin(MarkdownxGuardedModelAdmin):
         "publishing_rejection_comment",
         "tender_url",
         "identifier",
-        "issues",
         "notes",
         "summary",
-        "anonymized_contract_file",
-        "original_contract_file",
         "primary_contract",
         "expected_cost_total",
         "expected_cost_year",
@@ -53,23 +69,62 @@ class ContractAdmin(MarkdownxGuardedModelAdmin):
         "filing_area",
     )
 
+    inlines = (
+        ContractFileInline,
+        ContractIntentInline,
+        ContractIssueInline,
+    )
+
+
+# END Contracts
+
+# BEGIN Signing parties
+
+
+class SigneeRepresentativeInline(admin.TabularInline):
+    model = SigneeRepresentative
+    extra = 0
+
+
+class SigneeAdmin(MarkdownxGuardedModelAdmin):
+    form = SigneeAdminForm
+
+    inlines = (
+        SigneeRepresentativeInline,
+    )
+
+
+class ContracteeRepresentativeInline(admin.TabularInline):
+    model = ContracteeRepresentative
+    extra = 0
+
+
+class ContracteeAdmin(MarkdownxGuardedModelAdmin):
+    inlines = (
+        ContracteeRepresentativeInline,
+    )
+
+
+# END Signing parties
+
 
 for model in (
     SigneeRepresentative,
-    SigneeSignature,
     ContracteeRepresentative,
-    ContracteeSignature,
     ContractSubtype,
     ContractIntent,
 ):
     admin.site.register(model, IndexHiddenModelAdmin)
 
 for model in (
-    Signee,
-    Contractee,
+    SigneeSignature,
+    ContracteeSignature,
     ContractIssue,
     ContractFilingArea,
 ):
     admin.site.register(model, MarkdownxGuardedModelAdmin)
 
+admin.site.register(Signee, SigneeAdmin)
+admin.site.register(Contractee, ContracteeAdmin)
+
 admin.site.register(Contract, ContractAdmin)
diff --git a/contracts/forms.py b/contracts/forms.py
index f5d1c5aba5672f7faecf17f1d0e4bf5cb6f6b449..f6c1dc01e57493ddf61c1fd9510889ac6a2f3e8e 100644
--- a/contracts/forms.py
+++ b/contracts/forms.py
@@ -9,3 +9,12 @@ class ContractAdminForm(forms.ModelForm):
             "shared/shared.js",
             "shared/admin_contract_form.js",
         )
+
+
+class SigneeAdminForm(forms.ModelForm):
+    class Media:
+        js = (
+            "shared/runtime.js",
+            "shared/shared.js",
+            "shared/admin_signee_form.js",
+        )
diff --git a/contracts/migrations/0001_initial.py b/contracts/migrations/0001_initial.py
index fb189ca67c8f7d6faa7cbf673deb88847835635f..466d34d134c7ace29d0b426660db2de08b0323b5 100644
--- a/contracts/migrations/0001_initial.py
+++ b/contracts/migrations/0001_initial.py
@@ -1,10 +1,11 @@
-# Generated by Django 4.1.4 on 2023-02-15 14:24
+# Generated by Django 4.1.4 on 2023-02-15 17:12
 
 from django.conf import settings
 from django.db import migrations, models
 import django.db.models.deletion
 import django_countries.fields
 import markdownx.models
+import shared.models
 
 
 class Migration(migrations.Migration):
@@ -55,7 +56,7 @@ class Migration(migrations.Migration):
                 ('address_country', django_countries.fields.CountryField(default='CZ', max_length=2, verbose_name='Země')),
                 ('ico_number', models.CharField(blank=True, default='71339698', max_length=16, null=True, verbose_name='IČO')),
                 ('department', models.CharField(blank=True, max_length=128, null=True, verbose_name='Organizační složka')),
-                ('color', models.CharField(max_length=6, verbose_name='Barva')),
+                ('color', models.CharField(blank=True, max_length=6, null=True, verbose_name='Barva')),
             ],
             options={
                 'verbose_name': 'Naše smluvní strana',
@@ -73,6 +74,7 @@ class Migration(migrations.Migration):
                 'verbose_name': 'Spisovna',
                 'verbose_name_plural': 'Spisovny',
             },
+            bases=(shared.models.NameStrMixin, models.Model),
         ),
         migrations.CreateModel(
             name='ContractIssue',
@@ -84,6 +86,7 @@ class Migration(migrations.Migration):
                 'verbose_name': 'Problém se smlouvou',
                 'verbose_name_plural': 'Problémy se smlouvami',
             },
+            bases=(shared.models.NameStrMixin, models.Model),
         ),
         migrations.CreateModel(
             name='ContractSubtype',
@@ -95,6 +98,7 @@ class Migration(migrations.Migration):
                 'verbose_name': 'Podtyp smlouvy',
                 'verbose_name_plural': 'Podtypy smlouvy',
             },
+            bases=(shared.models.NameStrMixin, models.Model),
         ),
         migrations.CreateModel(
             name='Signee',
@@ -109,10 +113,11 @@ class Migration(migrations.Migration):
                 ('ico_number', models.CharField(blank=True, max_length=16, null=True, verbose_name='IČO')),
                 ('date_of_birth', models.DateField(blank=True, null=True, verbose_name='Datum narození')),
                 ('department', models.CharField(blank=True, max_length=128, null=True, verbose_name='Organizační složka')),
+                ('color', models.CharField(blank=True, max_length=6, null=True, verbose_name='Barva')),
             ],
             options={
-                'verbose_name': 'Druhá smluvní strana',
-                'verbose_name_plural': 'Druhé smluvní strany',
+                'verbose_name': 'Jiná smluvní strana',
+                'verbose_name_plural': 'Ostatní smluvní strany',
             },
         ),
         migrations.CreateModel(
@@ -123,8 +128,8 @@ class Migration(migrations.Migration):
                 ('signee', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='signatures', to='contracts.signee', verbose_name='Smluvní strana')),
             ],
             options={
-                'verbose_name': 'Podpis druhé smluvní strany',
-                'verbose_name_plural': 'Podpisy druhé smluvní strany',
+                'verbose_name': 'Podpis jiné smluvní strany',
+                'verbose_name_plural': 'Podpisy ostatních smluvních stran',
             },
         ),
         migrations.CreateModel(
@@ -132,12 +137,13 @@ class Migration(migrations.Migration):
             fields=[
                 ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                 ('name', models.CharField(max_length=256, verbose_name='Jméno')),
-                ('role', models.CharField(max_length=256, verbose_name='Funkce')),
+                ('function', models.CharField(blank=True, max_length=256, null=True, verbose_name='Funkce')),
+                ('role', models.CharField(blank=True, max_length=256, null=True, verbose_name='Role')),
                 ('signee', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='representatives', to='contracts.signee', verbose_name='Smluvní strana')),
             ],
             options={
-                'verbose_name': 'Zástupce druhé smluvní strany',
-                'verbose_name_plural': 'Zástupci druhé smluvní strany',
+                'verbose_name': 'Zástupce',
+                'verbose_name_plural': 'Zástupci',
             },
         ),
         migrations.CreateModel(
@@ -165,6 +171,7 @@ class Migration(migrations.Migration):
                 'verbose_name': 'Soubor',
                 'verbose_name_plural': 'Soubory',
             },
+            bases=(shared.models.NameStrMixin, models.Model),
         ),
         migrations.CreateModel(
             name='ContracteeSignature',
@@ -175,7 +182,7 @@ class Migration(migrations.Migration):
             ],
             options={
                 'verbose_name': 'Podpis naší smluvní strany',
-                'verbose_name_plural': 'Podpisy naší smluvní strany',
+                'verbose_name_plural': 'Podpisy našich smluvních stran',
             },
         ),
         migrations.CreateModel(
@@ -183,18 +190,19 @@ class Migration(migrations.Migration):
             fields=[
                 ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                 ('name', models.CharField(max_length=256, verbose_name='Jméno')),
-                ('role', models.CharField(max_length=256, verbose_name='Funkce')),
+                ('function', models.CharField(blank=True, max_length=256, null=True, verbose_name='Funkce')),
+                ('role', models.CharField(blank=True, max_length=256, null=True, verbose_name='Role')),
                 ('contractee', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='representatives', to='contracts.contractee', verbose_name='Smluvní strana')),
             ],
             options={
-                'verbose_name': 'Zástupce naší smluvní strany',
-                'verbose_name_plural': 'Zástupci naší smluvní strany',
+                'verbose_name': 'Zástupce',
+                'verbose_name_plural': 'Zástupci',
             },
         ),
         migrations.AddField(
             model_name='contract',
             name='contractee_signatures',
-            field=models.ManyToManyField(to='contracts.contracteesignature', verbose_name='Naše podpisy'),
+            field=models.ManyToManyField(to='contracts.contracteesignature', verbose_name='Podpisy našich smluvních stran'),
         ),
         migrations.AddField(
             model_name='contract',
@@ -218,8 +226,8 @@ class Migration(migrations.Migration):
         ),
         migrations.AddField(
             model_name='contract',
-            name='signee_signature',
-            field=models.ManyToManyField(to='contracts.signeesignature', verbose_name='Podpisy druhé smluvní strany'),
+            name='signee_signatures',
+            field=models.ManyToManyField(to='contracts.signeesignature', verbose_name='Podpisy ostatních smluvních stran'),
         ),
         migrations.AddField(
             model_name='contract',
diff --git a/contracts/migrations/0002_alter_contract_all_parties_sign_date_and_more.py b/contracts/migrations/0002_alter_contract_all_parties_sign_date_and_more.py
new file mode 100644
index 0000000000000000000000000000000000000000..463b58e98d3b4b3b7f94c6c48a609cbff7549eaf
--- /dev/null
+++ b/contracts/migrations/0002_alter_contract_all_parties_sign_date_and_more.py
@@ -0,0 +1,29 @@
+# Generated by Django 4.1.4 on 2023-02-15 17:19
+
+from django.db import migrations, models
+import markdownx.models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('contracts', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='contract',
+            name='all_parties_sign_date',
+            field=models.DateField(blank=True, null=True, verbose_name='Datum podpisu všech stran'),
+        ),
+        migrations.AlterField(
+            model_name='contract',
+            name='notes',
+            field=markdownx.models.MarkdownxField(blank=True, help_text='Poznámky jsou viditelné pro všechny, kteří mohou smlouvu spravovat.', null=True, verbose_name='Poznámky'),
+        ),
+        migrations.AlterField(
+            model_name='contract',
+            name='summary',
+            field=markdownx.models.MarkdownxField(blank=True, help_text='Obsah není veřejně přístupný.', null=True, verbose_name='Rekapitulace'),
+        ),
+    ]
diff --git a/contracts/migrations/0003_alter_contract_public_status_set_by.py b/contracts/migrations/0003_alter_contract_public_status_set_by.py
new file mode 100644
index 0000000000000000000000000000000000000000..b662563116ef5fb2d2c0e87b10a24d9e9c25ac9a
--- /dev/null
+++ b/contracts/migrations/0003_alter_contract_public_status_set_by.py
@@ -0,0 +1,21 @@
+# Generated by Django 4.1.4 on 2023-02-15 17:21
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('contracts', '0002_alter_contract_all_parties_sign_date_and_more'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='contract',
+            name='public_status_set_by',
+            field=models.ForeignKey(blank=True, help_text='Obsah není veřejně přístupný.', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='public_status_altered_contracts', to=settings.AUTH_USER_MODEL, verbose_name='Zveřejněno / nezveřejněno uživatelem'),
+        ),
+    ]
diff --git a/contracts/models.py b/contracts/models.py
index 10bcbdec50e12ac61452e6e4f80ad1cd9ce66335..49ab18d1ad506811b27da707f3298a4ad20bbfbe 100644
--- a/contracts/models.py
+++ b/contracts/models.py
@@ -4,6 +4,7 @@ from django_countries.fields import CountryField
 from markdownx.models import MarkdownxField
 
 from users.models import User
+from shared.models import NameStrMixin
 
 
 class Signee(models.Model):
@@ -58,9 +59,30 @@ class Signee(models.Model):
         verbose_name="Organizační složka",
     )
 
+    color = models.CharField(
+        max_length=6,  # e.g. "ffffff"
+        blank=True,
+        null=True,
+        verbose_name="Barva",
+    )
+
     class Meta:
-        verbose_name = "Druhá smluvní strana"
-        verbose_name_plural = "Druhé smluvní strany"
+        verbose_name = "Jiná smluvní strana"
+        verbose_name_plural = "Ostatní smluvní strany"
+
+    def __str__(self) -> str:
+        result = self.name
+
+        if self.ico_number is not None:
+            result += f" ({self.ico_number})"
+
+        if self.date_of_birth is not None:
+            result += f" ({self.date_of_birth})"
+
+        if self.department is not None:
+            result += f", {self.department}"
+
+        return result
 
 
 class SigneeRepresentative(models.Model):
@@ -76,14 +98,34 @@ class SigneeRepresentative(models.Model):
         verbose_name="Jméno",
     )
 
-    role = models.CharField(
+    function = models.CharField(
         max_length=256,
+        blank=True,
+        null=True,
         verbose_name="Funkce",
     )
 
+    role = models.CharField(
+        max_length=256,
+        blank=True,
+        null=True,
+        verbose_name="Role",
+    )
+
     class Meta:
-        verbose_name = "Zástupce druhé smluvní strany"
-        verbose_name_plural = "Zástupci druhé smluvní strany"
+        verbose_name = "Zástupce"
+        verbose_name_plural = "Zástupci"
+
+    def __str__(self) -> str:
+        result = self.name
+
+        if self.function is not None:
+            result += f", {self.function}"
+
+        if self.role is not None:
+            result += f" ({self.role})"
+
+        return result
 
 
 class SigneeSignature(models.Model):
@@ -99,8 +141,11 @@ class SigneeSignature(models.Model):
     )
 
     class Meta:
-        verbose_name = "Podpis druhé smluvní strany"
-        verbose_name_plural = "Podpisy druhé smluvní strany"
+        verbose_name = "Podpis jiné smluvní strany"
+        verbose_name_plural = "Podpisy ostatních smluvních stran"
+
+    def __str__(self) -> str:
+        return f"{self.signee.name}, {self.date}"
 
 
 class Contractee(models.Model):
@@ -151,6 +196,8 @@ class Contractee(models.Model):
     # TODO: Input validation
     color = models.CharField(
         max_length=6,  # e.g. "ffffff"
+        blank=True,
+        null=True,
         verbose_name="Barva",
     )
 
@@ -158,6 +205,14 @@ class Contractee(models.Model):
         verbose_name = "Naše smluvní strana"
         verbose_name_plural = "Naše smluvní strany"
 
+    def __str__(self) -> str:
+        result = self.name
+
+        if self.department is not None:
+            result += f", {self.department}"
+
+        return result
+
 
 class ContracteeRepresentative(models.Model):
     contractee = models.ForeignKey(
@@ -172,14 +227,35 @@ class ContracteeRepresentative(models.Model):
         verbose_name="Jméno",
     )
 
-    role = models.CharField(
+    function = models.CharField(
         max_length=256,
+        blank=True,
+        null=True,
         verbose_name="Funkce",
     )
 
+    role = models.CharField(
+        max_length=256,
+        blank=True,
+        null=True,
+        verbose_name="Role",
+    )
+
     class Meta:
-        verbose_name = "Zástupce naší smluvní strany"
-        verbose_name_plural = "Zástupci naší smluvní strany"
+        verbose_name = "Zástupce"
+        verbose_name_plural = "Zástupci"
+
+    # FIXME: Violates DRY, make a mixin
+    def __str__(self) -> str:
+        result = self.name
+
+        if self.function is not None:
+            result += f", {self.function}"
+
+        if self.role is not None:
+            result += f" ({self.role})"
+
+        return result
 
 
 class ContracteeSignature(models.Model):
@@ -196,10 +272,13 @@ class ContracteeSignature(models.Model):
 
     class Meta:
         verbose_name = "Podpis naší smluvní strany"
-        verbose_name_plural = "Podpisy naší smluvní strany"
+        verbose_name_plural = "Podpisy našich smluvních stran"
+
+    def __str__(self) -> str:
+        return f"{self.contractee.name}, {self.date}"
 
 
-class ContractSubtype(models.Model):
+class ContractSubtype(NameStrMixin, models.Model):
     name = models.CharField(
         max_length=32,
         verbose_name="Jméno",
@@ -210,7 +289,7 @@ class ContractSubtype(models.Model):
         verbose_name_plural = "Podtypy smlouvy"
 
 
-class ContractIssue(models.Model):
+class ContractIssue(NameStrMixin, models.Model):
     name = models.CharField(
         max_length=32,
         verbose_name="Jméno",
@@ -221,7 +300,7 @@ class ContractIssue(models.Model):
         verbose_name_plural = "Problémy se smlouvami"
 
 
-class ContractFilingArea(models.Model):
+class ContractFilingArea(NameStrMixin, models.Model):
     name = models.CharField(
         max_length=32,
         verbose_name="Jméno",
@@ -260,18 +339,20 @@ class Contract(models.Model):
         verbose_name="Obsahuje NDA",
     )
 
-    signee_signature = models.ManyToManyField(
+    signee_signatures = models.ManyToManyField(
         SigneeSignature,
-        verbose_name="Podpisy druhé smluvní strany",
+        verbose_name="Podpisy ostatních smluvních stran",
     )
 
     contractee_signatures = models.ManyToManyField(
         ContracteeSignature,
-        verbose_name="Naše podpisy",
+        verbose_name="Podpisy našich smluvních stran",
     )
 
     all_parties_sign_date = models.DateField(
         verbose_name="Datum podpisu všech stran",
+        blank=True,
+        null=True,
     )  # WARNING: Exclude in admin, autofill
 
     valid_start_date = models.DateField(
@@ -327,6 +408,8 @@ class Contract(models.Model):
     public_status_set_by = models.ForeignKey(
         User,
         on_delete=models.CASCADE,
+        blank=True,
+        null=True,
         related_name="public_status_altered_contracts",
         verbose_name="Zveřejněno / nezveřejněno uživatelem",
         help_text="Obsah není veřejně přístupný.",
@@ -359,12 +442,11 @@ class Contract(models.Model):
     notes = MarkdownxField(
         blank=True,
         null=True,
-        verbose_name="Obsah",
+        verbose_name="Poznámky",
         help_text="Poznámky jsou viditelné pro všechny, kteří mohou smlouvu spravovat.",
     )
 
-    summary = models.CharField(
-        max_length=65536,
+    summary = MarkdownxField(
         blank=True,
         null=True,
         verbose_name="Rekapitulace",
@@ -409,8 +491,11 @@ class Contract(models.Model):
         verbose_name = "Smlouva"
         verbose_name_plural = "Smlouvy"
 
+    def __str__(self) -> str:
+        return self.identifier
+
 
-class ContractFile(models.Model):
+class ContractFile(NameStrMixin, models.Model):
     name = models.CharField(
         max_length=128,
         blank=True,
@@ -457,3 +542,6 @@ class ContractIntent(models.Model):
     class Meta:
         verbose_name = "Záměr"
         verbose_name_plural = "Záměry"
+
+    def __str__(self) -> str:
+        return self.url
diff --git a/shared/models.py b/shared/models.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ee10b8b8e3b8e01efdbdf4e251b94b37c35863a2 100644
--- a/shared/models.py
+++ b/shared/models.py
@@ -0,0 +1,5 @@
+class NameStrMixin:
+    name = ""
+
+    def __str__(self) -> str:
+        return self.name
diff --git a/static_src/admin/signee_form.js b/static_src/admin/signee_form.js
new file mode 100644
index 0000000000000000000000000000000000000000..d03c7b527efc43d7b3e8a57826295de882e2c907
--- /dev/null
+++ b/static_src/admin/signee_form.js
@@ -0,0 +1,28 @@
+import $ from "jquery";
+
+$(window).ready(
+    () => {
+        $(".field-date_of_birth").
+        css(
+            "display",
+            (
+                ($("#id_is_legal_entity").is(":checked")) ?
+                "none": "block"
+            )
+        );
+
+        $("#id_is_legal_entity").on(
+            "change",
+            event => {
+                $(".field-date_of_birth").
+                css(
+                    "display",
+                    (
+                        (event.target.checked) ?
+                        "none" : "block"
+                    )
+                );
+            }
+        );
+    }
+);
diff --git a/webpack.config.js b/webpack.config.js
index 579381ee0904acfb069aebc042f5fe9d47d32d9c..ed6269a0038bbebde84fda4b50c1f3c26b47da46 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -13,6 +13,10 @@ module.exports = {
       import: path.resolve("static_src", "admin", "contract_form.js"),
       dependOn: "shared",
     },
+    admin_signee_form: {
+      import: path.resolve("static_src", "admin", "signee_form.js"),
+      dependOn: "shared",
+    },
     shared: ["jquery"],
   },
   output: {