test plan:
* get some notifications for discussions, conversations, etc.
* delete the root account
* reply to the notifications via e-mail
* undelete the root account
* the replies should not show up
Change-Id: I2afe5de256cbd55ca360a4327150871ea40d7493
Reviewed-on: https://gerrit.instructure.com/12902
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Jon Jensen <jon@instructure.com>
Test plan:
(We need two users here because Canvas doesn't notify you about
files you upload yourself. We'll call them Student and Teacher
here, but they don't actually have to be these things.)
* As Student, enable notifications for new files in Profile.
* As Teacher, upload a file.
* Within an hour or so (everything about notifications occurs
in low-priority background tasks), Student should receive
a notification for the file.
* As Teacher, upload multiple files.
* Student should eventually receive a notification that
X number of files were added.
Note that files are batched over a five-minute period; that is,
if a file is added to a course within five minutes of a previous
file, it will be counted in the same batch.
Change-Id: I09b5f497cae1d726b7aaf85824e98e69e45b0c1b
Reviewed-on: https://gerrit.instructure.com/12346
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Simon Williams <simon@instructure.com>
In a group graded discussion assignment, when creating the child topics for
each group, the new discussion topics were touching their root topics, kicking
off a new job to refresh the subtopics. This created a race condition where
duplicate subtopics for the group could get created, in addition to a lot of
unnecessary jobs. This commit moves the touch to only happen when an entry in
a subtopic is updated, tightens up some conditions in the way soft-destroys
cascade between assignment and discussion, and adds a unique index on
context+root_topic to prevent this from happening in the future.
test plan:
- ensure that creating a group discussion assignment still creates all
necessary sub-topics for the groups
- in a course with many student groups, create a new group discussion
assignment.
- each group should only have one unique topic for this assignment
- delete a group discussion assignment, it should delete all associated topics
at the course and group levels
- also try initiating the delete from the root topic. the assignment and sub
topics should be deleted
Change-Id: I9b0fb79c2c2b3b9512802a781b8ea0f4364af541
Reviewed-on: https://gerrit.instructure.com/11712
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Brian Palmer <brianp@instructure.com>
To allow commenting on CollectionItems, we are goign to leverage
DiscussionTopics. The topic will not be created until the first comment is
made, and is accessed via the normal DiscussionTopic API (using a special
endpoint).
This also adds a new "flat" DiscussionTopic type, which doesn't support any
nesting of replies.
test plan:
* Create a collection and an item in that collection (via console or API)
* Using the API, query the discussion topic for that item via the API
* Using the APi, add a comment to that discussion topic
* Using the API, fetch the discussion again and see that your comment appears
Change-Id: Ie7cc27a7bc1d7960040632015971e59f084d7e6f
Reviewed-on: https://gerrit.instructure.com/10960
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Brian Palmer <brianp@instructure.com>
* add the foreigner gem so plugins can begin adding foreign keys
immediately
* add an extension to do less locking when creating foreign keys
on postgres 9.1+
* fix a few pieces of code that either don't properly clean up
foreign dependencies, or create objects in the wrong order
to maintain referential integrity
* change the specs to truncate all tables in a single command
for postgres (to avoid referential integrity errors; also
slightly faster)
test plan:
* no user visible functionality should change
Change-Id: I185e478b99fbe598d408912053c34a064aa9c461
Reviewed-on: https://gerrit.instructure.com/10580
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Brian Palmer <brianp@instructure.com>
also removed obsolete/broken spec (superseded by newer spec/migration) and
removed unused :dependent => :destroy from model (we never actually
destroy, so it wasn't getting called. also we want those records to stick
around)
test plan:
* run specs
Change-Id: I5a3e101cd4c26200003650543a89c16f99361b77
Reviewed-on: https://gerrit.instructure.com/10336
Reviewed-by: Cody Cutrer <cody@instructure.com>
Tested-by: Hudson <hudson@instructure.com>
named_context_url wasn't always giving back absolute urls where it needed to
for atom feeds. additionally, some atom entries did not author entries which
are needed when the main feed does not have an author entry.
test-plan:
- view a modified atom feed in the browser and make sure all links are absolute
and all entries have an author.
- if the url is externally available, run it through http://feedvalidator.org/
and check that it validates.
Change-Id: I9bc2b99cd15ed5677bfd9d2cb977a29568ae4016
Reviewed-on: https://gerrit.instructure.com/9833
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
Fixes a race condition where the view might get generated by the job
without the new entry.
test plan: this is difficult to duplicate by hand, but you could put a
breakpoint in and verify the job doesn't get inserted before the
transaction commits.
Change-Id: I6c373553dfae409adab25dd9e3bafc7126169231
Reviewed-on: https://gerrit.instructure.com/9710
Reviewed-by: Brian Palmer <brianp@instructure.com>
Tested-by: Hudson <hudson@instructure.com>
test plan:
* Create an entry in a discussion, and make some side comments on it
* Delete the first entry
* Verify that the side comments were not deleted as well.
Change-Id: I1eea75877e39f2df56fa4e0013c5bd1649407359
Reviewed-on: https://gerrit.instructure.com/9656
Reviewed-by: Brian Whitmer <brian@instructure.com>
Tested-by: Hudson <hudson@instructure.com>
* faster discussion loading, uses materialized view
* threaded discussion support
* navigate between unread messages
test plan:
* use every feature within discussions
Change-Id: I9e89028e5a618c36a57dae958a16b0be73c35baa
Reviewed-on: https://gerrit.instructure.com/9584
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Jon Jensen <jon@instructure.com>
This is a cached-in-the-db view of the topic view json response, and
serialized arrays of participant ids and entry ids (for determining
unread entries). This is an optimization to make loading topics fast and
avoid a lot of db traffic.
test plan:
The UI for this new API is still under development, so this needs to
be tested via the API. With jobs turned off, hit the discussion view
endpoint and verify the 503 response. Then run the job to generate the
view, and verify the response json. Verify that any change to the
discussion that requires updating the view, properly updates the view.
Change-Id: I1eacace438a75a41b8b85ce6c42bfd042f27d1ea
Reviewed-on: https://gerrit.instructure.com/9443
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Jon Jensen <jon@instructure.com>
This is a specialized, optimized view of the entire discussion,
including a nested view on all the entries and participants, and the
current user's unread entry list.
An upcoming commit will cache these views to the database, and generate
them asynchronously, rather than in-request.
test plan: No UI yet. GET /api/v1/courses/X/discussion_topics/Y/view ,
and verify the formatting of the response, including the nesting of
arbitrarily nested discussion entires (also only creatable via the api,
right now). verify that deleted entries are returned, but without a
user_id or summary and with a deleted flag.
Change-Id: Ib7332743f92cca40cc2a861973bf492b1f294a02
Reviewed-on: https://gerrit.instructure.com/9305
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Simon Williams <simon@instructure.com>
fixes#7790fixes#6273
we weren't properly checking the workflow state when deciding whether or not
to create a new submission for discussion assignment posts. also, we were
ensuring that a submission exists for the entry every time the topic was
updated, which is more often than necessary.
test-plan:
- create a discussion assignment
- as a user, post an entry
- as a teacher, grade the assignment
- do something that would update the topic
- make sure a new submission isn't created and that the status is speedgrader
is still graded.
Change-Id: Ic2d0fc5d809695cf856b2902bd8b478fe3bf6934
Reviewed-on: https://gerrit.instructure.com/9543
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Zach Wily <zach@instructure.com>
If a discussion topic is threaded, it'll allow sub-entries to have other
sub-entries as parents. otherwise it'll force sub-entries to always have
a root entry as a parent (restoring the behavior pre-e9edb2a86f
test plan:
Make a side comment in reply to another side comment, reload the page,
and verify it shows your comment. Do the same via the API. There's no UI
yet for marking a discussion as threaded, but you can do it from the
console and then verify that replies to replies are now nested.
Change-Id: I6bddcfa318f36bcbc6ddb03c152ff1fa8fa550b8
Reviewed-on: https://gerrit.instructure.com/9506
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Simon Williams <simon@instructure.com>
We need to lock this to serialize updates of the count, so they don't get off
due to race conditions. We also have to make sure the AR query cache is
disabled when using the unique_constraint_retry. If it's not, then on the
retry we might just get the results from the first query out of the cache.
It's possible that that might be generally applicable to all
unique_constraint_retry usage, but it hasn't been thought through yet.
test plan:
* in a production-like environment:
* create a discussion topic, and some short entries on it (at least 3)
* load that topic with a tall window as a lot of different users
* verify that the visible posts get marked as read, and on reload, the
unread count stays correct.
Change-Id: I3e0cbebe991bbaaf74f4c8408cbe2214fca80eec
Reviewed-on: https://gerrit.instructure.com/9469
Reviewed-by: Simon Williams <simon@instructure.com>
Tested-by: Hudson <hudson@instructure.com>
we were including deleted discussion entries in our default unread counts, but
there was no way to mark these as read from the UI so it looked like the counts
were just off.
test-plan:
- run the migration and make sure existing unread counts look good
- create a discussion, make some entries, and delete some
- as a different user, view that discussion and make sure counts look right
Change-Id: I601fc7e0726a7982a2843b5a8a71cf782e5092eb
Reviewed-on: https://gerrit.instructure.com/9468
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Zach Wily <zach@instructure.com>
A race condition could cause this method to be called twice nearly in
parallel, meaning both processes would try to create the participant. The
second would fail due to the unique constraint. This catches the unique
constraint violation and retries, which means it will find the already created
one and do an update. (This is what we're opting to do instead of some global
locking for inserting discussion participants - it's optimistic locking.)
test plan:
* this will only work in an environment where multiple rails processes are
running. meaning: not development mode with webrick. :)
* create a discussion topic and add a couple short replies.
* make sure your window is tall enough to show both replies at the same time
* log in as another user in that course and go to that discussion
* verify that you don't get an ajax error, and unread counts get updated
correctly
Change-Id: I35f6119cabaef890a228c570799b7b3c88bf3f74
Reviewed-on: https://gerrit.instructure.com/9467
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Zach Wily <zach@instructure.com>
Adds support for threaded discussions. The existing API has been updated
to allow posting replies to replies, and returns the whole thread of
sub-replies rather than just first-level side comments. For backwards
compatbility, the sub-replies are returned in a flattened newest-first,
consumers can look at the parent id of each entry to re-build the
nested, threaded structure.
Another commit will add a new API endpoint for retriving the threaded
structure of the conversation in a more efficient and natural format.
test plan: there's no UI for threaded discussions yet, but you can use
the API to post replies to replies, and retrieve threads and verify the
parent_id information.
Change-Id: I7d541d093fbbdb6fc8a18d079b4337515c02a8a4
Reviewed-on: https://gerrit.instructure.com/9121
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Simon Williams <simon@instructure.com>
fixes#7319fixes#7015
if a user deleted a discussion entry an then re submitted one
it would take the date of the original entry
if a teacher made a comment on a no submission and then the
student submitted the entry it would take the date of the comment
test plan
* create a discussion topic assignment
* submit two entries as student
* delete one
* the date should equal the oldest existing submission
* create a discussion topic assignment
* make a comment on a students non existent submission
* submit the assignment as the student
* the submission submitted_at should be the real submission date
Change-Id: I09b643eba575a9d84f3903ab6eefaf52b7801bb1
Reviewed-on: https://gerrit.instructure.com/9070
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Simon Williams <simon@instructure.com>
also move notifications in "new email messages" to "administrative alerts",
because that's a much better description of them
test plan:
* go to communication preferences
* the last one should be "administrative alerts"
* "Files", "Private message from student", "New email messages",
and "Context Message" should be nowhere to be found
Change-Id: I8b30d53b8137ab4b17cb436920d87331327e01f9
Reviewed-on: https://gerrit.instructure.com/8996
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Simon Williams <simon@instructure.com>
the backend for tracking read/unread state of discussion entries/topics and
unread counts for discussion topics. the strategy is to assume that an entry is
unread unless there is an an entry in the join table indicating otherwise.
interface:
- DiscussionEntry has #read_state, #read?, and #unread?. You can use these
either by passing in a user directly, or by setting the current_user
attribute on the object before calling the method (useful for json). This
should already be handled for existing controllers.
- DiscussionTopic read_state functionality as above, plus #unread_count. Same
general idea with current_user as above.
- routes are setup through the api, use PUT to mark read, DELETE to mark
unread, or rails helpers like course_discussion_topic_mark_read_path
test plan:
- click through discussion pages, and make sure they all still work (no visible
changes though, this is backend only)
- manually call some of the above methods from the console
- make sure sql for updates is reasonable
Change-Id: I655ab6a69a8cbdf1c7c99a5548b8ed0d7eadba02
Reviewed-on: https://gerrit.instructure.com/8671
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Jon Jensen <jon@instructure.com>
we were already touching the immediate parent discussion topic, but for group
assignment discussions, the parent has it's own root discussion topic that also
needs to be touched for caching purposes.
test-plan:
- enable caching
- make a group discussion assignment
- post some entries in one of the sub discussions that is created
- go back to the main discussion page that lists the group discussions, and
make sure the counts in the main page match those in the right sidebar, and
are up to date
Change-Id: Ied0e07e5c61b7dbe2a148740bb7a9e46cc720b9a
Reviewed-on: https://gerrit.instructure.com/8926
Reviewed-by: Cody Cutrer <cody@instructure.com>
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Brian Palmer <brianp@instructure.com>
the "Topics I've Commented On" notification wasn't working, this fixes it to
correctly send messages for a new discussion entry to all other users who have
participated in that discussion already.
test plan:
- set your topics i've commented on notification to immediately
- create a discussion topic
- have another user create a response
- you should be notified
Change-Id: I6a0d90c7b8c590b645cc31ab004da991a5851b0f
Reviewed-on: https://gerrit.instructure.com/8564
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Brian Palmer <brianp@instructure.com>
provides a role override permission for viewing discussions. primarily useful
for disallowing observers from reading discussion, although by default it is
enabled.
test plan:
- create a course
- create a discussion (d1) in that course
- create a discussion assignment (d2) in that course
- log in as an observer and make sure you can see both discussions above
- log in as an admin and revoke the read_forum permission for observers
- log back in as the observer and make sure you can't see the discussions
- also check that the assignment shows the assignment page, but does not
redirect to the associated discussion.
Change-Id: I4c6441c781c24e6aadacbfc23dcc307c772ecd2c
Reviewed-on: https://gerrit.instructure.com/8069
Reviewed-by: Cody Cutrer <cody@instructure.com>
Tested-by: Cody Cutrer <cody@instructure.com>
fixes#6560
The assignment and submission apis were written before the discussion
api, and the response formats diverged. This merges the two formats so
that all apis return the same data structures.
Also, removed the attachments relation from DiscussionEntry, it's cruft.
We have to continue returning the attachments array in the json for now,
for backwards compatibility, since it includes the .attachment field as
well.
test plan: API calls to read discussion assignments and their
submissions should now include the full json response data, see the api
documentation for the discussions api.
Change-Id: Ib394d7e5c3fcf261adb8663470c6822fe2476b03
Reviewed-on: https://gerrit.instructure.com/7395
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Bracken Mosbacker <bracken@instructure.com>
Test Plan:
* Create a course and don't publish it
* Add a student to that course
* Create a discussion topic as the teacher
* Make sure there is no item for the topic in the student's stream
( make sure the student as at least one other active enrollment though because stream items don't show at all if a user has no enrollments at all)
closes#6200#5432
Change-Id: Ib993edf139d3c971197c7876a01e9f9592583704
Reviewed-on: https://gerrit.instructure.com/7221
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Jacob Fugal <jacob@instructure.com>
if a discussion goes from ungraded to graded create any missing
submissions in the newly associated assignment for existing entries.
also, find any situations where this should have already happened and
rectify them.
test-plan:
* using old code, create two ungraded discussions
* have a student contribute to each discussion
* switch the discussion to being graded
* note there are no submissions for the student in the speedgrader
* apply migration
* note there are submissions for the student in the speedgrader
* using new code, create a third ungraded discussion
* have the student contribute to the third discussion
* switch the third discussion to being graded
* note there is a submission for the student in the speedgrader
fixes#5748
Change-Id: I30b90ba36c5d688cd9512bdb2d9d2df2cee06a08
Reviewed-on: https://gerrit.instructure.com/6822
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Brian Palmer <brianp@instructure.com>
supports creating and listing top-level entries in a discussion topic,
and creating and listing replies to a discussion entry. listing
discussion topics was already supported. includes support for
attachments on top-level entries.
test-plan:
creating an entry under a topic
should allow creating an entry under a topic and create it correctly
should return json representation of the new entry
should allow creating a reply to an existing top-level entry
should not allow reply-to-reply
should allow including attachments on top-level entries
should silently ignore attachments on replies to top-level entries
should include attachment info in the json response
listing top-level discussion entries
should return top level entries for a topic
should return attachments on top level entries
should include replies on top level entries
should sort top-level entries by descending created_at
should sort replies included on top-level entries by descending
created_at
should paginate top-level entries
should only include the first 10 replies for each top-level entry
listing replies
should return replies for an entry
should sort replies by descending created_at
should paginate replies
require initial post
should allow admins to see posts without posting
shouldn't allow student who hasn't posted to see
shouldn't allow student's observer who hasn't posted to see
should allow student who has posted to see
should allow student's observer who has posted to see
fixes#4752
Change-Id: I0da83e6c301be74f1ac5d2d957ebb6338a98179c
Reviewed-on: https://gerrit.instructure.com/6690
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
This problem was hidden in 1.8 because Array#to_s is an alias for
Array#join , but manifests itself in 1.9 where it aliases Array#inspect
Change-Id: I118696cdc129f71f31997ad852d8d7c6d3ad0fc9
Reviewed-on: https://gerrit.instructure.com/5842
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Jon Jensen <jon@instructure.com>
update_all's update hash doesn't have any magic performed on bare Time
objects; it assumes any Time object it's given is already in UTC. using
a TimeWithZone object (regardless of timezone), which Fixnum#ago and
friends happen to return, is still fine.
Change-Id: I297b2a3211b896b5225ebcfaaee3c1eb56e55fb6
Reviewed-on: https://gerrit.instructure.com/5351
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Jon Jensen <jon@instructure.com>
This was already a small issue if the job queue was on a different
database driver than the main database, and it'll become more important
as more AR connections are introduced.
Change-Id: I204becadd32bb935df096e8c937a04bb6962f0b2
Reviewed-on: https://gerrit.instructure.com/4601
Reviewed-by: Cody Cutrer <cody@instructure.com>
Tested-by: Hudson <hudson@instructure.com>
Basically, don't call a bazillion procs everytime you check_policy;
just the "given" statement. Everything else is evaluated just once,
and cached on the class. This does lose functionality (the ability
to access the instance inside of set_policy, and set methods), but
none of it was currently in use.
Change-Id: I736879d98beb4115a2e8c492931c755076291d08
Reviewed-on: https://gerrit.instructure.com/4665
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: JT Olds <jt@instructure.com>
added checks to extractor for some common typos/oversights (and more line numbers)
Change-Id: I7a2b080cf2a26cb6711539220fe2486a1a4f04b5
Reviewed-on: https://gerrit.instructure.com/4581
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
Each topic can now have its own podcast stream. Teachers
have to manually turn on the podcast for the topic, and
can specify whether student comments show up in the stream
or not.
fixes#3538
Change-Id: I19b1b44fc2eec864cfeb298163ef34a0b0181067
Reviewed-on: https://gerrit.instructure.com/2369
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Brian Palmer <brianp@instructure.com>
The format_message call takes care of escaping HTML entities.
Change-Id: Ifb6f890903ee00c8098ee8596d4b66d18a2b9054
Reviewed-on: https://gerrit.instructure.com/2418
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Zach Wily <zach@instructure.com>