Compare commits

...
This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.

8 Commits

Author SHA1 Message Date
Jarek Radosz
38fdd842f5
UX: Fix chat separator alignment (#20669)
Also: work around 1px svg shift in scroll-to-bottom button
2023-03-18 18:03:54 +01:00
Joffrey JAFFEUX
aeab38aff1
UX: disable arrow up to edit if last message is not editable (#20729) 2023-03-17 23:08:10 +01:00
Joffrey JAFFEUX
aa8eff5e16
FIX: ensures updateLastRead is called when receiving a message (#20728)
This behavior is hard to test as it's mostly fixing a race condition: User A sends a message at the same time than User B, which as a result doesn't cause a scroll for the second message and we don't update last read unless we do a small up and down scroll.

`updateLastRead` is debounced so it has no direct consequences to call it slightly more often than what should ideally be needed.
2023-03-17 22:46:59 +01:00
Daniel Waterworth
293cb7bde2
FIX: An ember build is required to run the system tests (#20725) 2023-03-17 13:20:49 -05:00
Joffrey JAFFEUX
cfee0cfee9
FIX: ensures lightbox is working after collapse/expand (#20724)
Prior to this fix, the upload was removed from DOM when collapsed and not decorated again on expand, which was causing lightbox to not get reapplied. The fix is reverting to previous state where content was not removed from DOM.
2023-03-17 18:26:32 +01:00
Joffrey JAFFEUX
c5e5b6d5ab
DEV: fixes a flakey spec (#20721) 2023-03-17 18:01:19 +01:00
Joffrey JAFFEUX
184ce647ea
FIX: correctly infer polymorphic class from bookmarkable type (#20719)
Prior to this change `registered_bookmarkable` would return `nil` as  `type` in `Bookmark.registered_bookmarkable_from_type(type)` would be `ChatMessage` and we registered a `Chat::Message` class.

This commit will now properly rely on each model `polymorphic_class_for(name)` to help us infer the proper type from a a `bookmarkable_type`.

Tests have also been added to ensure that creating/destroying chat message bookmarks is working correctly.

---

Longer explanation

Currently when you save a bookmark in the database, it's associated to another object through a polymorphic relationship, which will is represented by two columns: `bookmarkable_id` and `bookmarkable_type`. The `bookmarkable_id` contains the id of the relationship (a post ID for example) and the `bookmarkable_type` contains the type of the object as a string by default, (`"Post"` for example).

Chat plugin just started namespacing objects, as a result a model named `ChatMessage` is now named `Chat::Message`, to avoid complex and risky migrations we rely on methods provided by rails to alter the `bookmarkable_type` when we save it: we want to still save it as `"ChatMessage"` and not `"Chat::Message"`. And, to retrieve the correct model when we load the bookmark from the database: we want `"ChatMessage"` to load the `Chat::Message` model and not the `ChatMessage`model which doesn't exist anymore.

On top of this the bookmark codepath is allowing plugins to register types and will check against these types, so we alter this code path to be able to do a similar ChatMessage <-> Chat::Message dance and allow to check the type is valid. In the specific case of this commit, we were retrieving a `"ChatMessage"` bookmarkable_type from the DB and looking for it in the registered bookmarkable types which contain `Chat::Message` and not `ChatMessage`.
2023-03-17 17:20:24 +01:00
TheJammiestDodger
f57ba758ce
UX: Update Install Popular items and links (#20688)
* UX: Update 'Install Popular' items and links

* Update popular-themes.js

* Update popular-themes.js

* Update popular-themes.js

* Lint

---------

Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>
2023-03-17 16:05:36 +00:00
10 changed files with 143 additions and 44 deletions

View File

@ -2,7 +2,7 @@ export const POPULAR_THEMES = [
{
name: "Graceful",
value: "https://github.com/discourse/graceful",
preview: "https://theme-creator.discourse.org/theme/awesomerobot/graceful",
preview: "https://discourse.theme-creator.io/theme/awesomerobot/graceful",
description: "A light and graceful theme for Discourse.",
meta_url:
"https://meta.discourse.org/t/a-graceful-theme-for-discourse/93040",
@ -10,8 +10,7 @@ export const POPULAR_THEMES = [
{
name: "Material Design Theme",
value: "https://github.com/discourse/material-design-stock-theme",
preview:
"https://theme-creator.discourse.org/theme/tshenry/material-design",
preview: "https://discourse.theme-creator.io/theme/tshenry/material-design",
description:
"Inspired by Material Design, this theme comes with several color palettes (incl. a dark one).",
meta_url: "https://meta.discourse.org/t/material-design-stock-theme/47142",
@ -19,7 +18,7 @@ export const POPULAR_THEMES = [
{
name: "Minima",
value: "https://github.com/discourse/minima",
preview: "https://theme-creator.discourse.org/theme/awesomerobot/minima",
preview: "https://discourse.theme-creator.io/theme/awesomerobot/minima",
description: "A minimal theme with reduced UI elements and focus on text.",
meta_url:
"https://meta.discourse.org/t/minima-a-minimal-theme-for-discourse/108178",
@ -27,7 +26,7 @@ export const POPULAR_THEMES = [
{
name: "Sam's Simple Theme",
value: "https://github.com/discourse/discourse-simple-theme",
preview: "https://theme-creator.discourse.org/theme/sam/simple",
preview: "https://discourse.theme-creator.io/theme/sam/simple",
description:
"Simplified front page design with classic colors and typography.",
meta_url:
@ -36,6 +35,8 @@ export const POPULAR_THEMES = [
{
name: "Brand Header",
value: "https://github.com/discourse/discourse-brand-header",
preview:
"https://discourse.theme-creator.io/theme/vinothkannans/brand-header",
description:
"Add an extra top header with your logo, navigation links and social icons.",
meta_url: "https://meta.discourse.org/t/brand-header-theme-component/77977",
@ -45,7 +46,7 @@ export const POPULAR_THEMES = [
name: "Custom Header Links",
value: "https://github.com/discourse/discourse-custom-header-links",
preview:
"https://theme-creator.discourse.org/theme/Johani/custom-header-links",
"https://discourse.theme-creator.io/theme/awesomerobot/custom-header-links",
description: "Easily add custom text-based links to the header.",
meta_url: "https://meta.discourse.org/t/custom-header-links/90588",
component: true,
@ -61,7 +62,7 @@ export const POPULAR_THEMES = [
name: "Category Banners",
value: "https://github.com/discourse/discourse-category-banners",
preview:
"https://theme-creator.discourse.org/theme/awesomerobot/discourse-category-banners",
"https://discourse.theme-creator.io/theme/awesomerobot/discourse-category-banners",
description:
"Show banners on category pages using your existing category details.",
meta_url: "https://meta.discourse.org/t/discourse-category-banners/86241",
@ -70,7 +71,7 @@ export const POPULAR_THEMES = [
{
name: "Kanban Board",
value: "https://github.com/discourse/discourse-kanban-theme",
preview: "https://theme-creator.discourse.org/theme/david/kanban",
preview: "https://discourse.theme-creator.io/theme/david/kanban",
description: "Display and organize topics using a Kanban board interface.",
meta_url:
"https://meta.discourse.org/t/kanban-board-theme-component/118164",
@ -84,10 +85,19 @@ export const POPULAR_THEMES = [
meta_url: "https://meta.discourse.org/t/hamburger-theme-selector/61210",
component: true,
},
{
name: "Sidebar Theme Toggle",
value: "https://github.com/discourse/discourse-sidebar-theme-toggle",
description:
"Displays a theme selector in the sidebar menus footer provided there is more than one user-selectable theme.",
meta_url: "https://meta.discourse.org/t/sidebar-theme-toggle/242802",
component: true,
},
{
name: "Header Submenus",
value: "https://github.com/discourse/discourse-header-submenus",
preview: "https://theme-creator.discourse.org/theme/Johani/header-submenus",
preview:
"https://discourse.theme-creator.io/theme/awesomerobot/header-submenus",
description: "Lets you build a header menu with submenus (dropdowns).",
meta_url: "https://meta.discourse.org/t/header-submenus/94584",
component: true,
@ -104,7 +114,7 @@ export const POPULAR_THEMES = [
{
name: "Easy Responsive Footer",
value: "https://github.com/discourse/Discourse-easy-footer",
preview: "https://theme-creator.discourse.org/theme/Johani/easy-footer",
preview: "https://discourse.theme-creator.io/theme/Johani/easy-footer",
description: "Add a fully responsive footer without writing any HTML.",
meta_url: "https://meta.discourse.org/t/easy-responsive-footer/95818",
component: true,

View File

@ -46,7 +46,8 @@ class Bookmark < ActiveRecord::Base
validates :name, length: { maximum: 100 }
def registered_bookmarkable
Bookmark.registered_bookmarkable_from_type(self.bookmarkable_type)
type = Bookmark.polymorphic_class_for(self.bookmarkable_type).name
Bookmark.registered_bookmarkable_from_type(type)
end
def polymorphic_columns_present

View File

@ -213,7 +213,10 @@ task "docker:test" do
@good &&= run_or_fail("bundle exec rspec #{params.join(" ")}".strip)
end
@good &&= run_or_fail("bundle exec rspec spec/system".strip) if ENV["RUN_SYSTEM_TESTS"]
if ENV["RUN_SYSTEM_TESTS"]
@good &&= run_or_fail("bin/ember-cli --build")
@good &&= run_or_fail("bundle exec rspec spec/system")
end
end
unless ENV["SKIP_PLUGINS"]

View File

@ -613,6 +613,7 @@ export default class ChatLivePane extends Component {
const message = ChatMessage.create(this.args.channel, data.chat_message);
this.args.channel.addMessages([message]);
this.scrollToLatestMessage();
this.updateLastReadMessage();
} else {
// If we are almost at the bottom, we append the message and notice the user
const message = ChatMessage.create(this.args.channel, data.chat_message);
@ -895,16 +896,19 @@ export default class ChatLivePane extends Component {
@action
editLastMessageRequested() {
const lastUserMessage = this.args.channel.messages.findLast(
(message) =>
message.user.id === this.currentUser.id &&
!message.staged &&
!message.error
(message) => message.user.id === this.currentUser.id
);
if (lastUserMessage) {
this.editingMessage = lastUserMessage;
this._focusComposer();
if (!lastUserMessage) {
return;
}
if (lastUserMessage.staged || lastUserMessage.error) {
return;
}
this.editingMessage = lastUserMessage;
this._focusComposer();
}
@action

View File

@ -2,30 +2,18 @@
{{#if this.hasUploads}}
{{html-safe @cooked}}
<Collapser
@header={{this.uploadsHeader}}
@onToggle={{@onToggleCollapse}}
as |collapsed|
>
{{#unless collapsed}}
<div class="chat-uploads">
{{#each @uploads as |upload|}}
<ChatUpload @upload={{upload}} />
{{/each}}
</div>
{{/unless}}
<Collapser @header={{this.uploadsHeader}} @onToggle={{@onToggleCollapse}}>
<div class="chat-uploads">
{{#each @uploads as |upload|}}
<ChatUpload @upload={{upload}} />
{{/each}}
</div>
</Collapser>
{{else}}
{{#each this.cookedBodies as |cooked|}}
{{#if cooked.needsCollapser}}
<Collapser
@header={{cooked.header}}
@onToggle={{@onToggleCollapse}}
as |collapsed|
>
{{#unless collapsed}}
{{cooked.body}}
{{/unless}}
<Collapser @header={{cooked.header}} @onToggle={{@onToggleCollapse}}>
{{cooked.body}}
</Collapser>
{{else}}
{{cooked.body}}

View File

@ -384,6 +384,7 @@ $float-height: 530px;
.d-icon {
color: var(--secondary);
margin-left: 1px; // "fixes" the 1px svg shift
}
}

View File

@ -56,7 +56,9 @@
}
.chat-message-separator__text-container {
padding-top: 7px;
align-items: center;
display: flex;
height: 40px;
position: sticky;
top: -1px;
@ -98,11 +100,7 @@
.chat-message-separator__line {
border-top: 1px solid var(--secondary-high);
left: 0;
margin: 0 0 -1px;
position: relative;
right: 0;
top: -1px;
}
}
}

View File

@ -0,0 +1,41 @@
# frozen_string_literal: true
RSpec.describe BookmarksController do
let(:current_user) { Fabricate(:user) }
let(:bookmark_message) { Fabricate(:chat_message) }
let(:bookmark_user) { current_user }
before do
register_test_bookmarkable(Chat::MessageBookmarkable)
sign_in(current_user)
end
after { DiscoursePluginRegistry.reset_register!(:bookmarkables) }
context "when bookmarking a chat message" do
describe "#create" do
it "creates the bookmark" do
post "/bookmarks.json",
params: {
bookmarkable_id: bookmark_message.id,
bookmarkable_type: "Chat::Message",
reminder_at: (Time.zone.now + 1.day).iso8601,
}
expect(response.status).to eq(200)
expect(Bookmark.find_by(bookmarkable: bookmark_message).user_id).to eq(current_user.id)
end
end
describe "#destroy" do
let!(:bookmark) { Fabricate(:bookmark, bookmarkable: bookmark_message, user: bookmark_user) }
it "destroys the bookmark" do
delete "/bookmarks/#{bookmark.id}.json"
expect(response.status).to eq(200)
expect(Bookmark.find_by(id: bookmark.id)).to eq(nil)
end
end
end
end

View File

@ -0,0 +1,39 @@
# frozen_string_literal: true
RSpec.describe "Channel message selection", type: :system, js: true do
fab!(:current_user) { Fabricate(:user) }
fab!(:channel_1) { Fabricate(:chat_channel) }
fab!(:message_1) { Fabricate(:chat_message, chat_channel: channel_1) }
let(:chat) { PageObjects::Pages::Chat.new }
let(:channel) { PageObjects::Pages::ChatChannel.new }
let(:image) do
Fabricate(
:upload,
original_filename: "test_image.jpg",
width: 400,
height: 300,
extension: "jpg",
)
end
before do
chat_system_bootstrap
channel_1.add(current_user)
sign_in(current_user)
message_1.attach_uploads([image])
end
it "can collapse/expand an image and still have lightbox working" do
chat.visit_channel(channel_1)
find(".chat-message-collapser-button").click
expect(page).to have_css(".chat-message-collapser-body.hidden", visible: :false)
find(".chat-message-collapser-button").click
expect(page).to have_no_css(".chat-message-collapser-body.hidden")
find(".chat-img-upload").click
# visible false is because the upload doesnt exist but it's enough to know lightbox is working
expect(page).to have_css(".mfp-image-holder img[src*='#{image.url}']", visible: false)
end
end

View File

@ -70,5 +70,19 @@ RSpec.describe "Shortcuts | chat composer", type: :system, js: true do
expect(page.find(".chat-composer-message-details")).to have_content(message_1.message)
end
context "when last message is not editable" do
after { page.driver.browser.network_conditions = { offline: false } }
it "does not edit a message" do
chat.visit_channel(channel_1)
page.driver.browser.network_conditions = { offline: true }
channel_page.send_message("Hello world")
find(".chat-composer-input").send_keys(:arrow_up)
expect(page).to have_no_css(".chat-composer-message-details")
end
end
end
end