Convert front end paths from `/users/` to `/u/`

This commit is contained in:
Robin Ward 2017-03-28 12:16:58 -04:00
parent 6b976433c9
commit 45a257815a
40 changed files with 129 additions and 84 deletions

View File

@ -1,6 +1,7 @@
import { ajax } from 'discourse/lib/ajax';
import CanCheckEmails from 'discourse/mixins/can-check-emails';
import { propertyNotEqual, setting } from 'discourse/lib/computed';
import { userPath } from 'discourse/lib/url';
export default Ember.Controller.extend(CanCheckEmails, {
editingTitle: false,
@ -62,7 +63,7 @@ export default Ember.Controller.extend(CanCheckEmails, {
saveTitle() {
const self = this;
return ajax(`/users/${this.get('model.username').toLowerCase()}.json`, {
return ajax(userPath(`${this.get('model.username').toLowerCase()}.json`), {
data: {title: this.get('userTitleValue')},
type: 'PUT'
}).catch(function(e) {

View File

@ -1,4 +1,5 @@
import { autoUpdatingRelativeAge } from 'discourse/lib/formatter';
import { userPath } from 'discourse/lib/url';
export function actionDescriptionHtml(actionCode, createdAt, username) {
const dt = new Date(createdAt);
@ -9,7 +10,7 @@ export function actionDescriptionHtml(actionCode, createdAt, username) {
if (actionCode === "invited_group" || actionCode === "removed_group") {
who = `<a class="mention-group" href="/groups/${username}">@${username}</a>`;
} else {
who = `<a class="mention" href="/users/${username}">@${username}</a>`;
who = `<a class="mention" href="${userPath(username)}">@${username}</a>`;
}
}
return I18n.t(`action_codes.${actionCode}`, { who, when }).htmlSafe();

View File

@ -5,6 +5,7 @@ import afterTransition from 'discourse/lib/after-transition';
import { default as computed, observes } from 'ember-addons/ember-computed-decorators';
import DiscourseURL from 'discourse/lib/url';
import User from 'discourse/models/user';
import { userPath } from 'discourse/lib/url';
const clickOutsideEventName = "mousedown.outside-user-card";
const clickDataExpand = "click.discourse-user-card";
@ -92,7 +93,7 @@ export default Ember.Component.extend(CleansUp, {
// Don't show on mobile
if (this.site.mobileView) {
DiscourseURL.routeTo(`/users/${username}`);
DiscourseURL.routeTo(userPath(username));
return false;
}

View File

@ -1,5 +1,5 @@
import { url } from 'discourse/lib/computed';
import computed from 'ember-addons/ember-computed-decorators';
import { userPath } from 'discourse/lib/url';
function normalize(name) {
return name.replace(/[\-\_ \.]/g, '').toLowerCase();
@ -8,7 +8,11 @@ function normalize(name) {
export default Ember.Component.extend({
classNameBindings: [':user-info', 'size'],
size: 'small',
userPath: url('user.username', '/users/%@'),
@computed('user.username')
userPath(username) {
return userPath(username);
},
// TODO: In later ember releases `hasBlock` works without this
hasBlock: Ember.computed.alias('template'),

View File

@ -6,6 +6,7 @@ import { emailValid } from 'discourse/lib/utilities';
import InputValidation from 'discourse/models/input-validation';
import PasswordValidation from "discourse/mixins/password-validation";
import UsernameValidation from "discourse/mixins/username-validation";
import { userPath } from 'discourse/lib/url';
export default Ember.Controller.extend(ModalFunctionality, PasswordValidation, UsernameValidation, {
login: Ember.inject.controller(),
@ -164,7 +165,7 @@ export default Ember.Controller.extend(ModalFunctionality, PasswordValidation, U
@on('init')
fetchConfirmationValue() {
return ajax('/users/hp.json').then(json => {
return ajax(userPath('hp.json')).then(json => {
this.set('accountPasswordConfirm', json.value);
this.set('accountChallenge', json.challenge.split("").reverse().join(""));
});
@ -196,7 +197,7 @@ export default Ember.Controller.extend(ModalFunctionality, PasswordValidation, U
const $hidden_login_form = $('#hidden-login-form');
$hidden_login_form.find('input[name=username]').val(attrs.accountUsername);
$hidden_login_form.find('input[name=password]').val(attrs.accountPassword);
$hidden_login_form.find('input[name=redirect]').val(Discourse.getURL('/users/account-created'));
$hidden_login_form.find('input[name=redirect]').val(userPath('account-created'));
$hidden_login_form.submit();
} else {
self.flash(result.message || I18n.t('create_account.failed'), 'error');

View File

@ -3,6 +3,7 @@ import { queryParams } from 'discourse/controllers/discovery-sortable';
import BulkTopicSelection from 'discourse/mixins/bulk-topic-selection';
import { endWith } from 'discourse/lib/computed';
import showModal from 'discourse/lib/show-modal';
import { userPath } from 'discourse/lib/url';
const controllerOpts = {
discovery: Ember.inject.controller(),
@ -133,14 +134,14 @@ const controllerOpts = {
}.property('allLoaded', 'model.topics.length'),
footerEducation: function() {
if (!this.get('allLoaded') || this.get('model.topics.length') > 0 || !Discourse.User.current()) { return; }
if (!this.get('allLoaded') || this.get('model.topics.length') > 0 || !this.currentUser) { return; }
const split = (this.get('model.filter') || '').split('/');
if (split[0] !== 'new' && split[0] !== 'unread') { return; }
return I18n.t("topics.none.educate." + split[0], {
userPrefsUrl: Discourse.getURL("/users/") + (Discourse.User.currentProp("username_lower")) + "/preferences"
userPrefsUrl: userPath(`${this.currentUser.get('username_lower')}/preferences`)
});
}.property('allLoaded', 'model.topics.length')

View File

@ -1,6 +1,7 @@
import { ajax } from 'discourse/lib/ajax';
import { popupAjaxError } from 'discourse/lib/ajax-error';
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import { userPath } from 'discourse/lib/url';
export default Ember.Controller.extend(ModalFunctionality, {
emailSent: false,
@ -11,7 +12,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
actions: {
sendActivationEmail() {
ajax('/users/action/send_activation_email', {
ajax(userPath('action/send_activation_email'), {
data: { username: this.get('username') },
type: 'POST'
}).then(() => {

View File

@ -3,6 +3,7 @@ import getUrl from 'discourse-common/lib/get-url';
import DiscourseURL from 'discourse/lib/url';
import { ajax } from 'discourse/lib/ajax';
import PasswordValidation from "discourse/mixins/password-validation";
import { userPath } from 'discourse/lib/url';
export default Ember.Controller.extend(PasswordValidation, {
isDeveloper: Ember.computed.alias('model.is_developer'),
@ -27,7 +28,7 @@ export default Ember.Controller.extend(PasswordValidation, {
actions: {
submit() {
ajax({
url: `/users/password-reset/${this.get('model.token')}.json`,
url: userPath(`password-reset/${this.get('model.token')}.json`),
type: 'PUT',
data: {
password: this.get('accountPassword')

View File

@ -1,5 +1,6 @@
import { setting, propertyEqual } from 'discourse/lib/computed';
import DiscourseURL from 'discourse/lib/url';
import { userPath } from 'discourse/lib/url';
export default Ember.Controller.extend({
taken: false,
@ -48,7 +49,7 @@ export default Ember.Controller.extend({
if (result) {
this.set('saving', true);
this.get('content').changeUsername(this.get('newUsername')).then(() => {
DiscourseURL.redirectTo("/users/" + this.get('newUsername').toLowerCase() + "/preferences");
DiscourseURL.redirectTo(userPath(this.get('newUsername').toLowerCase() + "/preferences"));
})
.catch(() => this.set('error', true))
.finally(() => this.set('saving', false));

View File

@ -1,5 +1,6 @@
import { ajax } from 'discourse/lib/ajax';
import computed from 'ember-addons/ember-computed-decorators';
import { userPath } from 'discourse/lib/url';
export default Ember.Controller.extend({
application: Ember.inject.controller(),
@ -18,7 +19,7 @@ export default Ember.Controller.extend({
markFaqRead() {
const currentUser = this.currentUser;
if (currentUser) {
ajax("/users/read-faq", { method: "POST" }).then(() => {
ajax(userPath("read-faq"), { method: "POST" }).then(() => {
currentUser.set('read_faq', true);
});
}

View File

@ -12,6 +12,7 @@ import Post from 'discourse/models/post';
import debounce from 'discourse/lib/debounce';
import isElementInViewport from "discourse/lib/is-element-in-viewport";
import QuoteState from 'discourse/lib/quote-state';
import { userPath } from 'discourse/lib/url';
export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
composer: Ember.inject.controller(),
@ -126,7 +127,7 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
showCategoryChooser: Ember.computed.not("model.isPrivateMessage"),
gotoInbox(name) {
var url = '/users/' + this.get('currentUser.username_lower') + '/messages';
let url = userPath(this.get('currentUser.username_lower') + '/messages');
if (name) {
url = url + '/group/' + name;
}

View File

@ -1,4 +1,5 @@
import { ajax } from 'discourse/lib/ajax';
import { userPath } from 'discourse/lib/url';
function replaceSpan($e, username, opts) {
let extra = "";
@ -15,7 +16,7 @@ function replaceSpan($e, username, opts) {
extra = `data-name='${username}'`;
extraClass = "cannot-see";
}
$e.replaceWith(`<a href='${Discourse.getURL("/users/") + username.toLowerCase()}' class='mention ${extraClass}' ${extra}>@${username}</a>`);
$e.replaceWith(`<a href='${userPath(username.toLowerCase())}' class='mention ${extraClass}' ${extra}>@${username}</a>`);
}
}
@ -54,7 +55,7 @@ export function linkSeenMentions($elem, siteSettings) {
// 'Create a New Topic' scenario is not supported (per conversation with codinghorror)
// https://meta.discourse.org/t/taking-another-1-7-release-task/51986/7
export function fetchUnseenMentions(usernames, topic_id) {
return ajax("/users/is_local_username", { data: { usernames, topic_id } }).then(r => {
return ajax(userPath("is_local_username"), { data: { usernames, topic_id } }).then(r => {
r.valid.forEach(v => found[v] = true);
r.valid_groups.forEach(vg => foundGroups[vg] = true);
r.mentionable_groups.forEach(mg => mentionableGroups[mg.name] = mg);

View File

@ -5,6 +5,7 @@ import { SEPARATOR } from 'discourse/lib/category-hashtags';
import Category from 'discourse/models/category';
import { search as searchCategoryTag } from 'discourse/lib/category-tag-search';
import userSearch from 'discourse/lib/user-search';
import { userPath } from 'discourse/lib/url';
export function translateResults(results, opts) {
@ -29,7 +30,7 @@ export function translateResults(results, opts) {
results.posts = results.posts.map(post => {
if (post.username) {
post.userPath = Discourse.getURL(`/users/${post.username.toLowerCase()}`);
post.userPath = userPath(post.username.toLowerCase());
}
post = Post.create(post);
post.set('topic', topicMap[post.topic_id]);

View File

@ -1,3 +1,5 @@
import { userPath } from 'discourse/lib/url';
function actionDescription(action, acted, count) {
if (acted) {
if (count <= 1) {
@ -39,7 +41,7 @@ export function transformBasicPost(post) {
via_email: post.via_email,
isAutoGenerated: post.is_auto_generated,
user_id: post.user_id,
usernameUrl: Discourse.getURL(`/users/${post.username}`),
usernameUrl: userPath(post.username),
username: post.username,
avatar_template: post.avatar_template,
bookmarked: post.bookmarked,

View File

@ -35,6 +35,10 @@ export function clearRewrites() {
rewrites.length = 0;
}
export function userPath(subPath) {
return Discourse.getURL(subPath ? `/u/${subPath}` : '/u');
}
let _jumpScheduled = false;
export function jumpToElement(elementId) {
if (_jumpScheduled || Ember.isEmpty(elementId)) { return; }
@ -190,7 +194,7 @@ const DiscourseURL = Ember.Object.extend({
if (path.indexOf('/my/') === 0) {
const currentUser = Discourse.User.current();
if (currentUser) {
path = path.replace('/my/', '/users/' + currentUser.get('username_lower') + "/");
path = path.replace('/my/', userPath(currentUser.get('username_lower') + "/"));
} else {
document.location.href = "/404";
return;

View File

@ -1,4 +1,5 @@
import { CANCELLED_STATUS } from 'discourse/lib/autocomplete';
import { userPath } from 'discourse/lib/url';
var cache = {},
cacheTopicId,
@ -14,7 +15,7 @@ function performSearch(term, topicId, includeGroups, includeMentionableGroups, a
}
// need to be able to cancel this
oldSearch = $.ajax(Discourse.getURL('/users/search/users'), {
oldSearch = $.ajax(userPath('search/users'), {
data: { term: term,
topic_id: topicId,
include_groups: includeGroups,

View File

@ -65,10 +65,6 @@ export function postUrl(slug, topicId, postNumber) {
return url;
}
export function userUrl(username) {
return Discourse.getURL("/users/" + username.toLowerCase());
}
export function emailValid(email) {
// see: http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
const re = /^[a-zA-Z0-9!#$%&'*+\/=?\^_`{|}~\-]+(?:\.[a-zA-Z0-9!#$%&'\*+\/=?\^_`{|}~\-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?$/;

View File

@ -17,7 +17,6 @@ const BareRouter = Ember.Router.extend({
url = `${url}?${params[1]}`;
}
}
console.log(url);
return this._super(url);
}
});

View File

@ -1,5 +1,6 @@
import { ajax } from 'discourse/lib/ajax';
import { popupAjaxError } from 'discourse/lib/ajax-error';
import { userPath } from 'discourse/lib/url';
const Invite = Discourse.Model.extend({
@ -41,7 +42,7 @@ Invite.reopenClass({
if (!Em.isNone(search)) { data.search = search; }
data.offset = offset || 0;
return ajax("/users/" + user.get('username_lower') + "/invited.json", {data}).then(function (result) {
return ajax(userPath(user.get('username_lower') + "/invited.json"), {data}).then(function (result) {
result.invites = result.invites.map(function (i) {
return Invite.create(i);
});
@ -52,7 +53,7 @@ Invite.reopenClass({
findInvitedCount(user) {
if (!user) { return Em.RSVP.resolve(); }
return ajax("/users/" + user.get('username_lower') + "/invited_count.json").then(result => Em.Object.create(result.counts));
return ajax(userPath(user.get('username_lower') + "/invited_count.json")).then(result => Em.Object.create(result.counts));
},
reinviteAll() {

View File

@ -2,11 +2,12 @@ import { ajax } from 'discourse/lib/ajax';
import RestModel from 'discourse/models/rest';
import { popupAjaxError } from 'discourse/lib/ajax-error';
import ActionSummary from 'discourse/models/action-summary';
import { url, propertyEqual } from 'discourse/lib/computed';
import { propertyEqual } from 'discourse/lib/computed';
import Quote from 'discourse/lib/quote';
import computed from 'ember-addons/ember-computed-decorators';
import { postUrl } from 'discourse/lib/utilities';
import { cook } from 'discourse/lib/text';
import { userPath } from 'discourse/lib/url';
const Post = RestModel.extend({
@ -60,7 +61,10 @@ const Post = RestModel.extend({
return postNumber === 1 ? baseUrl + "/1" : baseUrl;
},
usernameUrl: url('username', '/users/%@'),
@computed('username')
usernameUrl(username) {
return userPath(username);
},
topicOwner: propertyEqual('topic.details.created_by.id', 'user_id'),

View File

@ -9,6 +9,7 @@ import { popupAjaxError } from 'discourse/lib/ajax-error';
import { censor } from 'pretty-text/censored-words';
import { emojiUnescape } from 'discourse/lib/text';
import PreloadStore from 'preload-store';
import { userPath } from 'discourse/lib/url';
export function loadTopicView(topic, args) {
const topicId = topic.get('id');
@ -182,9 +183,10 @@ const Topic = RestModel.extend({
return this.urlForPostNumber(1) + (this.get('has_summary') ? "?filter=summary" : "");
}.property('url'),
lastPosterUrl: function() {
return Discourse.getURL("/users/") + this.get("last_poster.username");
}.property('last_poster'),
@computed('last_poster.username')
lastPosterUrl(username) {
return userPath(username);
},
// The amount of new posts to display. It might be different than what the server
// tells us if we are still asynchronously flushing our "recently read" data.

View File

@ -1,9 +1,9 @@
import RestModel from 'discourse/models/rest';
import { url } from 'discourse/lib/computed';
import { on } from 'ember-addons/ember-computed-decorators';
import computed from 'ember-addons/ember-computed-decorators';
import UserActionGroup from 'discourse/models/user-action-group';
import { postUrl } from 'discourse/lib/utilities';
import { userPath } from 'discourse/lib/url';
const UserActionTypes = {
likes_given: 1,
@ -79,14 +79,21 @@ const UserAction = RestModel.extend({
presentName: Ember.computed.or('name', 'username'),
targetDisplayName: Ember.computed.or('target_name', 'target_username'),
actingDisplayName: Ember.computed.or('acting_name', 'acting_username'),
targetUserUrl: url('target_username', '/users/%@'),
@computed('target_username')
targetUserUrl(username) {
return userPath(username);
},
@computed("username")
usernameLower(username) {
return username.toLowerCase();
},
userUrl: url('usernameLower', '/users/%@'),
@computed('usernameLower')
userUrl(usernameLower) {
return userPath(usernameLower);
},
@computed()
postUrl() {

View File

@ -15,6 +15,7 @@ import Topic from 'discourse/models/topic';
import { emojiUnescape } from 'discourse/lib/text';
import PreloadStore from 'preload-store';
import { defaultHomepage } from 'discourse/lib/utilities';
import { userPath } from 'discourse/lib/url';
const User = RestModel.extend({
@ -71,7 +72,7 @@ const User = RestModel.extend({
@computed()
path() {
// no need to observe, requires a hard refresh to update
return Discourse.getURL(`/users/${this.get('username_lower')}`);
return userPath(this.get('username_lower'));
},
@computed()
@ -124,11 +125,10 @@ const User = RestModel.extend({
// directly targetted so go to inbox
if (!groups || (allowedUsers && allowedUsers.findBy("id", userId))) {
return Discourse.getURL(`/users/${username}/messages`);
return userPath(`${username}/messages`);
} else {
if (groups && groups[0])
{
return Discourse.getURL(`/users/${username}/messages/group/${groups[0].name}`);
if (groups && groups[0]) {
return userPath(`${username}/messages/group/${groups[0].name}`);
}
}
@ -179,14 +179,14 @@ const User = RestModel.extend({
},
changeUsername(new_username) {
return ajax(`/users/${this.get('username_lower')}/preferences/username`, {
return ajax(userPath(`${this.get('username_lower')}/preferences/username`), {
type: 'PUT',
data: { new_username }
});
},
changeEmail(email) {
return ajax(`/users/${this.get('username_lower')}/preferences/email`, {
return ajax(userPath(`${this.get('username_lower')}/preferences/email`), {
type: 'PUT',
data: { email }
});
@ -254,7 +254,7 @@ const User = RestModel.extend({
// TODO: We can remove this when migrated fully to rest model.
this.set('isSaving', true);
return ajax(`/users/${this.get('username_lower')}.json`, {
return ajax(userPath(`${this.get('username_lower')}.json`), {
data: data,
type: 'PUT'
}).then(result => {
@ -330,7 +330,7 @@ const User = RestModel.extend({
const user = this;
return PreloadStore.getAndRemove(`user_${user.get('username')}`, () => {
return ajax(`/users/${user.get('username')}.json`, { data: options });
return ajax(userPath(`${user.get('username')}.json`), { data: options });
}).then(json => {
if (!Em.isEmpty(json.user.stats)) {
@ -375,13 +375,13 @@ const User = RestModel.extend({
findStaffInfo() {
if (!Discourse.User.currentProp("staff")) { return Ember.RSVP.resolve(null); }
return ajax(`/users/${this.get("username_lower")}/staff-info.json`).then(info => {
return ajax(userPath(`${this.get("username_lower")}/staff-info.json`)).then(info => {
this.setProperties(info);
});
},
pickAvatar(upload_id, type, avatar_template) {
return ajax(`/users/${this.get("username_lower")}/preferences/avatar/pick`, {
return ajax(userPath(`${this.get("username_lower")}/preferences/avatar/pick`), {
type: 'PUT',
data: { upload_id, type }
}).then(() => this.setProperties({
@ -437,7 +437,7 @@ const User = RestModel.extend({
"delete": function() {
if (this.get('can_delete_account')) {
return ajax("/users/" + this.get('username'), {
return ajax(userPath(this.get('username')), {
type: 'DELETE',
data: {context: window.location.pathname}
});
@ -448,14 +448,14 @@ const User = RestModel.extend({
dismissBanner(bannerKey) {
this.set("dismissed_banner_key", bannerKey);
ajax(`/users/${this.get('username')}`, {
ajax(userPath(this.get('username')), {
type: 'PUT',
data: { dismissed_banner_key: bannerKey }
});
},
checkEmail() {
return ajax(`/users/${this.get("username_lower")}/emails.json`, {
return ajax(userPath(`${this.get("username_lower")}/emails.json`), {
data: { context: window.location.pathname }
}).then(result => {
if (result) {
@ -468,7 +468,7 @@ const User = RestModel.extend({
},
summary() {
return ajax(`/users/${this.get("username_lower")}/summary.json`)
return ajax(userPath(`${this.get("username_lower")}/summary.json`))
.then(json => {
const summary = json["user_summary"];
const topicMap = {};
@ -526,7 +526,7 @@ User.reopenClass(Singleton, {
},
checkUsername(username, email, for_user_id) {
return ajax('/users/check_username', {
return ajax(userPath('check_username'), {
data: { username, email, for_user_id }
});
},
@ -557,7 +557,7 @@ User.reopenClass(Singleton, {
},
createAccount(attrs) {
return ajax("/users", {
return ajax(userPath(), {
data: {
name: attrs.accountName,
email: attrs.accountEmail,

View File

@ -7,6 +7,7 @@ import Category from 'discourse/models/category';
import mobile from 'discourse/lib/mobile';
import { findAll } from 'discourse/models/login-method';
import { getOwner } from 'discourse-common/lib/get-owner';
import { userPath } from 'discourse/lib/url';
function unlessReadOnly(method, message) {
return function() {
@ -23,7 +24,7 @@ const ApplicationRoute = Discourse.Route.extend(OpenComposer, {
actions: {
toggleAnonymous() {
ajax("/users/toggle-anon", {method: 'POST'}).then(() => {
ajax(userPath("toggle-anon"), {method: 'POST'}).then(() => {
window.location.reload();
});
},

View File

@ -1,5 +1,6 @@
import PreloadStore from 'preload-store';
import { ajax } from 'discourse/lib/ajax';
import { userPath } from 'discourse/lib/url';
export default Discourse.Route.extend({
titleToken() {
@ -15,7 +16,7 @@ export default Discourse.Route.extend({
afterModel(model) {
// confirm token here so email clients who crawl URLs don't invalidate the link
if (model) {
return ajax({ url: `/users/confirm-email-token/${model.token}.json`, dataType: 'json' });
return ajax({ url: userPath(`confirm-email-token/${model.token}.json`), dataType: 'json' });
}
}
});

View File

@ -3,12 +3,13 @@ import { avatarFor } from 'discourse/widgets/post';
import { iconNode } from 'discourse/helpers/fa-icon-node';
import { h } from 'virtual-dom';
import { dateNode } from 'discourse/helpers/node';
import { userPath } from 'discourse/lib/url';
export function avatarAtts(user) {
return { template: user.avatar_template,
username: user.username,
post_url: user.post_url,
url: Discourse.getURL('/users/') + user.username_lower };
url: userPath(user.username_lower) };
}
createWidget('small-user-list', {

View File

@ -2,6 +2,7 @@ import { createWidget, applyDecorators } from 'discourse/widgets/widget';
import { h } from 'virtual-dom';
import DiscourseURL from 'discourse/lib/url';
import { ajax } from 'discourse/lib/ajax';
import { userPath } from 'discourse/lib/url';
const flatten = array => [].concat.apply([], array);
@ -19,7 +20,7 @@ createWidget('priority-faq-link', {
click(e) {
e.preventDefault();
if (this.siteSettings.faq_url === this.attrs.href) {
ajax("/users/read-faq", { method: "POST" }).then(() => {
ajax(userPath("read-faq"), { method: "POST" }).then(() => {
this.currentUser.set('read_faq', true);
DiscourseURL.routeToTag($(e.target).closest('a')[0]);
});

View File

@ -6,6 +6,7 @@ import { h } from 'virtual-dom';
import { emojiUnescape } from 'discourse/lib/text';
import { postUrl, escapeExpression } from 'discourse/lib/utilities';
import { setTransientHeader } from 'discourse/lib/ajax';
import { userPath } from 'discourse/lib/url';
const LIKED_TYPE = 5;
const INVITED_TYPE = 8;
@ -45,11 +46,11 @@ createWidget('notification-item', {
}
if (attrs.notification_type === INVITED_TYPE) {
return Discourse.getURL('/users/' + data.display_username);
return userPath(data.display_username);
}
if (data.group_id) {
return Discourse.getURL('/users/' + data.username + '/messages/group/' + data.group_name);
return userPath(data.username + '/messages/group/' + data.group_name);
}
},

View File

@ -38,7 +38,7 @@ export function setup(helper) {
const type = mentionLookup && mentionLookup(name);
if (type === "user") {
return ['a', {'class': 'mention', href: opts.getURL("/users/") + name.toLowerCase()}, mention];
return ['a', {'class': 'mention', href: opts.getURL("/u/") + name.toLowerCase()}, mention];
} else if (type === "group") {
return ['a', {'class': 'mention-group', href: opts.getURL("/groups/") + name}, mention];
} else {

View File

@ -124,7 +124,8 @@ class PostAnalyzer
def link_is_a_mention?(l)
html_class = l['class']
return false if html_class.blank?
html_class.to_s['mention'] && l['href'].to_s[/^\/users\//]
href = l['href'].to_s
html_class.to_s['mention'] && href[/^\/u\//] || href[/^\/users\//]
end
end

View File

@ -19,7 +19,7 @@
(function() {
function activateAccount() {
$('#activate-account-button').prop('disabled', true);
$.ajax("<%= path "/users/hp" %>").then(function(hp) {
$.ajax("<%= path "/u/hp" %>").then(function(hp) {
$('#password_confirmation').val(hp.value);
$('#challenge').val(hp.challenge.split("").reverse().join(""));
$('#activate-account-form').submit();

View File

@ -305,6 +305,7 @@ Discourse::Application.routes.draw do
get 'u/check_username' => 'users#check_username'
get 'u/is_local_username' => 'users#is_local_username'
post 'u' => 'users#create'
get "u/hp" => "users#get_honeypot_value"
get "u/admin-login" => "users#admin_login"
put "u/admin-login" => "users#admin_login"
@ -320,7 +321,6 @@ Discourse::Application.routes.draw do
get "u/activate-account/:token" => "users#activate_account"
put "u/activate-account/:token" => "users#perform_account_activation", as: 'perform_activate_account'
get "u/authorize-email/:token" => "users_email#confirm"
get "u/hp" => "users#get_honeypot_value"
get "u/:username/private-messages" => "user_actions#private_messages", constraints: {username: USERNAME_ROUTE_FORMAT}
get "u/:username/private-messages/:filter" => "user_actions#private_messages", constraints: {username: USERNAME_ROUTE_FORMAT}
@ -377,6 +377,7 @@ Discourse::Application.routes.draw do
get 'users/check_username' => 'users#check_username'
get 'users/is_local_username' => 'users#is_local_username'
post 'users' => 'users#create'
get "users/hp" => "users#get_honeypot_value"
get "users/admin-login" => "users#admin_login"
put "users/admin-login" => "users#admin_login"

View File

@ -952,7 +952,7 @@ describe Post do
it "will unhide the post but will keep the topic invisible/unlisted" do
hidden_topic = Fabricate(:topic, visible: false)
first_post = create_post(topic: hidden_topic)
_first_post = create_post(topic: hidden_topic)
second_post = create_post(topic: hidden_topic)
second_post.update_columns(hidden: true, hidden_at: Time.now, hidden_reason_id: 1)

View File

@ -12,11 +12,11 @@ acceptance("Password Reset", {
];
};
server.get('/users/confirm-email-token/myvalidtoken.json', () => { //eslint-disable-line
server.get('/u/confirm-email-token/myvalidtoken.json', () => { //eslint-disable-line
return response({success: "OK"});
});
server.put('/users/password-reset/myvalidtoken.json', request => { //eslint-disable-line
server.put('/u/password-reset/myvalidtoken.json', request => { //eslint-disable-line
const body = parsePostData(request.requestBody);
if (body.password === "jonesyAlienSlayer") {
return response({success: false, errors: {password: ["is the name of your cat"]}});

View File

@ -14,7 +14,7 @@ acceptance("Search - Full Page", {
return response({results: [{text: 'monkey', count: 1}]});
});
server.get('/users/search/users', () => { //eslint-disable-line
server.get('/u/search/users', () => { //eslint-disable-line
return response({users: [{username: "admin", name: "admin",
avatar_template: "/images/avatar.png"}]});
});

File diff suppressed because one or more lines are too long

View File

@ -63,17 +63,17 @@ export default function() {
}] });
});
this.get(`/users/eviltrout/emails.json`, () => {
this.get(`/u/eviltrout/emails.json`, () => {
return response({ email: 'eviltrout@example.com' });
});
this.get('/users/eviltrout.json', () => {
const json = fixturesByUrl['/users/eviltrout.json'];
this.get('/u/eviltrout.json', () => {
const json = fixturesByUrl['/u/eviltrout.json'];
json.user.can_edit = loggedIn();
return response(json);
});
this.get('/users/eviltrout/summary.json', () => {
this.get('/u/eviltrout/summary.json', () => {
return response({
user_summary: {
topics: [],
@ -85,13 +85,13 @@ export default function() {
});
});
this.get('/users/eviltrout/invited_count.json', () => {
this.get('/u/eviltrout/invited_count.json', () => {
return response({
"counts": { "pending": 1, "redeemed": 0, "total": 0 }
});
});
this.get('/users/eviltrout/invited.json', () => {
this.get('/u/eviltrout/invited.json', () => {
return response({ "invites": [ {id: 1} ] });
});
@ -113,7 +113,7 @@ export default function() {
return response({});
});
this.put('/users/eviltrout.json', () => response({ user: {} }));
this.put('/u/eviltrout.json', () => response({ user: {} }));
this.get("/t/280.json", () => response(fixturesByUrl['/t/280/1.json']));
this.get("/t/28830.json", () => response(fixturesByUrl['/t/28830/1.json']));
@ -134,7 +134,7 @@ export default function() {
this.delete('/draft.json', success);
this.post('/draft.json', success);
this.get('/users/:username/staff-info.json', () => response({}));
this.get('/u/:username/staff-info.json', () => response({}));
this.get('/post_action_users', () => {
return response({
@ -198,9 +198,9 @@ export default function() {
return response(400, {error: 'invalid login'});
});
this.post('/users/action/send_activation_email', success);
this.post('/u/action/send_activation_email', success);
this.get('/users/hp.json', function() {
this.get('/u/hp.json', function() {
return response({"value":"32faff1b1ef1ac3","challenge":"61a3de0ccf086fb9604b76e884d75801"});
});
@ -208,14 +208,14 @@ export default function() {
return response({"csrf":"mgk906YLagHo2gOgM1ddYjAN4hQolBdJCqlY6jYzAYs="});
});
this.get('/users/check_username', function(request) {
this.get('/u/check_username', function(request) {
if (request.queryParams.username === 'taken') {
return response({available: false, suggestion: 'nottaken'});
}
return response({available: true});
});
this.post('/users', () => response({success: true}));
this.post('/u', () => response({success: true}));
this.get('/login.html', () => [200, {}, 'LOGIN PAGE']);

View File

@ -227,7 +227,7 @@ test("Mentions", function() {
const alwaysTrue = { mentionLookup: (function() { return "user"; }) };
cookedOptions("Hello @sam", alwaysTrue,
"<p>Hello <a class=\"mention\" href=\"/users/sam\">@sam</a></p>",
"<p>Hello <a class=\"mention\" href=\"/u/sam\">@sam</a></p>",
"translates mentions to links");
cooked("[@codinghorror](https://twitter.com/codinghorror)",
@ -303,11 +303,11 @@ test("Mentions", function() {
"handles mentions separated by a slash.");
cookedOptions("@eviltrout", alwaysTrue,
"<p><a class=\"mention\" href=\"/users/eviltrout\">@eviltrout</a></p>",
"<p><a class=\"mention\" href=\"/u/eviltrout\">@eviltrout</a></p>",
"it doesn't onebox mentions");
cookedOptions("<small>a @sam c</small>", alwaysTrue,
"<p><small>a <a class=\"mention\" href=\"/users/sam\">@sam</a> c</small></p>",
"<p><small>a <a class=\"mention\" href=\"/u/sam\">@sam</a> c</small></p>",
"it allows mentions within HTML tags");
});

View File

@ -1,4 +1,4 @@
import DiscourseURL from 'discourse/lib/url';
import { default as DiscourseURL, userPath } from 'discourse/lib/url';
module("lib:url");
@ -25,3 +25,9 @@ test("isInternal on subfolder install", function() {
not(DiscourseURL.isInternal("http://eviltrout.com/tophat"), "a url on the same host but on a different folder is not internal");
ok(DiscourseURL.isInternal("http://eviltrout.com/forum/moustache"), "a url on the same host and on the same folder is internal");
});
test("userPath", assert => {
assert.equal(userPath(), '/u');
assert.equal(userPath('eviltrout'), '/u/eviltrout');
assert.equal(userPath('hp.json'), '/u/hp.json');
});

View File

@ -10,7 +10,7 @@ module("lib:user-search", {
];
};
server.get('/users/search/users', () => { //eslint-disable-line
server.get('/u/search/users', () => { //eslint-disable-line
return response(
{
users: [