* add drafts.json endpoint, user profile tab with drafts stream * improve drafts stream display in user profile * truncate excerpts in drafts list, better handling for resume draft action * improve draft stream SQL query, add rspec tests * if composer is open, quietly close it when user opens another draft from drafts stream; load PM draft only when user is in /u/username/messages (instead of /u/username) * cleanup * linting fixes * apply prettier styling to modified files * add client tests for drafts, includes a fixture for drafts.json * improvements to code following review * refresh drafts route when user deletes a draft open in the composer while being in the drafts route; minor prettier scss fix * added more spec tests, deleted an acceptance test for removing drafts that was too finicky, formatting and code style fixes, added appEvent for draft:destroyed * prettier, eslint fixes * use "username_lower" from users table, added error handling for rejected promises * adds guardian spec for can_see_drafts, adds improvements following code review * move DraftsController spec to its own file * fix failing drafts qunit test, use getOwner instead of deprecated this.container * limit test fixture for draft.json testing to new_topic request only
106 lines
2.7 KiB
JavaScript
106 lines
2.7 KiB
JavaScript
import { ajax } from "discourse/lib/ajax";
|
|
import { url } from "discourse/lib/computed";
|
|
import RestModel from "discourse/models/rest";
|
|
import UserDraft from "discourse/models/user-draft";
|
|
import { emojiUnescape } from "discourse/lib/text";
|
|
import computed from "ember-addons/ember-computed-decorators";
|
|
|
|
import {
|
|
NEW_TOPIC_KEY,
|
|
NEW_PRIVATE_MESSAGE_KEY
|
|
} from "discourse/models/composer";
|
|
|
|
export default RestModel.extend({
|
|
loaded: false,
|
|
|
|
init() {
|
|
this._super();
|
|
this.setProperties({
|
|
itemsLoaded: 0,
|
|
content: [],
|
|
lastLoadedUrl: null
|
|
});
|
|
},
|
|
|
|
baseUrl: url(
|
|
"itemsLoaded",
|
|
"user.username_lower",
|
|
"/drafts.json?offset=%@&username=%@"
|
|
),
|
|
|
|
load(site) {
|
|
this.setProperties({
|
|
itemsLoaded: 0,
|
|
content: [],
|
|
lastLoadedUrl: null,
|
|
site: site
|
|
});
|
|
return this.findItems();
|
|
},
|
|
|
|
@computed("content.length", "loaded")
|
|
noContent(contentLength, loaded) {
|
|
return loaded && contentLength === 0;
|
|
},
|
|
|
|
remove(draft) {
|
|
let content = this.get("content").filter(
|
|
item => item.sequence !== draft.sequence
|
|
);
|
|
this.setProperties({ content, itemsLoaded: content.length });
|
|
},
|
|
|
|
findItems() {
|
|
let findUrl = this.get("baseUrl");
|
|
|
|
const lastLoadedUrl = this.get("lastLoadedUrl");
|
|
if (lastLoadedUrl === findUrl) {
|
|
return Ember.RSVP.resolve();
|
|
}
|
|
|
|
if (this.get("loading")) {
|
|
return Ember.RSVP.resolve();
|
|
}
|
|
|
|
this.set("loading", true);
|
|
|
|
return ajax(findUrl, { cache: "false" })
|
|
.then(result => {
|
|
if (result && result.no_results_help) {
|
|
this.set("noContentHelp", result.no_results_help);
|
|
}
|
|
if (result && result.drafts) {
|
|
const copy = Em.A();
|
|
result.drafts.forEach(draft => {
|
|
let draftData = JSON.parse(draft.data);
|
|
draft.post_number = draftData.postId || null;
|
|
if (
|
|
draft.draft_key === NEW_PRIVATE_MESSAGE_KEY ||
|
|
draft.draft_key === NEW_TOPIC_KEY
|
|
) {
|
|
draft.title = draftData.title;
|
|
}
|
|
draft.title = emojiUnescape(
|
|
Handlebars.Utils.escapeExpression(draft.title)
|
|
);
|
|
if (draft.category_id) {
|
|
draft.category =
|
|
this.site.categories.findBy("id", draft.category_id) || null;
|
|
}
|
|
|
|
copy.pushObject(UserDraft.create(draft));
|
|
});
|
|
this.get("content").pushObjects(copy);
|
|
this.setProperties({
|
|
loaded: true,
|
|
itemsLoaded: this.get("itemsLoaded") + result.drafts.length
|
|
});
|
|
}
|
|
})
|
|
.finally(() => {
|
|
this.set("loading", false);
|
|
this.set("lastLoadedUrl", findUrl);
|
|
});
|
|
}
|
|
});
|