discourse/app/assets/javascripts/admin/addon/components/dashboard-new-features.gjs
Martin Brennan 2ef9d6ac47
FEATURE: Allow admins to force refresh "What's new?" (#29911)
Sometimes changes to "What's new?" feed items are made or the feed items are
removed altogether, and the polling interval to check for new features is 1 day.

This is quite long, so this commit introduces a "Check for updates"
button for admins to click on the "What's new?" page which will bust
the cache for the feed and check again at the new features endpoint.
This is limited to 5 times per minute to avoid rapid sending of
requests.
2024-11-27 09:40:55 +10:00

88 lines
2.8 KiB
Plaintext

import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
import { service } from "@ember/service";
import { htmlSafe } from "@ember/template";
import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { bind } from "discourse-common/utils/decorators";
import { i18n } from "discourse-i18n";
import AdminConfigAreaCard from "admin/components/admin-config-area-card";
import AdminConfigAreaEmptyList from "admin/components/admin-config-area-empty-list";
import DashboardNewFeatureItem from "admin/components/dashboard-new-feature-item";
export default class DashboardNewFeatures extends Component {
@service currentUser;
@tracked newFeatures = null;
@tracked groupedNewFeatures = null;
@tracked isLoading = true;
constructor() {
super(...arguments);
this.args.onCheckForFeatures(this.loadNewFeatures);
}
@bind
async loadNewFeatures(opts = {}) {
opts.forceRefresh ||= false;
this.isLoading = true;
try {
const json = await ajax(
"/admin/whats-new.json?force_refresh=" + opts.forceRefresh
);
const items = json.new_features.reduce((acc, feature) => {
const key = moment(feature.released_at || feature.created_at).format(
"YYYY-MM"
);
acc[key] = acc[key] || [];
acc[key].push(feature);
return acc;
}, {});
this.groupedNewFeatures = Object.keys(items).map((date) => {
return {
date: moment
.tz(date, this.currentUser.user_option.timezone)
.format("MMMM YYYY"),
features: items[date],
};
});
} catch (err) {
popupAjaxError(err);
} finally {
this.isLoading = false;
}
}
<template>
<div
class="admin-config-area__primary-content"
{{didInsert this.loadNewFeatures}}
>
<ConditionalLoadingSpinner @condition={{this.isLoading}}>
{{#each this.groupedNewFeatures as |groupedFeatures|}}
<AdminConfigAreaCard @translatedHeading={{groupedFeatures.date}}>
<:content>
{{#each groupedFeatures.features as |feature|}}
<DashboardNewFeatureItem @item={{feature}} />
{{/each}}
</:content>
</AdminConfigAreaCard>
{{else}}
<AdminConfigAreaEmptyList
@emptyLabel={{htmlSafe
(i18n
"admin.dashboard.new_features.previous_announcements"
url="https://meta.discourse.org/tags/c/announcements/67/release-notes"
)
}}
/>
{{/each}}
</ConditionalLoadingSpinner>
</div>
</template>
}