add transcript support

it could be possible to load closed captions and subtitles from the transcript div via javascript, but I hate javascript so perhaps some other time.
This commit is contained in:
edshot99 2024-11-10 13:58:15 -06:00
parent 9ee8f13d5f
commit 4928747b83
25 changed files with 173 additions and 19 deletions

View File

@ -170,6 +170,7 @@ class PostsController < ApplicationController
source old_source source old_source
title old_title title old_title
description old_description description old_description
transcript old_transcript
rating old_rating rating old_rating
edit_reason edit_reason
] ]

View File

@ -72,7 +72,7 @@ class UploadsController < ApplicationController
def upload_params def upload_params
permitted_params = %i[ permitted_params = %i[
file direct_url source tag_string rating parent_id title description description as_pending file direct_url source tag_string rating parent_id title description description transcript as_pending
] ]
permitted_params << :locked_tags if CurrentUser.is_admin? permitted_params << :locked_tags if CurrentUser.is_admin?

View File

@ -63,6 +63,7 @@ module PostIndex
source: { type: "keyword" }, source: { type: "keyword" },
title: { type: "text" }, title: { type: "text" },
description: { type: "text" }, description: { type: "text" },
transcript: { type: "text" },
notes: { type: "text" }, notes: { type: "text" },
del_reason: { type: "keyword" }, del_reason: { type: "keyword" },
@ -276,6 +277,7 @@ module PostIndex
source: source_array, source: source_array,
title: title.present? ? title : nil, title: title.present? ? title : nil,
description: description.present? ? description : nil, description: description.present? ? description : nil,
transcript: transcript.present? ? transcript : nil,
rating_locked: is_rating_locked, rating_locked: is_rating_locked,
note_locked: is_note_locked, note_locked: is_note_locked,

View File

@ -21,10 +21,12 @@ module PostVersionIndex
source: { type: "keyword" }, source: { type: "keyword" },
title: { type: "text" }, title: { type: "text" },
description: { type: "text" }, description: { type: "text" },
transcript: { type: "text" },
reason: { type: "text" }, reason: { type: "text" },
title_changed: { type: "boolean" }, title_changed: { type: "boolean" },
description_changed: { type: "boolean" }, description_changed: { type: "boolean" },
transcript_changed: { type: "boolean" },
parent_id_changed: { type: "boolean" }, parent_id_changed: { type: "boolean" },
source_changed: { type: "boolean" }, source_changed: { type: "boolean" },
rating_changed: { type: "boolean" }, rating_changed: { type: "boolean" },
@ -84,10 +86,12 @@ module PostVersionIndex
source: source, source: source,
title: title, title: title,
description: description, description: description,
transcript: transcript,
reason: reason, reason: reason,
title_changed: title_changed, title_changed: title_changed,
description_changed: description_changed, description_changed: description_changed,
transcript_changed: transcript_changed,
parent_id_changed: parent_changed, parent_id_changed: parent_changed,
source_changed: source_changed, source_changed: source_changed,
rating_changed: rating_changed, rating_changed: rating_changed,

View File

@ -165,6 +165,14 @@
<%= ApplicationController.new.render_to_string(partial: "dtext_input", locals: { limit: Danbooru.config.post_descr_max_size, textarea: '<textarea class="dtext-formatter-input tag-textarea dtext" id="post_description" rows="10" v-model="description"></textarea>'.html_safe, allow_color: true }) %> <%= ApplicationController.new.render_to_string(partial: "dtext_input", locals: { limit: Danbooru.config.post_descr_max_size, textarea: '<textarea class="dtext-formatter-input tag-textarea dtext" id="post_description" rows="10" v-model="description"></textarea>'.html_safe, allow_color: true }) %>
</div> </div>
</div> </div>
<div class="flex-grid border-bottom">
<div class="col">
<label class="section-label" for="post_transcript">Transcript</label>
</div>
<div class="col2">
<textarea spellcheck="true" class="tag-textarea" v-model="transcript" id="post_transcript"></textarea>
</div>
</div>
<div v-if="allowUploadAsPending" class="flex-grid border-bottom"> <div v-if="allowUploadAsPending" class="flex-grid border-bottom">
<div class="col"> <div class="col">
<label class="section-label">Upload as Pending</label> <label class="section-label">Upload as Pending</label>
@ -331,6 +339,7 @@
parentID: '', parentID: '',
title: '', title: '',
description: '', description: '',
transcript: '',
rating: '', rating: '',
error: '', error: '',
duplicateId: 0, duplicateId: 0,
@ -387,6 +396,7 @@
fillField('parentID', 'parent'); fillField('parentID', 'parent');
fillField('title', 'title'); fillField('title', 'title');
fillField('description', 'description'); fillField('description', 'description');
fillField('transcript', 'transcript');
fillTags(); fillTags();
fillRating(); fillRating();
if(params.has('sources')) { if(params.has('sources')) {
@ -421,6 +431,7 @@
data.append('upload[source]', this.sources.join('\n')); data.append('upload[source]', this.sources.join('\n'));
data.append('upload[title]', this.title); data.append('upload[title]', this.title);
data.append('upload[description]', this.description); data.append('upload[description]', this.description);
data.append('upload[transcript]', this.transcript);
data.append('upload[parent_id]', this.parentID); data.append('upload[parent_id]', this.parentID);
if (this.allowLockedTags) if (this.allowLockedTags)
data.append('upload[locked_tags]', this.lockedTags); data.append('upload[locked_tags]', this.lockedTags);

View File

@ -128,14 +128,25 @@ div#c-post-versions {
@include grid-border(right); @include grid-border(right);
} }
.pv-transcript-label {
grid-row: 1;
@include grid-col(9, 10);
}
.pv-transcript {
grid-row: 2;
@include grid-col(9, 10);
@include grid-border(right);
}
.pv-tags-locked-label { .pv-tags-locked-label {
grid-row: 1; grid-row: 1;
@include grid-col(9, 13); @include grid-col(10, 13);
} }
.pv-tags-locked { .pv-tags-locked {
grid-row: 2; grid-row: 2;
@include grid-col(9, 13); @include grid-col(10, 13);
@include grid-border(right); @include grid-border(right);
} }

View File

@ -110,6 +110,7 @@ class ElasticPostQueryBuilder < ElasticQueryBuilder
add_array_relation(:delreason, :del_reason, action: :wildcard) add_array_relation(:delreason, :del_reason, action: :wildcard)
add_array_relation(:title, :title, action: :match_phrase_prefix) add_array_relation(:title, :title, action: :match_phrase_prefix)
add_array_relation(:description, :description, action: :match_phrase_prefix) add_array_relation(:description, :description, action: :match_phrase_prefix)
add_array_relation(:transcript, :transcript, action: :match_phrase_prefix)
add_array_relation(:note, :notes, action: :match_phrase_prefix) add_array_relation(:note, :notes, action: :match_phrase_prefix)
add_array_relation(:sources, :source, any_none_key: :source, action: :wildcard) add_array_relation(:sources, :source, any_none_key: :source, action: :wildcard)
add_array_relation(:deleter, :deleter) add_array_relation(:deleter, :deleter)
@ -158,6 +159,10 @@ class ElasticPostQueryBuilder < ElasticQueryBuilder
(q[:hasdescription] ? must : must_not).push({exists: {field: :description}}) (q[:hasdescription] ? must : must_not).push({exists: {field: :description}})
end end
if q.include?(:hastranscript)
(q[:hastranscript] ? must : must_not).push({exists: {field: :transcript}})
end
if q.include?(:ischild) if q.include?(:ischild)
(q[:ischild] ? must : must_not).push({exists: {field: :parent}}) (q[:ischild] ? must : must_not).push({exists: {field: :parent}})
end end

View File

@ -8,11 +8,11 @@ class TagQuery
].freeze ].freeze
BOOLEAN_METATAGS = %w[ BOOLEAN_METATAGS = %w[
hassource hastitle hasdescription isparent ischild inpool pending_replacements artverified hassource hastitle hasdescription hastranscript isparent ischild inpool pending_replacements artverified
].freeze ].freeze
NEGATABLE_METATAGS = %w[ NEGATABLE_METATAGS = %w[
id filetype type rating title description parent user user_id approver flagger deletedby delreason id filetype type rating title description transcript parent user user_id approver flagger deletedby delreason
source status pool set fav favoritedby note locked upvote votedup downvote voteddown voted source status pool set fav favoritedby note locked upvote votedup downvote voteddown voted
width height mpixels ratio filesize duration score favcount date age change tagcount width height mpixels ratio filesize duration score favcount date age change tagcount
commenter comm noter noteupdater commenter comm noter noteupdater
@ -296,6 +296,9 @@ class TagQuery
when "description", "-description", "~description" when "description", "-description", "~description"
add_to_query(type, :description) { g2 } add_to_query(type, :description) { g2 }
when "transcript", "-transcript", "~transcript"
add_to_query(type, :transcript) { g2 }
when "note", "-note", "~note" when "note", "-note", "~note"
add_to_query(type, :note) { g2 } add_to_query(type, :note) { g2 }

View File

@ -53,6 +53,7 @@ class UploadService
p.is_rating_locked = upload.locked_rating if upload.locked_rating.present? p.is_rating_locked = upload.locked_rating if upload.locked_rating.present?
p.title = upload.title.strip p.title = upload.title.strip
p.description = upload.description.strip p.description = upload.description.strip
p.transcript = upload.transcript.strip
p.md5 = upload.md5 p.md5 = upload.md5
p.file_ext = upload.file_ext p.file_ext = upload.file_ext
p.image_width = upload.image_width p.image_width = upload.image_width

View File

@ -23,6 +23,7 @@ class Post < ApplicationRecord
validates :bg_color, format: { with: /\A[A-Fa-f0-9]{6}\z/ }, allow_nil: true validates :bg_color, format: { with: /\A[A-Fa-f0-9]{6}\z/ }, allow_nil: true
validates :title, length: { maximum: Danbooru.config.post_title_max_size }, if: :title_changed? validates :title, length: { maximum: Danbooru.config.post_title_max_size }, if: :title_changed?
validates :description, length: { maximum: Danbooru.config.post_descr_max_size }, if: :description_changed? validates :description, length: { maximum: Danbooru.config.post_descr_max_size }, if: :description_changed?
validates :transcript, length: { maximum: Danbooru.config.post_trasc_max_size }, if: :transcript_changed?
validate :added_tags_are_valid, if: :should_process_tags? validate :added_tags_are_valid, if: :should_process_tags?
validate :removed_tags_are_valid, if: :should_process_tags? validate :removed_tags_are_valid, if: :should_process_tags?
validate :has_artist_tag, if: :should_process_tags? validate :has_artist_tag, if: :should_process_tags?
@ -1174,6 +1175,7 @@ class Post < ApplicationRecord
id: id, id: id,
title: title, title: title,
description: description, description: description,
transcript: transcript,
md5: md5, md5: md5,
tags: tag_string, tags: tag_string,
height: image_height, height: image_height,
@ -1323,7 +1325,7 @@ class Post < ApplicationRecord
end end
def saved_change_to_watched_attributes? def saved_change_to_watched_attributes?
saved_change_to_rating? || saved_change_to_source? || saved_change_to_parent_id? || saved_change_to_tag_string? || saved_change_to_locked_tags? || saved_change_to_title? || saved_change_to_description? saved_change_to_rating? || saved_change_to_source? || saved_change_to_parent_id? || saved_change_to_tag_string? || saved_change_to_locked_tags? || saved_change_to_title? || saved_change_to_description? || saved_change_to_transcript?
end end
def create_new_version def create_new_version
@ -1343,6 +1345,7 @@ class Post < ApplicationRecord
self.parent_id = target.parent_id self.parent_id = target.parent_id
self.title = target.title self.title = target.title
self.description = target.description self.description = target.description
self.transcript = target.transcript
self.edit_reason = "Revert to version #{target.version}" self.edit_reason = "Revert to version #{target.version}"
end end

View File

@ -249,6 +249,7 @@ class PostReplacement < ApplicationRecord
parent_id: post.id, parent_id: post.id,
title: post.title, title: post.title,
description: post.description, description: post.description,
transcript: post.transcript,
locked_tags: post.locked_tags, locked_tags: post.locked_tags,
replacement_id: self.id replacement_id: self.id
} }

View File

@ -39,6 +39,7 @@ class PostVersion < ApplicationRecord
locked_tags: post.locked_tags, locked_tags: post.locked_tags,
title: post.title, title: post.title,
description: post.description, description: post.description,
transcript: post.transcript,
reason: post.edit_reason reason: post.edit_reason
}) })
end end
@ -71,6 +72,7 @@ class PostVersion < ApplicationRecord
self.source_changed = prev.nil? || source != prev.try(:source) self.source_changed = prev.nil? || source != prev.try(:source)
self.title_changed = prev.nil? || title != prev.try(:title) self.title_changed = prev.nil? || title != prev.try(:title)
self.description_changed = prev.nil? || description != prev.try(:description) self.description_changed = prev.nil? || description != prev.try(:description)
self.transcript_changed = prev.nil? || transcript != prev.try(:transcript)
end end
def tag_array def tag_array
@ -221,6 +223,10 @@ class PostVersion < ApplicationRecord
post.description = previous.description post.description = previous.description
end end
if transcript_changed
post.transcript = previous.transcript
end
if rating_changed && !post.is_rating_locked? if rating_changed && !post.is_rating_locked?
post.rating = previous.rating post.rating = previous.rating
end end

View File

@ -150,6 +150,7 @@ class PostPresenter < Presenter
uploader_id: post.uploader_id, uploader_id: post.uploader_id,
title: post.title, title: post.title,
description: post.description, description: post.description,
transcript: post.transcript,
flags: { flags: {
pending: post.is_pending, pending: post.is_pending,
flagged: post.is_flagged, flagged: post.is_flagged,

View File

@ -139,5 +139,5 @@ class PostSerializer < ActiveModel::Serializer
attributes :id, :created_at, :updated_at, :file, :preview, :sample, :score, :tags, :locked_tags, :change_seq, :flags, attributes :id, :created_at, :updated_at, :file, :preview, :sample, :score, :tags, :locked_tags, :change_seq, :flags,
:rating, :fav_count, :sources, :pools, :relationships, :approver_id, :uploader_id, :title, :description, :rating, :fav_count, :sources, :pools, :relationships, :approver_id, :uploader_id, :title, :description,
:comment_count, :is_favorited, :has_notes, :duration :transcript, :comment_count, :is_favorited, :has_notes, :duration
end end

View File

@ -21,6 +21,9 @@
<div class="pv-description-label pv-label"> <div class="pv-description-label pv-label">
Description Description
</div> </div>
<div class="pv-transcript-label pv-label">
Transcript
</div>
<div class="pv-tags-locked-label pv-label"> <div class="pv-tags-locked-label pv-label">
Locked Tags Locked Tags
</div> </div>
@ -70,6 +73,21 @@
<em>Cleared</em> <em>Cleared</em>
<% end %> <% end %>
</div> </div>
<div class="pv-transcript pv-content">
<% if post_version.transcript.present? %>
<div class="desc-show">
<%= post_version.transcript_changed ? "Show Transcript" : "No change" %></div>
<div id='transcript-<%= post_version.id %>' class='desc-popup box-section'>
<h2>Transcript</h2>
<div class="closebutton">X</div>
<div class='desc-popup-inner'>
<p class="dtext-container"><%= format_text(post_version.transcript) %></p>
</div>
</div>
<% elsif post_version.transcript_changed && post_version.version != 1%>
<em>Cleared</em>
<% end %>
</div>
<div class="pv-tags-locked pv-content"> <div class="pv-tags-locked pv-content">
<%= post_version_locked_diff(post_version) %> <%= post_version_locked_diff(post_version) %>
</div> </div>

View File

@ -6,6 +6,8 @@
<%= f.input :title_changed, label: "Title Changed", collection: [%w[Yes true], %w[No false]], include_blank: true %> <%= f.input :title_changed, label: "Title Changed", collection: [%w[Yes true], %w[No false]], include_blank: true %>
<%= f.input :description, label: "Description" %> <%= f.input :description, label: "Description" %>
<%= f.input :description_changed, label: "Description Changed", collection: [%w[Yes true], %w[No false]], include_blank: true %> <%= f.input :description_changed, label: "Description Changed", collection: [%w[Yes true], %w[No false]], include_blank: true %>
<%= f.input :transcript, label: "Transcript" %>
<%= f.input :transcript_changed, label: "Transcript Changed", collection: [%w[Yes true], %w[No false]], include_blank: true %>
<%= f.input :rating_changed, label: "Rating Changed To", collection: rating_collection + [%w[Any any]], include_blank: true %> <%= f.input :rating_changed, label: "Rating Changed To", collection: rating_collection + [%w[Any any]], include_blank: true %>
<%= f.input :rating, label: "Final Rating", collection: rating_collection, include_blank: true %> <%= f.input :rating, label: "Final Rating", collection: rating_collection, include_blank: true %>
<%= f.input :parent_id, label: "Parent ID" %> <%= f.input :parent_id, label: "Parent ID" %>

View File

@ -46,6 +46,8 @@
<%= f.input :description, as: :dtext, limit: Danbooru.config.post_descr_max_size, allow_color: true %> <%= f.input :description, as: :dtext, limit: Danbooru.config.post_descr_max_size, allow_color: true %>
</div> </div>
<%= f.input :transcript, as: :text, label: "Transcript", input_html: { size: "60x5", spellcheck: true } %>
<% if CurrentUser.is_privileged? %> <% if CurrentUser.is_privileged? %>
<div class="input"> <div class="input">
<%= f.label :blank, "Lock" %> <%= f.label :blank, "Lock" %>

View File

@ -194,6 +194,17 @@
</div> </div>
<% end %> <% end %>
<% if @post.transcript.present? %>
<div id="post-transcript-container" class="styled-dtext">
<details id="transcript">
<summary>Transcript</summary>
<div>
<%= format_text(@post.transcript, max_thumbs: 0) %>
</div>
</details>
</div>
<% end %>
<ul class="menu mobile-only"> <ul class="menu mobile-only">
<li><a href="#image-and-nav">Image</a></li> <li><a href="#image-and-nav">Image</a></li>
<li><a href="#tag-list">Tags/Info</a></li> <li><a href="#tag-list">Tags/Info</a></li>

View File

@ -329,6 +329,10 @@ module Danbooru
50_000 50_000
end end
def post_trasc_max_size
50_000
end
def ticket_max_size def ticket_max_size
5_000 5_000
end end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddTranscriptToPosts < ActiveRecord::Migration[7.1]
def change
add_column(:posts, :transcript, :text, null: false, default: "")
end
end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddTranscriptToPostVersions < ActiveRecord::Migration[7.1]
def change
add_column :post_versions, :transcript, :text
end
end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddTranscriptChangedToPostVersions < ActiveRecord::Migration[7.1]
def change
add_column(:post_versions, :transcript_changed, :boolean, null: false, default: false)
end
end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddTranscriptToUploads < ActiveRecord::Migration[7.1]
def change
add_column(:uploads, :transcript, :text, null: false, default: "")
end
end

View File

@ -0,0 +1,39 @@
# frozen_string_literal: true
class UpdatePostsTriggerChangeSeqForTranscript < ActiveRecord::Migration[7.1]
def up
execute <<-SQL.squish
CREATE OR REPLACE FUNCTION public.posts_trigger_change_seq() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
IF NEW.tag_string != OLD.tag_string OR NEW.parent_id != OLD.parent_id OR NEW.source != OLD.source OR NEW.approver_id != OLD.approver_id OR NEW.rating != OLD.rating OR NEW.title != OLD.title OR NEW.description != OLD.description OR NEW.transcript != OLD.transcript OR NEW.md5 != OLD.md5 OR NEW.is_deleted != OLD.is_deleted OR NEW.is_pending != OLD.is_pending OR NEW.is_flagged != OLD.is_flagged OR NEW.is_rating_locked != OLD.is_rating_locked OR NEW.is_status_locked != OLD.is_status_locked OR NEW.is_note_locked != OLD.is_note_locked OR NEW.bit_flags != OLD.bit_flags OR NEW.has_active_children != OLD.has_active_children OR NEW.last_noted_at != OLD.last_noted_at
THEN
NEW.change_seq = nextval('public.posts_change_seq_seq');
END IF;
RETURN NEW;
END;
$$;
SQL
end
def down
execute <<-SQL.squish
CREATE OR REPLACE FUNCTION public.posts_trigger_change_seq() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
IF NEW.tag_string != OLD.tag_string OR NEW.parent_id != OLD.parent_id OR NEW.source != OLD.source OR NEW.approver_id != OLD.approver_id OR NEW.rating != OLD.rating OR NEW.title != OLD.title OR NEW.description != OLD.description OR NEW.md5 != OLD.md5 OR NEW.is_deleted != OLD.is_deleted OR NEW.is_pending != OLD.is_pending OR NEW.is_flagged != OLD.is_flagged OR NEW.is_rating_locked != OLD.is_rating_locked OR NEW.is_status_locked != OLD.is_status_locked OR NEW.is_note_locked != OLD.is_note_locked OR NEW.bit_flags != OLD.bit_flags OR NEW.has_active_children != OLD.has_active_children OR NEW.last_noted_at != OLD.last_noted_at
THEN
NEW.change_seq = nextval('public.posts_change_seq_seq');
END IF;
RETURN NEW;
END;
$$;
SQL
end
end

View File

@ -29,15 +29,7 @@ COMMENT ON EXTENSION pg_trgm IS 'text similarity measurement and index searching
CREATE FUNCTION public.posts_trigger_change_seq() RETURNS trigger CREATE FUNCTION public.posts_trigger_change_seq() RETURNS trigger
LANGUAGE plpgsql LANGUAGE plpgsql
AS $$ AS $$ BEGIN IF NEW.tag_string != OLD.tag_string OR NEW.parent_id != OLD.parent_id OR NEW.source != OLD.source OR NEW.approver_id != OLD.approver_id OR NEW.rating != OLD.rating OR NEW.title != OLD.title OR NEW.description != OLD.description OR NEW.transcript != OLD.transcript OR NEW.md5 != OLD.md5 OR NEW.is_deleted != OLD.is_deleted OR NEW.is_pending != OLD.is_pending OR NEW.is_flagged != OLD.is_flagged OR NEW.is_rating_locked != OLD.is_rating_locked OR NEW.is_status_locked != OLD.is_status_locked OR NEW.is_note_locked != OLD.is_note_locked OR NEW.bit_flags != OLD.bit_flags OR NEW.has_active_children != OLD.has_active_children OR NEW.last_noted_at != OLD.last_noted_at THEN NEW.change_seq = nextval('public.posts_change_seq_seq'); END IF; RETURN NEW; END; $$;
BEGIN
IF NEW.tag_string != OLD.tag_string OR NEW.parent_id != OLD.parent_id OR NEW.source != OLD.source OR NEW.approver_id != OLD.approver_id OR NEW.rating != OLD.rating OR NEW.title != OLD.title OR NEW.description != OLD.description OR NEW.md5 != OLD.md5 OR NEW.is_deleted != OLD.is_deleted OR NEW.is_pending != OLD.is_pending OR NEW.is_flagged != OLD.is_flagged OR NEW.is_rating_locked != OLD.is_rating_locked OR NEW.is_status_locked != OLD.is_status_locked OR NEW.is_note_locked != OLD.is_note_locked OR NEW.bit_flags != OLD.bit_flags OR NEW.has_active_children != OLD.has_active_children OR NEW.last_noted_at != OLD.last_noted_at
THEN
NEW.change_seq = nextval('public.posts_change_seq_seq');
END IF;
RETURN NEW;
END;
$$;
SET default_tablespace = ''; SET default_tablespace = '';
@ -1575,7 +1567,9 @@ CREATE TABLE public.post_versions (
description text, description text,
description_changed boolean DEFAULT false NOT NULL, description_changed boolean DEFAULT false NOT NULL,
version integer DEFAULT 1 NOT NULL, version integer DEFAULT 1 NOT NULL,
reason character varying reason character varying,
transcript text,
transcript_changed boolean DEFAULT false NOT NULL
); );
@ -1690,7 +1684,8 @@ CREATE TABLE public.posts (
generated_samples character varying[], generated_samples character varying[],
duration numeric, duration numeric,
is_comment_disabled boolean DEFAULT false NOT NULL, is_comment_disabled boolean DEFAULT false NOT NULL,
is_comment_locked boolean DEFAULT false NOT NULL is_comment_locked boolean DEFAULT false NOT NULL,
transcript text DEFAULT ''::text NOT NULL
); );
@ -2141,7 +2136,8 @@ CREATE TABLE public.uploads (
image_width integer, image_width integer,
image_height integer, image_height integer,
title text DEFAULT ''::text NOT NULL, title text DEFAULT ''::text NOT NULL,
description text DEFAULT ''::text NOT NULL description text DEFAULT ''::text NOT NULL,
transcript text DEFAULT ''::text NOT NULL
); );
@ -4682,6 +4678,11 @@ ALTER TABLE ONLY public.avoid_postings
SET search_path TO "$user", public; SET search_path TO "$user", public;
INSERT INTO "schema_migrations" (version) VALUES INSERT INTO "schema_migrations" (version) VALUES
('20241110171706'),
('20241110171006'),
('20241110170952'),
('20241110170945'),
('20241110170937'),
('20241029202902'), ('20241029202902'),
('20241010174014'), ('20241010174014'),
('20241009155325'), ('20241009155325'),