mirror of
https://github.com/discourse/discourse-rewind.git
synced 2025-07-08 14:42:44 +00:00
render rewind in ember
This commit is contained in:
parent
b56070313e
commit
5d165376a1
@ -4,9 +4,4 @@ Display stats on your last year of Discourse usage.
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
- add `http://127.0.0.1:4200/rewinds?` in `SiteSetting.allowed_iframes`
|
Navigate to `/my/activity/rewind`
|
||||||
- example embed of a rewind in a post:
|
|
||||||
|
|
||||||
```
|
|
||||||
<iframe src="http://127.0.0.1:4200/rewinds?year=2024&username=j.jaffeux" width="320" height="500" frameborder="0" style="border:0;" allowfullscreen="" aria-hidden="false" tabindex="0" />
|
|
||||||
```
|
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module ::DiscourseRewind
|
|
||||||
class RewindsAssetsController < ::ApplicationController
|
|
||||||
requires_plugin PLUGIN_NAME
|
|
||||||
|
|
||||||
skip_before_action :preload_json, :check_xhr, only: %i[show]
|
|
||||||
skip_before_action :verify_authenticity_token, only: %i[show]
|
|
||||||
|
|
||||||
def show
|
|
||||||
no_cookies
|
|
||||||
|
|
||||||
name = params[:name]
|
|
||||||
path, content_type =
|
|
||||||
if name == "rewind"
|
|
||||||
%w[rewind.css text/css]
|
|
||||||
else
|
|
||||||
raise Discourse::NotFound
|
|
||||||
end
|
|
||||||
|
|
||||||
content = File.read(DiscourseRewind.public_asset_path("css/#{path}"))
|
|
||||||
|
|
||||||
# note, path contains a ":version" which automatically busts the cache
|
|
||||||
# based on file content, so this is safe
|
|
||||||
response.headers["Last-Modified"] = 10.years.ago.httpdate
|
|
||||||
response.headers["Content-Length"] = content.bytesize.to_s
|
|
||||||
immutable_for 1.year
|
|
||||||
|
|
||||||
render plain: content, disposition: :nil, content_type: content_type
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -4,16 +4,11 @@ module ::DiscourseRewind
|
|||||||
class RewindsController < ::ApplicationController
|
class RewindsController < ::ApplicationController
|
||||||
requires_plugin PLUGIN_NAME
|
requires_plugin PLUGIN_NAME
|
||||||
|
|
||||||
skip_before_action :preload_json, :check_xhr, :redirect_to_login_if_required, only: %i[show]
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
# expires_in 1.minute, public: false
|
|
||||||
response.headers["X-Robots-Tag"] = "noindex"
|
|
||||||
|
|
||||||
DiscourseRewind::Rewind::Fetch.call(service_params) do
|
DiscourseRewind::Rewind::Fetch.call(service_params) do
|
||||||
on_success do |reports:|
|
on_success do |reports:|
|
||||||
@reports = reports
|
@reports = reports
|
||||||
render "show", layout: false
|
render json: MultiJson.dump(reports), status: 200
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module DiscourseRewind
|
|
||||||
module RewindsHelper
|
|
||||||
# keeping it here for caching
|
|
||||||
def self.rewind_asset_url(asset_name)
|
|
||||||
if !%w[rewind.css].include?(asset_name)
|
|
||||||
raise StandardError, "unknown asset type #{asset_name}"
|
|
||||||
end
|
|
||||||
|
|
||||||
@urls ||= {}
|
|
||||||
url = @urls[asset_name]
|
|
||||||
return url if url
|
|
||||||
|
|
||||||
content = File.read(DiscourseRewind.public_asset_path("css/#{asset_name}"))
|
|
||||||
sha1 = Digest::SHA1.hexdigest(content)
|
|
||||||
url = "/rewinds/assets/#{sha1}/#{asset_name}"
|
|
||||||
@urls[asset_name] = GlobalPath.cdn_path(url)
|
|
||||||
end
|
|
||||||
|
|
||||||
def rewind_asset_url(asset_name)
|
|
||||||
DiscourseRewind::RewindsHelper.rewind_asset_url(asset_name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -5,11 +5,7 @@ module DiscourseRewind
|
|||||||
#
|
#
|
||||||
# @example
|
# @example
|
||||||
# ::DiscourseRewind::Rewind::Fetch.call(
|
# ::DiscourseRewind::Rewind::Fetch.call(
|
||||||
# guardian: guardian,
|
# guardian: guardian
|
||||||
# params: {
|
|
||||||
# username: "falco",
|
|
||||||
# year: 2024,
|
|
||||||
# }
|
|
||||||
# )
|
# )
|
||||||
#
|
#
|
||||||
class Rewind::Fetch
|
class Rewind::Fetch
|
||||||
@ -30,34 +26,26 @@ module DiscourseRewind
|
|||||||
|
|
||||||
CACHE_DURATION = 5.minutes
|
CACHE_DURATION = 5.minutes
|
||||||
|
|
||||||
params do
|
|
||||||
attribute :year, :integer
|
|
||||||
attribute :username, :string
|
|
||||||
|
|
||||||
validates :year, presence: true
|
|
||||||
validates :username, presence: true
|
|
||||||
end
|
|
||||||
|
|
||||||
model :user
|
model :user
|
||||||
model :date
|
model :date
|
||||||
model :reports
|
model :reports
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def fetch_user(params:)
|
def fetch_user(guardian:)
|
||||||
User.find_by_username(params.username)
|
User.find_by_username(guardian.user.username)
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_date(params:)
|
def fetch_date(params:)
|
||||||
Date.new(params.year).all_year
|
Date.new(2024).all_year
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_reports(params:, date:, user:, guardian:)
|
def fetch_reports(date:, user:, guardian:)
|
||||||
key = "rewind:#{params.username}:#{params.year}"
|
key = "rewind:#{guardian.user.username}:#{2024}"
|
||||||
reports = Discourse.redis.get(key)
|
reports = Discourse.redis.get(key)
|
||||||
|
|
||||||
if Rails.env.development? || !reports
|
if Rails.env.development? || !reports
|
||||||
reports = REPORTS.map { |report| report.call(params:, date:, user:, guardian:) }
|
reports = REPORTS.map { |report| report.call(date:, user:, guardian:) }
|
||||||
Discourse.redis.setex(key, CACHE_DURATION, MultiJson.dump(reports))
|
Discourse.redis.setex(key, CACHE_DURATION, MultiJson.dump(reports))
|
||||||
else
|
else
|
||||||
reports = MultiJson.load(reports, symbolize_keys: true)
|
reports = MultiJson.load(reports, symbolize_keys: true)
|
||||||
|
@ -1 +0,0 @@
|
|||||||
POSTING CALENDAR
|
|
@ -1 +0,0 @@
|
|||||||
READING TIME
|
|
@ -1,24 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title><%= I18n.t("discourse_rewind.title", title: "RETRO TITLE", site_name: SiteSetting.title) %></title>
|
|
||||||
<meta property="og:title" content="<%= I18n.t("discourse_rewind.title", title: "RETRO TITLE", site_name: SiteSetting.title) %>">
|
|
||||||
<meta property="og:description" content="DESC">
|
|
||||||
<meta property="og:type" content="website">
|
|
||||||
<meta property="og:url" content="<%= request.original_url %>">
|
|
||||||
<meta name="twitter:card" content="summary">
|
|
||||||
<meta name="twitter:title" content="<%= I18n.t("discourse_rewind.title", title: "RETRO TITLE", site_name: SiteSetting.title) %>">
|
|
||||||
<meta name="twitter:description" content="DESC">
|
|
||||||
<meta name="viewport" content="width=device-width">
|
|
||||||
<link rel="stylesheet" href="<%= rewind_asset_url("rewind.css") %>">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="rewind__wrapper">
|
|
||||||
<div class="rewind">
|
|
||||||
<%- @reports.each do |report| %>
|
|
||||||
<%= render report[:identifier] %>
|
|
||||||
<%- end %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
27
assets/javascripts/discourse/components/rewind.gjs
Normal file
27
assets/javascripts/discourse/components/rewind.gjs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import Component from "@glimmer/component";
|
||||||
|
import { tracked } from "@glimmer/tracking";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
|
||||||
|
import { ajax } from "discourse/lib/ajax";
|
||||||
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
|
|
||||||
|
export default class Rewind extends Component {
|
||||||
|
@tracked rewind = [];
|
||||||
|
|
||||||
|
@action
|
||||||
|
async loadRewind() {
|
||||||
|
try {
|
||||||
|
this.rewind = await ajax("/rewinds");
|
||||||
|
} catch (e) {
|
||||||
|
popupAjaxError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="rewind" {{didInsert this.loadRewind}}>
|
||||||
|
{{#each this.rewind as |report|}}
|
||||||
|
<p>{{report.identifier}}</p>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
import Component from "@glimmer/component";
|
||||||
|
import DNavigationItem from "discourse/components/d-navigation-item";
|
||||||
|
import icon from "discourse-common/helpers/d-icon";
|
||||||
|
import { i18n } from "discourse-i18n";
|
||||||
|
|
||||||
|
export default class RewindTab extends Component {
|
||||||
|
<template>
|
||||||
|
<DNavigationItem
|
||||||
|
@route="userActivity.rewind"
|
||||||
|
@ariaCurrentContext="subNav"
|
||||||
|
class="user-nav__activity-rewind"
|
||||||
|
>
|
||||||
|
{{icon "repeat"}}
|
||||||
|
<span>{{i18n "rewind.title"}}</span>
|
||||||
|
</DNavigationItem>
|
||||||
|
</template>
|
||||||
|
}
|
11
assets/javascripts/discourse/rewind-route-map.js
Normal file
11
assets/javascripts/discourse/rewind-route-map.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export default function () {
|
||||||
|
this.route(
|
||||||
|
"user",
|
||||||
|
{ path: "/u/:username", resetNamespace: true },
|
||||||
|
function () {
|
||||||
|
this.route("userActivity", function () {
|
||||||
|
this.route("rewind");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
|
|
||||||
|
export default class UserActivityRewind extends DiscourseRoute {
|
||||||
|
templateName = "user/rewind";
|
||||||
|
}
|
1
assets/javascripts/discourse/templates/user/rewind.hbs
Normal file
1
assets/javascripts/discourse/templates/user/rewind.hbs
Normal file
@ -0,0 +1 @@
|
|||||||
|
<Rewind />
|
1
assets/stylesheets/common/index.scss
Normal file
1
assets/stylesheets/common/index.scss
Normal file
@ -0,0 +1 @@
|
|||||||
|
@import "rewind";
|
6
assets/stylesheets/common/rewind.scss
Normal file
6
assets/stylesheets/common/rewind.scss
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.rewind {
|
||||||
|
width: 280px;
|
||||||
|
height: 400px;
|
||||||
|
background-color: var(--secondary-high);
|
||||||
|
border-radius: var(--d-border-radius);
|
||||||
|
}
|
0
assets/stylesheets/desktop/index.scss
Normal file
0
assets/stylesheets/desktop/index.scss
Normal file
0
assets/stylesheets/mobile/index.scss
Normal file
0
assets/stylesheets/mobile/index.scss
Normal file
@ -1,8 +1,5 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
DiscourseRewind::Engine.routes.draw do
|
DiscourseRewind::Engine.routes.draw { get "/rewinds" => "rewinds#show" }
|
||||||
get "/rewinds" => "rewinds#show"
|
|
||||||
get "/rewinds/assets/:version/:name" => "rewinds_assets#show"
|
|
||||||
end
|
|
||||||
|
|
||||||
Discourse::Application.routes.draw { mount ::DiscourseRewind::Engine, at: "/" }
|
Discourse::Application.routes.draw { mount ::DiscourseRewind::Engine, at: "/" }
|
||||||
|
@ -10,6 +10,12 @@
|
|||||||
|
|
||||||
enabled_site_setting :discourse_rewind_enabled
|
enabled_site_setting :discourse_rewind_enabled
|
||||||
|
|
||||||
|
register_svg_icon "repeat"
|
||||||
|
|
||||||
|
register_asset "stylesheets/common/index.scss"
|
||||||
|
register_asset "stylesheets/desktop/index.scss", :desktop
|
||||||
|
register_asset "stylesheets/mobile/index.scss", :mobile
|
||||||
|
|
||||||
module ::DiscourseRewind
|
module ::DiscourseRewind
|
||||||
PLUGIN_NAME = "discourse-rewind"
|
PLUGIN_NAME = "discourse-rewind"
|
||||||
|
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
/* RESET CSS */
|
|
||||||
*, *::before, *::after { box-sizing: border-box; }
|
|
||||||
* { margin: 0; padding: 0; }
|
|
||||||
ul[role='list'], ol[role='list'] { list-style: none; }
|
|
||||||
html:focus-within { scroll-behavior: smooth; }
|
|
||||||
a:not([class]) { text-decoration-skip-ink: auto; }
|
|
||||||
input, button, textarea, select { font: inherit; }
|
|
||||||
body, html { height: 100%; scroll-behavior: smooth; }
|
|
||||||
/* END RESET CSS */
|
|
||||||
|
|
||||||
.rewind {
|
|
||||||
display: flex;
|
|
||||||
height: 100vh;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user