mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 23:27:26 +01:00
Merge pull request #5087 from negue/copyMessageTodo
copy chat messages as todo
This commit is contained in:
@@ -96,5 +96,9 @@
|
|||||||
"abuseReported": "Thank you for reporting this violation. The moderators have been notified.",
|
"abuseReported": "Thank you for reporting this violation. The moderators have been notified.",
|
||||||
"abuseAlreadyReported": "You have already reported this message.",
|
"abuseAlreadyReported": "You have already reported this message.",
|
||||||
"needsText": "Please type a message.",
|
"needsText": "Please type a message.",
|
||||||
"needsTextPlaceholder": "Type your message here."
|
"needsTextPlaceholder": "Type your message here.",
|
||||||
|
"copyMessageAsToDo": "Copy message as To-Do",
|
||||||
|
"messageAddedAsToDo": "Message copied as To-Do.",
|
||||||
|
"messageWroteIn": "<%= user %> wrote in <%= group %>",
|
||||||
|
"msgPreviewHeading": "Message Preview"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,76 @@ describe('Groups Controller', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Chat Controller", function() {
|
||||||
|
var scope, ctrl, user, $rootScope, $controller;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
module(function($provide) {
|
||||||
|
$provide.value('User', {});
|
||||||
|
});
|
||||||
|
|
||||||
|
inject(function(_$rootScope_, _$controller_){
|
||||||
|
user = specHelper.newUser();
|
||||||
|
user._id = "unique-user-id";
|
||||||
|
$rootScope = _$rootScope_;
|
||||||
|
|
||||||
|
scope = _$rootScope_.$new();
|
||||||
|
|
||||||
|
$controller = _$controller_;
|
||||||
|
|
||||||
|
// Load RootCtrl to ensure shared behaviors are loaded
|
||||||
|
$controller('RootCtrl', {$scope: scope, User: {user: user}});
|
||||||
|
|
||||||
|
ctrl = $controller('ChatCtrl', {$scope: scope});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('copyToDo', function() {
|
||||||
|
it('when copying a user message it opens modal with information from message', function() {
|
||||||
|
scope.group = {
|
||||||
|
name: "Princess Bride"
|
||||||
|
};
|
||||||
|
|
||||||
|
var modalSpy = sinon.spy($rootScope, "openModal");
|
||||||
|
var message = {
|
||||||
|
uuid: 'the-dread-pirate-roberts',
|
||||||
|
user: 'Wesley',
|
||||||
|
text: 'As you wish'
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.copyToDo(message);
|
||||||
|
|
||||||
|
modalSpy.should.have.been.calledOnce;
|
||||||
|
|
||||||
|
modalSpy.should.have.been.calledWith('copyChatToDo', sinon.match(function(callArgToMatch){
|
||||||
|
return callArgToMatch.controller == 'CopyMessageModalCtrl'
|
||||||
|
&& callArgToMatch.scope.text == message.text
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('when copying a system message it opens modal with information from message', function() {
|
||||||
|
scope.group = {
|
||||||
|
name: "Princess Bride"
|
||||||
|
};
|
||||||
|
|
||||||
|
var modalSpy = sinon.spy($rootScope, "openModal");
|
||||||
|
var message = {
|
||||||
|
uuid: 'system',
|
||||||
|
text: 'Wesley attacked the ROUS in the Fire Swamp'
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.copyToDo(message);
|
||||||
|
|
||||||
|
modalSpy.should.have.been.calledOnce;
|
||||||
|
|
||||||
|
modalSpy.should.have.been.calledWith('copyChatToDo', sinon.match(function(callArgToMatch){
|
||||||
|
return callArgToMatch.controller == 'CopyMessageModalCtrl'
|
||||||
|
&& callArgToMatch.scope.text == message.text
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("Autocomplete controller", function() {
|
describe("Autocomplete controller", function() {
|
||||||
var scope, ctrl, user, $rootScope, $controller;
|
var scope, ctrl, user, $rootScope, $controller;
|
||||||
|
|
||||||
@@ -172,3 +242,57 @@ describe("Autocomplete controller", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("CopyMessageModal controller", function() {
|
||||||
|
var scope, ctrl, user, Notification, $rootScope, $controller;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
module(function($provide) {
|
||||||
|
$provide.value('User', {});
|
||||||
|
});
|
||||||
|
|
||||||
|
inject(function($rootScope, _$controller_, _Notification_){
|
||||||
|
user = specHelper.newUser();
|
||||||
|
user._id = "unique-user-id";
|
||||||
|
user.ops = {
|
||||||
|
addTask: sinon.spy()
|
||||||
|
};
|
||||||
|
|
||||||
|
scope = $rootScope.$new();
|
||||||
|
scope.$close = sinon.spy();
|
||||||
|
|
||||||
|
$controller = _$controller_;
|
||||||
|
|
||||||
|
// Load RootCtrl to ensure shared behaviors are loaded
|
||||||
|
$controller('RootCtrl', {$scope: scope, User: {user: user}});
|
||||||
|
|
||||||
|
ctrl = $controller('CopyMessageModalCtrl', {$scope: scope, User: {user: user}});
|
||||||
|
|
||||||
|
Notification = _Notification_;
|
||||||
|
Notification.text = sinon.spy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("saveTodo", function() {
|
||||||
|
it('saves todo', function() {
|
||||||
|
|
||||||
|
scope.text = "A Tavern msg";
|
||||||
|
scope.notes = "Some notes";
|
||||||
|
var payload = {
|
||||||
|
body: {
|
||||||
|
text: scope.text,
|
||||||
|
type: 'todo',
|
||||||
|
notes: scope.notes
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.saveTodo();
|
||||||
|
|
||||||
|
user.ops.addTask.should.have.been.calledOnce;
|
||||||
|
user.ops.addTask.should.have.been.calledWith(payload);
|
||||||
|
Notification.text.should.have.been.calledOnce;
|
||||||
|
Notification.text.should.have.been.calledWith(window.env.t('messageAddedAsToDo'));
|
||||||
|
scope.$close.should.have.been.calledOnce;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -187,3 +187,6 @@ a.label
|
|||||||
color: #fff !important
|
color: #fff !important
|
||||||
.line-through
|
.line-through
|
||||||
text-decoration line-through
|
text-decoration line-through
|
||||||
|
|
||||||
|
.markdown-preview markdown code
|
||||||
|
white-space inherit
|
||||||
@@ -142,6 +142,14 @@ for $stage in $stages
|
|||||||
padding: 0
|
padding: 0
|
||||||
font-weight: 300
|
font-weight: 300
|
||||||
|
|
||||||
|
.task-column.preview
|
||||||
|
padding: 0
|
||||||
|
background: transparent
|
||||||
|
border: 0;
|
||||||
|
|
||||||
|
.task:hover
|
||||||
|
cursor: auto
|
||||||
|
|
||||||
// 50% width columns with scrollbars for tablets
|
// 50% width columns with scrollbars for tablets
|
||||||
@media (min-width: 768px) and (max-width: 970px)
|
@media (min-width: 768px) and (max-width: 970px)
|
||||||
.task-column
|
.task-column
|
||||||
|
|||||||
@@ -362,7 +362,25 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
$scope.copyToDo = function(message) {
|
||||||
|
var taskNotes = env.t("messageWroteIn", {
|
||||||
|
user: message.uuid == 'system'
|
||||||
|
? 'system'
|
||||||
|
: '[' + message.user + '](' + env.BASE_URL + '/static/front/#?memberId=' + message.uuid + ')',
|
||||||
|
group: '[' + $scope.group.name + '](' + window.location.href + ')'
|
||||||
|
});
|
||||||
|
|
||||||
|
var newScope = $scope.$new();
|
||||||
|
newScope.text = message.text;
|
||||||
|
newScope.notes = taskNotes;
|
||||||
|
|
||||||
|
$rootScope.openModal('copyChatToDo',{
|
||||||
|
controller:'CopyMessageModalCtrl',
|
||||||
|
scope: newScope
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
$scope.sync = function(group){
|
$scope.sync = function(group){
|
||||||
group.$get();
|
group.$get();
|
||||||
@@ -567,3 +585,20 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
.controller("CopyMessageModalCtrl", ['$scope', 'User', 'Notification',
|
||||||
|
function($scope, User, Notification){
|
||||||
|
$scope.saveTodo = function() {
|
||||||
|
var newTask = {
|
||||||
|
text: $scope.text,
|
||||||
|
type: 'todo',
|
||||||
|
notes: $scope.notes
|
||||||
|
};
|
||||||
|
|
||||||
|
User.user.ops.addTask({body:newTask});
|
||||||
|
Notification.text(window.env.t('messageAddedAsToDo'));
|
||||||
|
|
||||||
|
$scope.$close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ mixin chatMessages(inbox)
|
|||||||
|
|
|
|
||||||
a(ng-click="flagChatMessage(group._id, message)", ng-if=':: user.contributor.admin || (!message.sent && user.flags.communityGuidelinesAccepted && message.uuid != user.id && message.uuid != "system")')
|
a(ng-click="flagChatMessage(group._id, message)", ng-if=':: user.contributor.admin || (!message.sent && user.flags.communityGuidelinesAccepted && message.uuid != user.id && message.uuid != "system")')
|
||||||
span.glyphicon.glyphicon-flag(tooltip="{{message.flags[user._id] ? env.t('abuseAlreadyReported') : env.t('abuseFlag')}}" ng-class='message.flags[user._id] ? "text-danger" : ""')
|
span.glyphicon.glyphicon-flag(tooltip="{{message.flags[user._id] ? env.t('abuseAlreadyReported') : env.t('abuseFlag')}}" ng-class='message.flags[user._id] ? "text-danger" : ""')
|
||||||
|
|
|
||||||
|
a(ng-click="copyToDo(message)")
|
||||||
|
span.glyphicon.glyphicon-share(tooltip=env.t('copyMessageAsToDo'))
|
||||||
span.float-label(ng-class='::contribText(message.contributor, message.backer).length > 30 ? "long-title" : ""')
|
span.float-label(ng-class='::contribText(message.contributor, message.backer).length > 30 ? "long-title" : ""')
|
||||||
a.label.label-default.chat-message(ng-if=':: message.user', ng-class='::userLevelStyleFromLevel(message.contributor.level, message.backer.npc, style)', ng-click='clickMember(message.uuid, true)')
|
a.label.label-default.chat-message(ng-if=':: message.user', ng-class='::userLevelStyleFromLevel(message.contributor.level, message.backer.npc, style)', ng-click='clickMember(message.uuid, true)')
|
||||||
span.glyphicon.glyphicon-arrow-right(ng-if='::message.sent')
|
span.glyphicon.glyphicon-arrow-right(ng-if='::message.sent')
|
||||||
|
|||||||
@@ -113,3 +113,33 @@ script(type='text/ng-template', id='partials/options.social.html')
|
|||||||
.tab-content
|
.tab-content
|
||||||
.tab-pane.active
|
.tab-pane.active
|
||||||
div(ui-view)
|
div(ui-view)
|
||||||
|
|
||||||
|
script(type='text/ng-template', id='modals/copyChatToDo.html')
|
||||||
|
.modal-header
|
||||||
|
h4=env.t('copyMessageAsToDo')
|
||||||
|
.modal-body
|
||||||
|
.form-group
|
||||||
|
input.form-control(type='text',ng-model='text', ng-model-options="{debounce: 1000}")
|
||||||
|
.form-group
|
||||||
|
textarea.form-control(rows='5',ng-model='notes', ng-model-options="{debounce: 1000}", focus-me)
|
||||||
|
|
||||||
|
hr
|
||||||
|
|
||||||
|
div.task-column.preview
|
||||||
|
div(ng-init='popoverOpen = false', class='task todo uncompleted color-neutral', popover-trigger='mouseenter', data-popover-html="{{popoverOpen ? '' : notes | markdown}}", popover-placement="top")
|
||||||
|
// right-hand side control buttons
|
||||||
|
.task-meta-controls
|
||||||
|
// Icons only available if you own the tasks (aka, hidden from challenge stats)
|
||||||
|
span(ng-if='!obj._locked')
|
||||||
|
// notes
|
||||||
|
span.task-notes(ng-show='notes', ng-click='popoverOpen = !popoverOpen', popover-trigger='click', data-popover-html="{{notes | markdown}}", popover-placement="top")
|
||||||
|
span.glyphicon.glyphicon-comment
|
||||||
|
|
|
||||||
|
|
||||||
|
// main content
|
||||||
|
div.task-text
|
||||||
|
markdown(text='text',target='_blank')
|
||||||
|
|
||||||
|
.modal-footer
|
||||||
|
button.btn.btn-default(ng-click='$close()')=env.t('close')
|
||||||
|
button.btn.btn-primary(ng-click='saveTodo()')=env.t('submit')
|
||||||
@@ -11,3 +11,9 @@ mixin aLink(url, label)
|
|||||||
a(href="", ng-click="externalLink('#{url}')")= label
|
a(href="", ng-click="externalLink('#{url}')")= label
|
||||||
else
|
else
|
||||||
a(href='#{url}', target='_blank')= label
|
a(href='#{url}', target='_blank')= label
|
||||||
|
|
||||||
|
mixin previewMarkdown(text)
|
||||||
|
.panel.panel-warning
|
||||||
|
.panel-heading=env.t('msgPreviewHeading')
|
||||||
|
.panel-body.markdown-preview
|
||||||
|
markdown(text='#{text}')
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
li(bindonce='list', id='task-{{::task.id}}', ng-repeat='task in obj[list.type+"s"] | conditionalOrderBy: list.view=="dated":"date"', class='task {{Shared.taskClasses(task, user.filters, user.preferences.dayStart, user.lastCron, list.showCompleted, main)}}', ng-click='spell && (list.type != "reward") && castEnd(task, "task", $event)', ng-class='{"cast-target":spell && (list.type != "reward"), "locked-task":obj._locked === true}', popover-trigger='mouseenter', data-popover-html="{{task.notes | markdown}}", popover-placement="top", popover-append-to-body='{{::modal ? "false":"true"}}', ng-show='shouldShow(task, list, user.preferences)')
|
li(bindonce='list', id='task-{{::task.id}}', ng-repeat='task in obj[list.type+"s"] | conditionalOrderBy: list.view=="dated":"date"', class='task {{Shared.taskClasses(task, user.filters, user.preferences.dayStart, user.lastCron, list.showCompleted, main)}}', ng-click='spell && (list.type != "reward") && castEnd(task, "task", $event)', ng-class='{"cast-target":spell && (list.type != "reward"), "locked-task":obj._locked === true}', popover-trigger='mouseenter', data-popover-html="{{task.popoverOpen ? '' : task.notes | markdown}}", popover-placement="top", popover-append-to-body='{{::modal ? "false":"true"}}', ng-show='shouldShow(task, list, user.preferences)')
|
||||||
// right-hand side control buttons
|
// right-hand side control buttons
|
||||||
.task-meta-controls
|
.task-meta-controls
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ li(bindonce='list', id='task-{{::task.id}}', ng-repeat='task in obj[list.type+"s
|
|||||||
span.glyphicon.glyphicon-signal
|
span.glyphicon.glyphicon-signal
|
||||||
|
|
|
|
||||||
// notes
|
// notes
|
||||||
span.task-notes(ng-show='task.notes && !task._editing')
|
span.task-notes(ng-show='task.notes && !task._editing', ng-click='task.popoverOpen = !task.popoverOpen', popover-trigger='click', data-popover-html="{{task.notes | markdown}}", popover-placement="top", popover-append-to-body='{{::modal ? "false":"true"}}')
|
||||||
span.glyphicon.glyphicon-comment
|
span.glyphicon.glyphicon-comment
|
||||||
|
|
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user