From 646571385817f0928a5e1b37b6750b0d952d5b9c Mon Sep 17 00:00:00 2001 From: 2458773093 <2458773093@protonmail.com> Date: Wed, 11 Sep 2019 17:20:55 +0300 Subject: [PATCH 1/5] annotation fix --- app/models/account_verification_request.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/account_verification_request.rb b/app/models/account_verification_request.rb index 75896dbc..0b451879 100644 --- a/app/models/account_verification_request.rb +++ b/app/models/account_verification_request.rb @@ -6,7 +6,7 @@ # account_id :bigint(8) # image_file_name :string # image_content_type :string -# image_file_size :bigint(8) +# image_file_size :integer # image_updated_at :datetime # created_at :datetime not null # updated_at :datetime not null From d1f7d17ef5a387c5b76d5eedd41ce6641d3cd0dc Mon Sep 17 00:00:00 2001 From: 2458773093 <2458773093@protonmail.com> Date: Wed, 11 Sep 2019 17:21:29 +0300 Subject: [PATCH 2/5] new revision model --- app/models/status.rb | 2 ++ app/models/status_revision.rb | 13 +++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 app/models/status_revision.rb diff --git a/app/models/status.rb b/app/models/status.rb index 57b1c694..85aaf7e4 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -24,6 +24,7 @@ # poll_id :bigint(8) # group_id :integer # quote_of_id :bigint(8) +# revised_at :datetime # class Status < ApplicationRecord @@ -61,6 +62,7 @@ class Status < ApplicationRecord has_many :mentions, dependent: :destroy, inverse_of: :status has_many :active_mentions, -> { active }, class_name: 'Mention', inverse_of: :status has_many :media_attachments, dependent: :nullify + has_many :revisions, class_name: 'StatusRevision', dependent: :destroy has_and_belongs_to_many :tags has_and_belongs_to_many :preview_cards diff --git a/app/models/status_revision.rb b/app/models/status_revision.rb new file mode 100644 index 00000000..62004c54 --- /dev/null +++ b/app/models/status_revision.rb @@ -0,0 +1,13 @@ +# == Schema Information +# +# Table name: status_revisions +# +# id :bigint(8) not null, primary key +# status_id :bigint(8) +# text :string +# created_at :datetime not null +# updated_at :datetime not null +# + +class StatusRevision < ApplicationRecord +end From cdc0b8dd2fcd6dc0f1f0527e4d31cd317298a157 Mon Sep 17 00:00:00 2001 From: 2458773093 <2458773093@protonmail.com> Date: Wed, 11 Sep 2019 17:21:45 +0300 Subject: [PATCH 3/5] new revision migrations --- db/migrate/20190917135359_create_status_revisions.rb | 9 +++++++++ .../20190917141707_add_revised_at_to_statuses.rb | 5 +++++ db/schema.rb | 10 +++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20190917135359_create_status_revisions.rb create mode 100644 db/migrate/20190917141707_add_revised_at_to_statuses.rb diff --git a/db/migrate/20190917135359_create_status_revisions.rb b/db/migrate/20190917135359_create_status_revisions.rb new file mode 100644 index 00000000..d3ca5bd5 --- /dev/null +++ b/db/migrate/20190917135359_create_status_revisions.rb @@ -0,0 +1,9 @@ +class CreateStatusRevisions < ActiveRecord::Migration[5.2] + def change + create_table :status_revisions do |t| + t.bigint :status_id + t.string :text + t.timestamps + end + end +end diff --git a/db/migrate/20190917141707_add_revised_at_to_statuses.rb b/db/migrate/20190917141707_add_revised_at_to_statuses.rb new file mode 100644 index 00000000..a9e88d78 --- /dev/null +++ b/db/migrate/20190917141707_add_revised_at_to_statuses.rb @@ -0,0 +1,5 @@ +class AddRevisedAtToStatuses < ActiveRecord::Migration[5.2] + def change + add_column :statuses, :revised_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index ac9420ea..a81bcc54 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2019_09_03_162122) do +ActiveRecord::Schema.define(version: 2019_09_17_141707) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -672,6 +672,13 @@ ActiveRecord::Schema.define(version: 2019_09_03_162122) do t.index ["account_id", "status_id"], name: "index_status_pins_on_account_id_and_status_id", unique: true end + create_table "status_revisions", force: :cascade do |t| + t.bigint "status_id" + t.string "text" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "status_stats", force: :cascade do |t| t.bigint "status_id", null: false t.bigint "replies_count", default: 0, null: false @@ -703,6 +710,7 @@ ActiveRecord::Schema.define(version: 2019_09_03_162122) do t.bigint "poll_id" t.integer "group_id" t.bigint "quote_of_id" + t.datetime "revised_at" t.index ["account_id", "id", "visibility", "updated_at"], name: "index_statuses_20180106", order: { id: :desc } t.index ["group_id"], name: "index_statuses_on_group_id" t.index ["in_reply_to_account_id"], name: "index_statuses_on_in_reply_to_account_id" From 7219c9b5e6255ab9d076ed0039072d84aa82dd3f Mon Sep 17 00:00:00 2001 From: 2458773093 <2458773093@protonmail.com> Date: Tue, 17 Sep 2019 17:22:02 +0300 Subject: [PATCH 4/5] service + seerializer completed --- app/serializers/rest/status_serializer.rb | 2 +- app/services/edit_status_service.rb | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index c663c909..af017da7 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class REST::StatusSerializer < ActiveModel::Serializer - attributes :id, :created_at, :in_reply_to_id, :in_reply_to_account_id, + attributes :id, :created_at, :revised_at, :in_reply_to_id, :in_reply_to_account_id, :sensitive, :spoiler_text, :visibility, :language, :uri, :url, :replies_count, :reblogs_count, :favourites_count, :quote_of_id diff --git a/app/services/edit_status_service.rb b/app/services/edit_status_service.rb index f90f0312..f464f570 100644 --- a/app/services/edit_status_service.rb +++ b/app/services/edit_status_service.rb @@ -25,9 +25,11 @@ class EditStatusService < BaseService validate_media! preprocess_attributes! + revision_text = prepare_revision_text process_status! postprocess_status! + create_revision! revision_text redis.setex(idempotency_key, 3_600, @status.id) if idempotency_given? @@ -60,6 +62,25 @@ class EditStatusService < BaseService LinkCrawlWorker.perform_async(@status.id) unless @status.spoiler_text? end + def prepare_revision_text + text = @status.text + current_media_ids = @status.media_attachments.pluck(:id) + new_media_ids = @options[:media_ids].take(4).map(&:to_i) + + if current_media_ids.sort != new_media_ids.sort + text = "" if text == @options[:text] + text += " [Media attachments changed]" + end + + text.strip() + end + + def create_revision!(text) + @status.revisions.create!({ + text: text + }) + end + def validate_media! return if @options[:media_ids].blank? || !@options[:media_ids].is_a?(Enumerable) @@ -100,6 +121,7 @@ class EditStatusService < BaseService def status_attributes { + revised_at: Time.now, text: @text, media_attachments: @media || [], sensitive: (@options[:sensitive].nil? ? @account.user&.setting_default_sensitive : @options[:sensitive]) || @options[:spoiler_text].present?, From 498630f20f0dab076feeb9a5c46927d105f08aac Mon Sep 17 00:00:00 2001 From: 2458773093 <2458773093@protonmail.com> Date: Tue, 17 Sep 2019 18:23:51 +0300 Subject: [PATCH 5/5] revision history ui --- app/controllers/api/v1/statuses_controller.rb | 12 ++-- .../gabsocial/actions/status_revision_list.js | 16 +++++ app/javascript/gabsocial/components/status.js | 6 +- .../gabsocial/containers/status_container.js | 4 ++ .../features/ui/components/modal_root.js | 2 + .../ui/components/status_revision_list.js | 44 ++++++++++++ .../ui/components/status_revision_modal.js | 40 +++++++++++ .../status_revision_list_container.js | 27 +++++++ .../features/ui/util/async-components.js | 4 ++ app/javascript/gabsocial/reducers/index.js | 2 + .../reducers/status_revision_list.js | 31 ++++++++ app/javascript/styles/application.scss | 1 + .../components/status-revisions.scss | 72 +++++++++++++++++++ .../rest/status_revision_serializer.rb | 5 ++ config/routes.rb | 1 + 15 files changed, 257 insertions(+), 10 deletions(-) create mode 100644 app/javascript/gabsocial/actions/status_revision_list.js create mode 100644 app/javascript/gabsocial/features/ui/components/status_revision_list.js create mode 100644 app/javascript/gabsocial/features/ui/components/status_revision_modal.js create mode 100644 app/javascript/gabsocial/features/ui/containers/status_revision_list_container.js create mode 100644 app/javascript/gabsocial/reducers/status_revision_list.js create mode 100644 app/javascript/styles/gabsocial/components/status-revisions.scss create mode 100644 app/serializers/rest/status_revision_serializer.rb diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index f04aa3aa..1a0dab99 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -6,7 +6,7 @@ class Api::V1::StatusesController < Api::BaseController before_action -> { authorize_if_got_token! :read, :'read:statuses' }, except: [:create, :update, :destroy] before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only: [:create, :update, :destroy] before_action :require_user!, except: [:show, :context, :card] - before_action :set_status, only: [:show, :context, :card, :update] + before_action :set_status, only: [:show, :context, :card, :update, :revisions] respond_to :json @@ -33,14 +33,10 @@ class Api::V1::StatusesController < Api::BaseController render json: @context, serializer: REST::ContextSerializer, relationships: StatusRelationshipsPresenter.new(statuses, current_user&.account_id) end - def card - @card = @status.preview_cards.first + def revisions + @revisions = @status.revisions - if @card.nil? - render_empty - else - render json: @card, serializer: REST::PreviewCardSerializer - end + render json: @revisions, each_serializer: REST::StatusRevisionSerializer end def create diff --git a/app/javascript/gabsocial/actions/status_revision_list.js b/app/javascript/gabsocial/actions/status_revision_list.js new file mode 100644 index 00000000..672f7bb4 --- /dev/null +++ b/app/javascript/gabsocial/actions/status_revision_list.js @@ -0,0 +1,16 @@ +import api from '../api'; + +export const STATUS_REVISION_LIST_LOAD = 'STATUS_REVISION_LIST'; +export const STATUS_REVISION_LIST_LOAD_SUCCESS = 'STATUS_REVISION_LIST_SUCCESS'; +export const STATUS_REVISION_LIST_LOAD_FAIL = 'STATUS_REVISION_LIST_FAIL'; + +const loadSuccess = data => ({ type: STATUS_REVISION_LIST_LOAD_SUCCESS, payload: data }); +const loadFail = e => ({ type: STATUS_REVISION_LIST_LOAD_FAIL, payload: e }); + +export function load(statusId) { + return (dispatch, getState) => { + api(getState).get(`/api/v1/statuses/${statusId}/revisions`) + .then(res => dispatch(loadSuccess(res.data))) + .catch(e => dispatch(loadFail(e))); + }; +} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/status.js b/app/javascript/gabsocial/components/status.js index 4e8fde9e..87d7d13e 100644 --- a/app/javascript/gabsocial/components/status.js +++ b/app/javascript/gabsocial/components/status.js @@ -67,6 +67,7 @@ class Status extends ImmutablePureComponent { otherAccounts: ImmutablePropTypes.list, onClick: PropTypes.func, onReply: PropTypes.func, + onShowRevisions: PropTypes.func, onQuote: PropTypes.func, onFavourite: PropTypes.func, onReblog: PropTypes.func, @@ -438,9 +439,10 @@ class Status extends ImmutablePureComponent { - {!group && status.get('group') && ( + {((!group && status.get('group')) || status.get('revised_at') !== null) && (