Compare commits

...

481 commits

Author SHA1 Message Date
Devin Howard
98081097b4 Revert "update rails dependencies"
Original commit broke the build, since some dependencies have breaking
changes.

This reverts commit f753392d49.
2018-11-09 07:42:26 -08:00
Devin Howard
f753392d49 update rails dependencies 2018-10-17 19:51:51 -07:00
Connor Turland
38a209a970 small bug fix (#1174)
if someone besides one of "us" tried to change their password, and their settings, it wouldn't work

in the typical case it would work fine
2018-03-11 21:57:23 -07:00
Devin Howard
bd7bf20810
factory_girl => factory_bot (#1172) 2018-03-10 08:10:09 -08:00
Devin Howard
955ebdd747
Change log level of Metamaps.Debug (#1170)
debug log level is invisible in Chrome by default, which is confusing
2018-02-05 21:35:53 -08:00
Devin Howard
fdcd8a93f1 tag 3.6.1 2018-01-24 20:02:28 -08:00
Devin Howard
b5c52adf5e update to paperclip 5.2.0 2018-01-24 19:52:33 -08:00
Devin Howard
b7761a3627
manual rubocop fixes (#1163) 2018-01-21 14:21:00 -08:00
Devin Howard
e0d72fce14
update nokogiri (#1169) 2018-01-21 14:20:21 -08:00
Devin Howard
139fdf8e2b
update rubocop to 0.48.1. We still want to match Code Climate though (#1168) 2018-01-20 14:10:26 -08:00
Devin Howard
4313f6eff8
TopicCard/Desc.spec.js (#1167)
TopicCard/Desc.spec.js
2018-01-20 13:31:36 -08:00
Devin Howard
91c004ebfd
TopicCard/Permission.spec.js (#1166) 2017-12-04 21:06:09 -08:00
Devin Howard
96056f43ef
TopicCard/Title.spec.js (#1165) 2017-12-02 12:45:05 -08:00
Devin Howard
32e58fa8af
tests for TopicCard/index.js (#1164) 2017-11-26 16:13:17 -08:00
Devin Howard
5ebbd87afc
automatic rubocop fixes (#1162) 2017-11-25 11:23:47 -08:00
Devin Howard
006920b686 fix broken experience if forgot password email isn't found 2017-11-13 07:16:25 -08:00
Devin Howard
97448b389f null check in synapse policy 2017-11-13 07:11:48 -08:00
Connor Turland
f1ecc9eb0b Merge pull request #1160 from metamaps/bug/map.info.box.closing
event listener was getting lost cuz react
2017-10-26 19:17:42 -04:00
Connor Turland
ca2684fcf3 event listener was getting lost cuz react 2017-10-26 19:09:28 -04:00
Connor Turland
d9c53514fe Update pull-changes.md 2017-10-25 06:44:20 -04:00
Connor Turland
e195b89bbd Merge pull request #1155 from metamaps/bug/fix.emails
fix map activity emails
2017-10-17 12:26:20 -04:00
Connor Turland
e66498a861 add logging for delayedJob 2017-10-17 12:20:51 -04:00
Connor Turland
901eb4a513 Update daily_summary.html.erb 2017-10-17 12:06:37 -04:00
Devin Howard
cbf44e3dfe add one view test 2017-10-17 08:28:00 -07:00
Connor Turland
8b492d6dc8 made the mistake of not checking all cases 2017-10-17 01:28:07 -04:00
Connor Turland
b83f366284 Merge pull request #1151 from metamaps/feature/admin.pages
move admin header to react
2017-10-15 16:05:18 -04:00
Connor Turland
1ac06d973c Merge pull request #1153 from metamaps/feature/follow.created
follow created maps as default setting
2017-10-15 14:08:04 -04:00
Connor Turland
9af3754bc8 follow created maps as default setting
if you are the map creator, we'd like to set you up to be following it by default
2017-10-15 14:07:11 -04:00
Connor Turland
8169f24072 Merge pull request #1150 from metamaps/rake-assets-precompile
run perms:fix on assets:precompile
2017-10-15 11:02:59 -04:00
Connor Turland
b9fb4a2829 move admin header to react 2017-10-15 10:56:51 -04:00
Connor Turland
9b52d0e081 fix tests 2017-10-15 10:56:04 -04:00
Devin Howard
14dc3687cd run perms:fix on assets:precompile 2017-10-14 12:02:41 -07:00
Metamaps on Linode
0a6e7918ef fix docs building by reverting raml2html 2017-10-14 14:55:42 -04:00
Metamaps on Linode
4a7595e76d fixup imports 2017-10-14 14:55:42 -04:00
Connor Turland
e899179314 Update first-deploy.md 2017-10-14 14:44:10 -04:00
Connor Turland
44fec58985 Merge pull request #1149 from metamaps/feature/reorg.react
reorg code to distinguish between route components and normal ones
2017-10-14 12:38:57 -04:00
Connor Turland
29a25c28a8 distinguish between route components and reusable components 2017-10-14 12:37:48 -04:00
Connor Turland
76c727cd61 Merge pull request #1148 from metamaps/feature/refactor.nav.bar
rename exploreMapsBar into reusable navBar
2017-10-14 12:30:29 -04:00
Connor Turland
693e6f5e10 bug fixes and make active class auto 2017-10-14 12:03:05 -04:00
Connor Turland
a1d4c99ff6 abstract exploreMapsBar into reusable navBar 2017-10-13 13:58:21 -04:00
Connor Turland
55f2425501 Merge pull request #1142 from metamaps/feature/notifs.box
Notifications Dropdown
2017-10-13 12:29:21 -04:00
Connor Turland
f9c139c19e ruby codeclimate fixes 2017-10-13 12:22:05 -04:00
Connor Turland
d51a22c5a9 eslint fixes 2017-10-13 12:13:36 -04:00
Connor Turland
567bc9d69d Merge pull request #1145 from metamaps/feature/lower.case.headings
Switch junto headings to have normal casing (not all uppercase)
2017-10-04 11:22:33 -04:00
Connor Turland
15f512efef improve notificationbox readability 2017-09-29 14:05:39 -04:00
Connor Turland
5e6fb6290c refactor for clarity 2017-09-29 13:06:33 -04:00
Connor Turland
8695297a0f wasn't using the proper serializer causing frontend error 2017-09-29 13:06:19 -04:00
Connor Turland
216a19476b add hover states and empty case 2017-09-28 12:28:33 -04:00
Connor Turland
a0c9530c91 Update index.js 2017-09-25 16:01:25 -04:00
Connor Turland
277644f59d improve styling, fix index notifs page 2017-09-25 15:21:04 -04:00
Connor Turland
0ffc01b3fb Merge pull request #1144 from metamaps/feature/hide-learn-markdown
hide "learn markdown" unless you're editing the topic card desc
2017-09-25 14:46:44 -04:00
Devin Howard
9471efb6bd hide "learn markdown" unless you're editing the topic card desc 2017-09-23 13:19:43 -07:00
Connor Turland
fc8ac6eef1 nest inconsistent data under data key 2017-09-23 11:20:02 -04:00
Connor Turland
9cc700c64d use decorator pattern for notifs api 2017-09-22 18:38:38 -04:00
Connor Turland
64ffc78f45 add the container for the notifications dropdown 2017-09-19 23:48:46 -04:00
Connor Turland
322da431eb Merge pull request #1139 from metamaps/feature/right.click.react
Right click/context menu redone in React
2017-09-19 11:49:30 -04:00
Connor Turland
3c7c8812a4 tempplate strings and new lines 2017-09-19 11:46:19 -04:00
Connor Turland
0d6963ebb0 eslint 2017-09-19 10:16:14 -04:00
Connor Turland
c4d0bf8ce4 clean up jquery ref and strings 2017-09-19 10:02:05 -04:00
Connor Turland
3406f2e04d make render a callback and use async apply for ease of use 2017-09-19 09:58:59 -04:00
Connor Turland
a4c905df4e move each li into its own function 2017-09-19 09:04:21 -04:00
Connor Turland
5f1fe4dc3f reimplement shifting menu according to click position 2017-09-19 08:37:00 -04:00
Connor Turland
2515073393 replace old edgeRightClick code 2017-09-19 00:46:23 -04:00
Connor Turland
a04cd0d395 call the right callbacks and show in the right context 2017-09-19 00:34:37 -04:00
Connor Turland
da9e44afa0 clear the right click menu the right way 2017-09-18 23:49:35 -04:00
Connor Turland
e290244404 beginning to come together 2017-09-18 23:30:33 -04:00
Connor Turland
6e1878413f wip right click in react 2017-09-18 21:09:35 -04:00
Connor Turland
77846cfcb7 missing period for consistency 2017-09-18 16:59:52 -04:00
Connor Turland
1ffc513617 Merge pull request #1137 from metamaps/feature/improve.desc
make desc edit area larger and resizable
2017-09-17 16:25:53 -04:00
Connor Turland
3886e62a7b make desc edit area larger and resizable 2017-09-17 09:01:44 -04:00
Devin Howard
ad2ba33db6 downgrade redis to 3.3.3
This fixes the following error seen on metamaps.cc:

> *A* `Gem::LoadError` *occurred while* `POST </mappings>` *was processed
> by* `mappings#create`: Specified 'redis' for Action Cable pubsub
> adapter, but the gem is not loaded. Add `gem 'redis'` to your Gemfile
> (and ensure its version is at the minimum required by Action Cable).

Backtrace
----------------

    ```/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/monitor.rb:214:in
    `mon_synchronize'
    /home/metamaps/metamaps.cc/app/models/mapping.rb:32:in `after_created'
    /home/metamaps/metamaps.cc/app/controllers/mappings_controller.rb:24:in
    `create'```
2017-09-16 13:41:50 -07:00
Devin Howard
cf9f54c738 tag v3.5 2017-09-16 12:27:02 -07:00
Connor Turland
f323796030 Merge pull request #1132 from metamaps/feature/mod.follow
add active scope to follows model
2017-09-13 22:45:50 -04:00
Connor Turland
a080b82e7f Merge pull request #1133 from metamaps/feature/topic.follow
Topic Card Design changes (to include 'follows')
2017-09-13 10:32:44 -04:00
Connor Turland
1174123b60 use scss vars and font fallbacks 2017-09-13 10:31:48 -04:00
Connor Turland
35f77129ad email job needs to respect active as well 2017-09-13 10:20:25 -04:00
Connor Turland
a56991aede add exception notifier for failed jobs 2017-09-13 10:18:00 -04:00
Connor Turland
672b456193 add markdown clarifications 2017-09-12 21:37:49 -04:00
Connor Turland
21518c8696 revert react router update and webpack config 2017-09-12 17:07:57 -04:00
Connor Turland
29bf2a23e8 review changes 2017-09-12 17:01:08 -04:00
Connor Turland
61eac509de Merge branch 'develop' into feature/topic.follow 2017-09-10 18:16:11 -04:00
Connor Turland
4cc420eb63 eslint fixes 2017-09-10 18:13:25 -04:00
Connor Turland
ec3e09c578 topic card design changes 2017-09-10 17:17:56 -04:00
Devin Howard
3e03e0ebbf update npm/gem dependencies (#1131)
* update npm/gem dependencies

* move to react prop-types package and fix jsdom usage

* fix sinon

* fix test support

* eslint?
2017-09-09 09:38:18 -07:00
Connor Turland
9ab7e7e170 topic card re-org 2017-09-08 16:58:17 -04:00
Connor Turland
5af2b8f216 add active scope to follows model 2017-09-08 13:42:56 -04:00
Connor Turland
8af66b1b2c Merge pull request #1130 from metamaps/feature/release.notifs
make notifs and follows work for all users
2017-09-03 18:44:33 -04:00
Connor Turland
9b2193ad8c show autofollow on client and mute on unfollow 2017-09-03 15:18:57 -04:00
Connor Turland
1a8c7810be fix eslint issue picked up by codeclimate 2017-09-03 09:13:15 -04:00
Connor Turland
d87bb7c75c make notifs and follows work for all users 2017-09-03 09:07:29 -04:00
Connor Turland
aceb3ff31e Merge pull request #1129 from metamaps/feature/map.activity.improved
improve email styling for release
2017-09-03 08:33:13 -04:00
Connor Turland
f26c6cf0b7 Merge pull request #1128 from metamaps/feature/prevent.notif.fork
dont send notification for each topic of forked map
2017-09-03 08:29:03 -04:00
Connor Turland
42f4ecb37b added bg color to sections 2017-09-03 08:27:05 -04:00
Connor Turland
64f4249f44 add comment 2017-09-02 14:12:07 -04:00
Connor Turland
958bd8c70c improve email styling for release 2017-09-02 14:06:23 -04:00
Connor Turland
3830946723 dont send notif for each topic of forked map 2017-09-02 09:59:21 -04:00
Connor Turland
3482e799fd Merge pull request #1127 from metamaps/update-docs
update docs
2017-07-26 09:26:59 -07:00
Connor Turland
e016b923a4 Update WindowsInstallation.md 2017-07-26 09:25:41 -07:00
Connor Turland
bb546779cd Update VagrantInstallation.md 2017-07-26 09:24:51 -07:00
Connor Turland
3829d32390 Update UbuntuInstallation.md 2017-07-26 09:22:34 -07:00
Connor Turland
9783a5ee1e Update MacInstallation.md 2017-07-26 09:22:06 -07:00
Connor Turland
12fc0c71f6 Update README.md 2017-07-26 09:21:16 -07:00
Connor Turland
c2cb8949eb Create VagrantInstallation.md 2017-07-25 17:22:27 -07:00
Connor Turland
4e7bf02749 Update README.md 2017-07-25 17:19:17 -07:00
Connor Turland
3203c2b4d0 de-prioritize vagrant docs, as its no longer our setup of choice 2017-07-25 17:18:07 -07:00
Connor Turland
1ec9dc20e4 Update MacInstallation.md 2017-07-25 17:07:46 -07:00
Connor Turland
1af4728073 Update UbuntuInstallation.md 2017-07-25 17:06:27 -07:00
Connor Turland
785e16eeae make Vagrantfile realtime server port match default 2017-07-25 16:57:37 -07:00
Connor Turland
d08cb3f95e Update UbuntuInstallation.md 2017-07-25 16:52:11 -07:00
Connor Turland
271fc7ebd0 Update MacInstallation.md 2017-07-25 16:47:33 -07:00
Connor Turland
9d590295cb Update WindowsInstallation.md 2017-07-25 16:44:40 -07:00
Connor Turland
dc4d44951e Update UbuntuInstallation.md 2017-07-25 16:41:47 -07:00
Connor Turland
767414ad9f Update MacInstallation.md 2017-07-25 16:37:16 -07:00
Connor Turland
1ec897b8c8 Update MacInstallation.md 2017-07-17 20:45:34 -07:00
Connor Turland
00e2aefb4e Delete ISSUE_TEMPLATE.md 2017-07-16 20:50:14 -07:00
Connor Turland
aec0f104b8 Merge pull request #1121 from JohnGillanders/develop
Update README.md
2017-07-09 23:32:41 -07:00
John Gillanders
db6d2e77da Merge pull request #1 from metamaps/develop
Updates from metamaps base 04/07/2017
2017-07-04 12:59:20 +12:00
John Gillanders
9585dce511 Update README.md
Added example of cloning repository using https:// protocol instead of SSH protocol - this is simpler to do since no set-up of SSH keys is required.
2017-07-04 12:49:28 +12:00
Devin Howard
78acd7e0b0 fix NoMethodError in mappings after_created when synapse's topic1/topic2 are nil 2017-05-20 10:58:06 -07:00
Devin Howard
328c1a14f3 mark v3.4.1 one commit too late 2017-05-13 19:32:51 -07:00
Devin Howard
10ac64c574 before destroy callback on maps to remove source_id foreign key relations (#1119) 2017-05-13 19:26:43 -07:00
Devin Howard
edce66c44d new react tests with enzyme library (#1116)
* move ImportDialogBox into a folder

* install enzyme

* start testing InfoAndHelp component

* add star logic to tests

* switch ImportDialogBox to using enzyme but tests are still failing

* make `npm run test` work

* tests pass again

* eslint

* try to fix travis by adding react-addons-test-utils again

* eslintrc for test dir

* remove duplicated code

* fix

* try to suppress 2 warnings
2017-05-13 13:50:52 -04:00
Devin Howard
74df2559a4 try to fix fatal on notifications index when a topic is invalid (#1115)
* try to fix fatal on notifications index when a topic is invalid

* Update index.html.erb
2017-05-13 13:49:46 -04:00
Robert Best
a6694a3f72 Improvements to Import (#1109)
* Changed URL Regex to make more links importable, also removed need for special text formatting in order to paste or drop new topic labels. (Didn't break TSV import mode)

* Removed console logs

* add url regex with full documentation

* don't eslint 3rd party lib

* check for TSV only at start of string

* fix a bug with event/e and eslint

* handleTEXT => handleText
2017-04-11 11:51:22 -04:00
Devin Howard
8c7a657499 update vimeo url, use asset path + erb for poster path (#1106) 2017-03-26 13:53:59 -07:00
Connor Turland
90f77cd4f7 simplify views/topiccard (#1102)
* simplify views/topiccard

* Update Links.js
2017-03-22 19:22:38 -04:00
Connor Turland
af4dc869c0 devins right shouldnt push straight to develop 2017-03-22 17:04:18 +00:00
Connor Turland
2cae12e1ab found a better way to handle junto chat panel 2017-03-22 16:35:28 +00:00
Connor Turland
49102ea474 only toggle if authorized 2017-03-22 16:13:59 +00:00
Connor Turland
f2a7cc1f19 stop using jquery ui for topic card dragging 2017-03-22 16:10:08 +00:00
Devin Howard
a5d5cd6000 fix editing synapse desc (#1101) 2017-03-20 19:32:54 -07:00
Devin Howard
391a1d8b24 link feedback directly to a hylo feedback tag (#1099) 2017-03-20 12:48:30 -07:00
Connor Turland
cc17c1ed38 add tiny divider between global and map items 2017-03-17 12:54:18 -04:00
Connor Turland
eee1febbf9 clean up unused vars and logs 2017-03-17 10:25:08 -04:00
Connor Turland
c8f6374ac8 remove no longer needed comments 2017-03-17 09:32:52 -04:00
Connor Turland
ed76162b63 added icons to mobile menu fixes #1095 2017-03-17 01:32:01 -04:00
Connor Turland
1eb4187691 broken import 2017-03-17 00:11:57 -04:00
Connor Turland
4a7dd54aca remove unused vars 2017-03-17 00:48:28 +00:00
Connor Turland
efd6258c7e mobile.js was already removed but not deleted 2017-03-17 00:29:24 +00:00
Connor Turland
f4d1b8ba35 ensure node is defined before calling function on it 2017-03-17 00:10:32 +00:00
Connor Turland
47a74dd77b react-router and rebuild app structure in react (#1091)
* initial restructuring

* stuff

* lock version number

* just keep using current mapinfobox

* fix map upperRightUI layout

* make mapsWidth work and add mobile

* remove filterBoxOpen for now

* redo the mobile menu in react

* get account menu and invite lightbox working

* fixed maps scrolling

* make other routes work

* fix signed out home page

* fix accountbox toggling

* add metacode edit routes

* lots of fixes

* fix map chat layout and tab bug

* improve topic card readability and fix dragging bug

* fixup mapchat stuff

* fix up navigation to use react-router

* jquery no longer handling access requests

* handle case where user hasn't loaded yet

* this shouldn't have been removed

* add frame for topic view

* rewrite map instructions

* fix toast (and sign out bug)

* fix apps pages and missing routes

* made our request invite page look nice

* filter box in react

* forgot to add one proptype

* remove extra comments

* handle page title and mobile title updates

* reenable google analytics

* make filterbox use onclickoutside

* reenable topic view in react

* fix csrf auth token

* fix little homepage styling issue

* try putting preparevizdata in a timeout

* installing render log to count

* little fixes

* fixup filters

* make filter map function names more readable

* eslint helps

* renaming for clarity

* use onclickoutside for account/sign in box

* add some logging to see whether this is source of many renders

* turns out chatview was heavily hogging memory

* tiimeout not needed
2017-03-16 17:58:56 -04:00
Robert Best
33276444c7 [Feature] Expand current selection to include neighbors by pressing CTRL+SHIFT+UP (#1090)
* Expand current selection to include neighbors by pressing CTRL+SHIFT+UP

* minor fixes as requested
2017-03-10 15:22:30 -08:00
Devin Howard
1124d76475 re-enable codeclimate duplication 2017-03-10 08:30:01 -08:00
Connor Turland
4ffa9460f5 bug fix for people who aren't testers on settings page 2017-03-10 11:29:00 -05:00
Connor Turland
44753dbfe1 Merge branch 'develop' 2017-03-09 14:55:59 -05:00
Connor Turland
77f76b1b5a variable name fix and make is_tester method global for reuse in views 2017-03-09 14:36:24 -05:00
Devin Howard
e544d6a6db refactor api and fix bugs (#1088)
* fix weird double-embed issue

* fix users/current api if not logged in

* turbocharge the api

* fix docs
2017-03-09 14:24:52 -05:00
Devin Howard
780e66632b fix react embedly (#1089) 2017-03-09 14:23:24 -05:00
Connor Turland
de4f51bb5c fix permissions and don't send if has map open 2017-03-08 15:45:40 -05:00
Connor Turland
5d0da4c5f1 method was preventing certain follows from succeeding 2017-03-08 15:02:22 -05:00
Connor Turland
9079d1bffc check permissions prior to sending 2017-03-08 15:01:58 -05:00
Connor Turland
962881a35d Update follow_service.rb 2017-03-08 14:13:47 -05:00
Connor Turland
8483b62603 allow users to select follow settings 2017-03-08 18:50:56 +00:00
Devin Howard
e3b4dac1e1 remove takeScreenshot button in favour of separate buttons in the map card and import/export dialogue (#1086) 2017-03-07 12:15:28 -05:00
Connor Turland
8998e3858c fixes bug where popups are happening 2017-03-07 16:55:15 +00:00
Devin Howard
ce51eeca8c remove dedupe plugin 2017-03-07 07:54:25 -08:00
Connor Turland
3178f6e650 bump version number 2017-03-07 03:58:29 +00:00
Connor Turland
7ee96bf6c6 Into master: two finger pan/zoom, map and topic follows (for internal testing) on the UI, map activity emails (#1084)
* fix topic spec

* fix synapse/mapping spec

* brakeman csrf warning suppressed :|

* follows for maps in the ui for internal testing only still (#1072)

* follows for maps in the ui for testers

* require user for these actions

* match how map follow works

* include ability to unfollow from email

* fixup templates

* add unfollow_from_email to the policies

* Update _cheatsheet.html.erb

Clean up text, clarify, and bring in line with current functionality

* topicsRegex and synapsesRegex should allow commas (#1073)

* even better import csv regexes

* prevent double prompt on file drop import

* topic card in react (#1031)

* its coming along

* links bar

* scssify a bunch

* metacode image working a bit better

* metacode selector in react topic card

* riek editing for name field on topic card

* riek submit on enter

* factor out Title and Links from Topic Card component, but not the listeners

* create working Desc editor

* styling is much better now

* textarea min height for desc

* disallow images in topic card markdown

* shift enter is linebreak, enter is save

* attachments split out, but it's pretty buggy

* move listeners into Links.js

* slightly wider metacodeTitle

* fix positioning on metacode selector

* fix metacode selection

* move metacode and permissions into subcomponents

* fixes

* prevent editing on desc/title if not authorized to edit

* fix topic card draggability

* fix embedly

* fix md test

* remove the removed link card manually with jquery

* fix test syntax

* eslint

* more eslin

* reuse authorizedToEdit

* convert metacode sets to a json object for react

* add the html in react whoop

* fix metacode styling

* sort wasn't working

* finishing metacode select

* readd the above link input border

* fix syntax

* multiline title editable textarea

* more portable metacode selector component

* factor out #metacodeOptions into one react component with a callback :D:D:D

* render metacodeOptions in right click menu with react

* render metacodeOptions in right click menu with react

* fix up right click menu's metacode editing

* fix topic card title character counter

* ignore metamaps secret bundle in ag

* simplify Attachments props

* factor out embedly card into its own component; it seems to help

* link resetter

* fix edit icon on title in topic card

* move mapCount and synapseCount hover/click logic to react

* fix up the showMore control

* metacode selection tweaks

* tweak links bar spacing in topic card

* rubocop

* remove TODOs

* more badass permissions selector

* close permission selector when you click outside

* fix overeager metacode selector

* more modular attachments component

* fix bug in Desc.js

* fix right click styling

* permission changes are different than edit rights

* bad module ref

* ensure maxLength on topic titles

* hellz yeah (#1074)

* fix drop from two touches to one

* don't commit activity service

* ability to select/unselect all metacodes in custom set with keyboard shortcut (fix #390) (#1078)

* ability to select/unselect all metacodes in custom set with keyboard shortcut

* select all button

* nicer all/none buttons

* set up react testing (#1080)

* install mocha-webpack. also switch hark to npm version instead of github version

* well, mocha-webpack runs

* add jsdom for tests

* upgrade to webpack 2

* fix npm run test errors

* ImportDialogBox component tests

* Fixes bug where pressing delete key while editing text will suggest... (#1083)

* Fixes bug where pressing delete key while editing text will suggest the deletion of selected map entities

* Changed the DEL key to remove entities instead of delete them

* temporarily disable code climate duplication engine

* add topic following for internal testing

* daily map activity emails (#1081)

* data prepared, task setup

* add the basics of the email template

* cover granular permissions

* unfollow this map

* break out permissions tests better

* rename so test runs
2017-03-06 22:49:46 -05:00
Connor Turland
b740fef8fe daily map activity emails (#1081)
* data prepared, task setup

* add the basics of the email template

* cover granular permissions

* unfollow this map

* break out permissions tests better

* rename so test runs
2017-03-06 22:42:22 -05:00
Connor Turland
55b031ccb7 add topic following for internal testing 2017-03-07 01:47:10 +00:00
Devin Howard
9df389060e temporarily disable code climate duplication engine 2017-03-06 09:29:36 -08:00
Robert Best
153cc38d1a Fixes bug where pressing delete key while editing text will suggest... (#1083)
* Fixes bug where pressing delete key while editing text will suggest the deletion of selected map entities

* Changed the DEL key to remove entities instead of delete them
2017-03-06 11:48:59 -05:00
Devin Howard
4ff9619837 set up react testing (#1080)
* install mocha-webpack. also switch hark to npm version instead of github version

* well, mocha-webpack runs

* add jsdom for tests

* upgrade to webpack 2

* fix npm run test errors

* ImportDialogBox component tests
2017-03-06 02:29:12 +08:00
Devin Howard
a6c1c0c730 ability to select/unselect all metacodes in custom set with keyboard shortcut (fix #390) (#1078)
* ability to select/unselect all metacodes in custom set with keyboard shortcut

* select all button

* nicer all/none buttons
2017-03-04 11:51:51 -05:00
Connor Turland
529dec09a3 don't commit activity service 2017-03-02 04:38:33 +00:00
Connor Turland
ddbaac513f fix drop from two touches to one 2017-03-02 04:35:13 +00:00
Connor Turland
ba943b20f1 hellz yeah (#1074) 2017-02-27 17:06:56 -05:00
Connor Turland
4deb3f5ab9 topic card in react (#1031)
* its coming along

* links bar

* scssify a bunch

* metacode image working a bit better

* metacode selector in react topic card

* riek editing for name field on topic card

* riek submit on enter

* factor out Title and Links from Topic Card component, but not the listeners

* create working Desc editor

* styling is much better now

* textarea min height for desc

* disallow images in topic card markdown

* shift enter is linebreak, enter is save

* attachments split out, but it's pretty buggy

* move listeners into Links.js

* slightly wider metacodeTitle

* fix positioning on metacode selector

* fix metacode selection

* move metacode and permissions into subcomponents

* fixes

* prevent editing on desc/title if not authorized to edit

* fix topic card draggability

* fix embedly

* fix md test

* remove the removed link card manually with jquery

* fix test syntax

* eslint

* more eslin

* reuse authorizedToEdit

* convert metacode sets to a json object for react

* add the html in react whoop

* fix metacode styling

* sort wasn't working

* finishing metacode select

* readd the above link input border

* fix syntax

* multiline title editable textarea

* more portable metacode selector component

* factor out #metacodeOptions into one react component with a callback :D:D:D

* render metacodeOptions in right click menu with react

* render metacodeOptions in right click menu with react

* fix up right click menu's metacode editing

* fix topic card title character counter

* ignore metamaps secret bundle in ag

* simplify Attachments props

* factor out embedly card into its own component; it seems to help

* link resetter

* fix edit icon on title in topic card

* move mapCount and synapseCount hover/click logic to react

* fix up the showMore control

* metacode selection tweaks

* tweak links bar spacing in topic card

* rubocop

* remove TODOs

* more badass permissions selector

* close permission selector when you click outside

* fix overeager metacode selector

* more modular attachments component

* fix bug in Desc.js

* fix right click styling

* permission changes are different than edit rights

* bad module ref

* ensure maxLength on topic titles
2017-02-26 11:42:47 -05:00
Devin Howard
47d0faadf2 prevent double prompt on file drop import 2017-02-25 13:04:00 -08:00
Devin Howard
9800cc27c6 even better import csv regexes 2017-02-25 12:15:45 -08:00
Devin Howard
7840e09e5f topicsRegex and synapsesRegex should allow commas (#1073) 2017-02-25 12:05:56 -08:00
ben, bro
687b957737 Update _cheatsheet.html.erb
Clean up text, clarify, and bring in line with current functionality
2017-02-23 22:03:33 -08:00
Connor Turland
9ce989eba5 add unfollow_from_email to the policies 2017-02-16 14:01:22 +00:00
Connor Turland
2c85590d65 fixup templates 2017-02-16 13:55:19 +00:00
Connor Turland
2b34d84715 include ability to unfollow from email 2017-02-16 13:42:35 +00:00
Connor Turland
013e3c7f21 follows for maps in the ui for internal testing only still (#1072)
* follows for maps in the ui for testers

* require user for these actions

* match how map follow works
2017-02-15 23:01:53 -05:00
Devin Howard
8d771543d8 Merge branch 'fix/rspec' into develop 2017-02-12 15:29:40 -08:00
Devin Howard
50639e8a0a Merge branch 'develop' 2017-02-12 15:11:19 -08:00
Devin Howard
9d52aa9c74 tag v3.3 2017-02-12 15:09:08 -08:00
Devin Howard
545706e17a disable cookie based auth on the API - mostly (#1070) 2017-02-12 12:54:54 -05:00
Devin Howard
95901e17e8 fix travis (#1071)
* fix topic spec

* fix synapse/mapping spec

* brakeman csrf warning suppressed :|
2017-02-12 12:53:04 -05:00
Devin Howard
9dbbdf1150 brakeman csrf warning suppressed :| 2017-02-11 20:00:42 -08:00
Devin Howard
4ee4aeaad2 fix synapse/mapping spec 2017-02-11 19:56:07 -08:00
Devin Howard
bfdce21a66 fix topic spec 2017-02-11 19:54:09 -08:00
Devin Howard
53d4beddec move hr tag in notification emails 2017-02-11 19:35:23 -08:00
Devin Howard
d455ced683 send mail by default is false in message from devs. also fixes a bug where the option didn't do anything 2017-02-11 19:30:58 -08:00
Connor Turland
d8698ef6f2 api stuffs (#1069)
* Update restful_controller.rb

* Update tokens_controller.rb

* /tokens/new form

* thats all
2017-02-11 19:29:03 -05:00
Connor Turland
1374da35da Update notification_service.rb 2017-02-11 15:29:31 -05:00
Connor Turland
2d0d0403b1 little fixes for deploy 2017-02-11 19:50:59 +00:00
Connor Turland
2d50f24be6 var misnamed 2017-02-11 14:21:47 +00:00
Connor Turland
876c61a18e Better experience of notifications. (#1066)
* all the good changes

* follows

* dont send duplicates

* remove follow_type for now

* dont add all the extra stuff we're not implementing yet

* refactor

* lots of fixes

* notifications improvements

* bad merge
2017-02-11 09:06:01 -05:00
Connor Turland
b0deafc53e Follows and some new notifications (#1063)
* all the good changes

* follows

* dont send duplicates

* remove follow_type for now

* dont add all the extra stuff we're not implementing yet

* refactor

* lots of fixes

* Delete activity.html.erb

* Delete activity.text.erb

* Update 20170209215819_create_follows.rb

* Update schema.rb

* Update mapping.rb

* Update mailboxer.rb
2017-02-11 00:20:42 -05:00
Connor Turland
a647d80efa third try to fix this little bug 2017-02-10 12:02:05 -05:00
Connor Turland
559ad230ce actually this fixes it 2017-02-10 11:52:58 -05:00
Connor Turland
26dfcbf823 edge case where realtime server is passing empty object 2017-02-10 11:45:05 -05:00
Connor Turland
915defcd1b little fixes 2017-02-10 00:32:15 +00:00
Connor Turland
dde097ea75 all the good changes (#1065) 2017-02-09 16:53:19 -05:00
Devin Howard
3706cd83e7 helper function and notification setup for messages from the devs to be sent to all users (#1064)
* message from devs notification type

* helper function for messages from devs

* don't use find_by_email

* temporary fix
2017-02-09 10:37:35 -05:00
Connor Turland
575a3ec8bf Rename user_not_present_on_map.rB to user_not_present_on_map.rb 2017-02-05 22:09:51 -05:00
Connor Turland
b2bf9978aa Update ISSUE_TEMPLATE.md 2017-02-05 14:34:47 -05:00
Connor Turland
0441850504 Secret.convo (#1059)
* set up for using secret css/js

* testing

* add stuff

* final tweak for secret convos

* looks like its all working

* realized this change is just good all around

* minor touch ups

* only us for now

* no longer validate presence of xloc/yloc

* fix syntax issue
2017-02-05 14:30:23 -05:00
Connor Turland
3ae4072b5d add ability to keep metacode focus 2017-02-05 06:28:10 +00:00
Robert Best
00ecb0f6bb Make DEL key delete selected items (With confirmation still :P ) (#1058)
* add del key

* made DEL key into delete shortcut
2017-02-03 14:23:04 -05:00
Devin Howard
45a15da896 fix error in loading url titles 2017-02-01 12:37:50 -05:00
Devin Howard
a96c8ae75c fix bug 2017-01-31 23:44:10 -05:00
Devin Howard
a137c21d2d searchfields api parameter (#1054) 2017-01-28 16:53:54 -05:00
Connor Turland
952cf4e79f keep permission of topic/synapse in sync with map its deferring to from beginning (#1053)
* Update topic.rb

* Update synapse.rb
2017-01-28 16:40:41 -05:00
Devin Howard
53bc4ee1c8 fix mapper page (#1050) 2017-01-28 15:44:38 -05:00
Connor Turland
c60f7f4525 add Story, which is on metamaps, total is now 48 2017-01-28 01:04:23 -05:00
Connor Turland
8df2cd8732 fix metacode names 2017-01-28 01:01:20 -05:00
Devin Howard
2c6da79df3 redirect /explore to / (#1051) 2017-01-27 15:16:31 -05:00
Connor Turland
6e913efbae track pageloads with google analytics. fixes #1012 (#1048)
* track pageloads with google analytics. fixes #1012

* Update Router.js
2017-01-25 20:57:34 -08:00
Connor Turland
db81962c91 some c9 files to gitignore 2017-01-26 00:24:31 +00:00
Connor Turland
8330ef9679 treat cable sub/unsub as joined/left map. fixes #1035 (#1047) 2017-01-25 15:32:13 -08:00
Devin Howard
696ff396b0 file attachments in db (re: #124) (#1043)
* file attachments in db

* rubocop

* factor out a bunch of file types

* thumb and medium image styles"

* syntax error in concern

* markdown is also plaintext

* rubocop
2017-01-24 15:10:40 -05:00
Devin Howard
b16617286f revert back to jquery 1 to fix best in place 2017-01-23 19:50:59 -05:00
Devin Howard
fee011bba6 fix readme bullets 2017-01-23 19:37:50 -05:00
Devin Howard
d16709e8e7 fix codeclimate style issues (#1046)
* bunch of code climate fixes

* more
2017-01-23 19:30:13 -05:00
Devin Howard
0ad10c0f5a fix style of thumb button on map card (#1044) 2017-01-23 14:02:14 -05:00
Devin Howard
d11278b63b map rdf export (fixes #1015) (#1036)
* simple rdf export of maps

* register ttl mime type

* owl

* mm

* fix up export service

* implement base url thing whoo

* add more rdf fields

* fix rdf syntax errors

* hide unused fields in rdf

* some code climate fixes

* update ontology a bit more

* syntax fix

* typo
2017-01-22 16:42:04 -05:00
Devin Howard
2652d53e9b update ruby dependencies too (#1042)
* update rubygem dependencies

* update backbone

* brakeman fix

* brakeman

* ugh syntax fix
2017-01-22 16:41:51 -05:00
Devin Howard
dc8d274487 whoops, I guess we do need jquery in package.json 2017-01-22 14:07:04 -05:00
Devin Howard
2fd972ddce ajax queue (fixes #853) (#1037)
* jquery.ajaxq

* install jquery.ajaxq from npm

* patch ajaxq into Backbone code

* use ajaxq library with more github stars

* eslint
2017-01-22 13:50:34 -05:00
Devin Howard
bba8231e8c update npm dependencies (#1038)
* only one github dependency left

* update npm deps

* exact versions of npm deps
2017-01-21 15:37:14 -05:00
Devin Howard
1229e92feb fix bug in Debug.js 2017-01-21 13:34:39 -05:00
Devin Howard
ba3d5f07dd try to fix metamaps.debug 2017-01-21 13:09:26 -05:00
Devin Howard
d47d7e50e7 mark v3.2 on develop 2017-01-21 13:04:28 -05:00
Devin Howard
af2c6ebef1 split screenshot function/button into two parts (#1027)
* split screenshot function into 4 separate helpers

* screenshot download button in import dialog box

* thumbnail button inside map info box

* import blue button styling

* fight with styling to make the button at least appear

* add more text

* fix tooltip display

* automatically start downloading the screenshot

* eslint

* revamp GlobalUI.notifyUser

* fix object destructuring syntax

* fix
2017-01-19 14:50:08 -05:00
Devin Howard
a9f19815e4 fix api embed to use the correct serializers (fix #998) (#1029)
* use correct serializer for singular embeds in api (almost fixes #998)

* fix has_many api embeds too!

* unused arg
2017-01-19 14:49:40 -05:00
Devin Howard
460de840b6 redis server 2017-01-18 16:38:34 -05:00
Devin Howard
36ed85312e fix crontab 2017-01-18 16:29:52 -05:00
Devin Howard
991c4cabdb move node installation further up 2017-01-18 13:40:48 -05:00
Devin Howard
38004c1f1f fix npm install isntructions 2017-01-18 13:34:32 -05:00
Devin Howard
cd796f3ade gist for unicode error on db:setup 2017-01-18 13:25:50 -05:00
Devin Howard
c57015cb15 rvm install needs sudo 2017-01-18 13:16:33 -05:00
Devin Howard
9223295320 add node source 2017-01-18 13:14:39 -05:00
Devin Howard
b4bffbe427 database called metamaps, not metamap002 in example 2017-01-18 13:10:09 -05:00
Devin Howard
6296df1102 need postgres dev headers 2017-01-18 13:09:47 -05:00
Devin Howard
2e0acfc170 update docs 2017-01-18 12:04:40 -05:00
Devin Howard
99b21be27b tag v3.2 2017-01-16 14:18:49 -05:00
Devin Howard
2c60d7335c Merge branch 'develop' (v3.2) 2017-01-16 11:21:02 -05:00
Connor Turland
6f6e5bea06 Update README.md 2017-01-15 20:23:18 -05:00
Connor Turland
6f0d391aaa Update ISSUE_TEMPLATE.md 2017-01-15 20:17:30 -05:00
Connor Turland
b1a64c6e7a Update ISSUE_TEMPLATE.md 2017-01-15 20:16:53 -05:00
Connor Turland
59b3d254dd include new info zones 2017-01-14 01:35:48 -05:00
Devin Howard
f3539f54bf hotfix ugh 2017-01-11 23:36:30 -05:00
Devin Howard
75ccfb0ab3 hotfix map title in meta tags whoops 2017-01-11 23:32:13 -05:00
Devin Howard
7b5bd53c28 I think this will fix the meta tags (#1030) 2017-01-11 23:27:05 -05:00
Connor Turland
5302f03196 remove exclamation mark 2017-01-11 23:00:19 -05:00
Devin Howard
536c458981 add code climate to the readme 2017-01-11 22:42:32 -05:00
Devin Howard
f64612f99b add meta tags to maps (#1028) 2017-01-11 22:26:45 -05:00
Connor Turland
cbc38e0c93 emoji-mart styling fix 2017-01-11 14:02:11 -05:00
Devin Howard
42d671c05b stop replacing shortcodes/emoticon in the live NewMessage textarea (#1026) 2017-01-11 13:56:44 -05:00
Devin Howard
08109ee5de remove instructions from ImportDialogBox (#1022)
* remove instructions from ImportDialogBox

* link back to docs.metamaps.cc for import instructions
2017-01-11 13:50:37 -05:00
Connor Turland
0952c0f3c9 Bug/name.overflow (#1025)
* creator name was pushing 'view only' off card

* Update MapCard.js
2017-01-11 13:36:07 -05:00
Devin Howard
25b4d388de eslint commands and apply some style fixes (#1021)
* auto eslint and add commands for eslint

* eslint the entire frontend folder
2017-01-11 12:52:34 -05:00
Devin Howard
8b738f3d28 emoticons turned on by default 2017-01-10 22:05:04 -05:00
Devin Howard
da94cd0c8b systemd job in deploy docs 2017-01-10 18:00:46 -05:00
Devin Howard
e9e6b1dc09 tweak chat emoji (#1019) 2017-01-09 14:55:21 -05:00
Connor Turland
e84dfbaa33 fix message styling 2017-01-09 13:27:39 -05:00
Devin Howard
cb95e027c4 Add emoji to chat (#1013)
* add emoji picker unstyled

* rename junto.css.erb => junto.scss.erb

* junto scss-ified

* add emoji mart css

* emoji are replaced in the text area

* remove unicode emoji from messages before sending to db

* add emoji back into messages on display

* bigger font size on chat messages

* tweak styling

* codeclimate (eslint)
2017-01-09 13:14:20 -05:00
Connor Turland
8e50efb3c1 render messages nicer 2017-01-04 18:12:07 -05:00
Connor Turland
5ab5f6fec2 Update README.md 2017-01-04 17:17:53 -05:00
Devin Howard
cbf1ec3afb fix missing npm github dep (#1011) 2017-01-04 12:34:08 -05:00
Connor Turland
d3315d962d only render google analytics if a tracking code envvar is set 2017-01-04 12:08:12 -05:00
Connor Turland
ae05fb35d3 more config updates for heroku 2017-01-04 11:14:03 -05:00
Connor Turland
9e6ce90950 update config for heroku and prod 2017-01-04 11:08:32 -05:00
Connor Turland
3868910dde Stream map related events from rails server via actioncable instead of nodejs (#1010)
* actioncable needs puma not webrick

* add framework

* remove the old way

* send events from server to client

* get all events working

* clean up receivable

* map is polymorphic on message

* add the moved event

* make todo comments clear

* verify before streaming from map channel

* rubocop fixes

* wasn't set up correctly for nodejs realtime
2017-01-03 16:12:58 -05:00
Connor Turland
5c1261892f remove the one pixel gap between search input and icon 2016-12-26 21:03:22 -05:00
Connor Turland
9ada1ca935 remove exclamation mark 2016-12-26 17:19:56 -05:00
Connor Turland
df5cc4e1a8 remove exclamation mark 2016-12-26 17:15:42 -05:00
Connor Turland
ce073028c8 remove exclamation mark 2016-12-26 17:13:42 -05:00
Connor Turland
7d869d7b63 remove exclamation mark 2016-12-26 17:10:41 -05:00
Connor Turland
73e8f2d4c8 re-implement chat in react (#997)
* hidously mangle ChatView to start moving it to React

* fix up Realtime/index.js - should be good now?

* in theory this should compile

* ok the MapChat renders using react...

* move Handlers code into react - woot

* try reintegrating backbone

* fix wrapper styling

* chat box opens and closes properly

* make the unread count work

* organize more sanely

* refactor some of the ChatView functions

* removed management of chatview from room

* css can stop handling logic right about now

* makin things work

* don't need room here anymore

* set raw html in message

* make pending work

* removeParticipant when mapper left was broken

* re-enable scrolling, focus, and blur
2016-12-21 03:56:29 -05:00
Connor Turland
68f0e91259 track forks (#994)
* track forks

* update api and docs

* fix tests
2016-12-18 16:17:51 -05:00
Devin Howard
b07941834c v3.1 in initializers 2016-12-16 17:22:48 -05:00
Devin Howard
b914065bb3 Merge branch 'develop'; tag v3.1 2016-12-16 17:17:24 -05:00
Devin Howard
33fc27ffd1 Merge pull request #989 from metamaps/fix/travis
fix travis
2016-12-16 17:16:32 -05:00
Devin Howard
7ca7f0862f fix mapping spec 2016-12-16 17:09:23 -05:00
Devin Howard
c604e69d77 enable postgresql 9.4 in travis 2016-12-16 17:09:23 -05:00
Connor Turland
fb12c7e202 Track everything we need to reconstruct maps (#984)
* feature/more.events

* keep mapping.user as the creator

* cleanup cruft and include slack notifs

* capture topic and synapse updates, store the old values

* avoid the mapping gets deleted problem

* include an indicator of which values changed

* style cleanup

* remove the hack in favor of a legit way

* updated schema file
2016-12-16 16:51:52 -05:00
Devin Howard
9ab1c9c647 Merge pull request #932 from metamaps/feature/mailboxer
mailboxer notification centre
2016-12-16 16:41:37 -05:00
Connor Turland
28d960459e styling of notifs list 2016-12-16 16:25:14 -05:00
Connor Turland
ef84209de1 make it look better when its taking up the full screen width 2016-12-16 16:25:13 -05:00
Connor Turland
2d920cf66a add maps links to nav locations 2016-12-16 16:25:13 -05:00
Connor Turland
40a97a5ae9 these are output in the main layout file 2016-12-16 16:25:13 -05:00
Devin Howard
186129807e fix spec, bugs, style 2016-12-16 16:25:08 -05:00
Connor Turland
87228c27c1 Fix mailboxer + email bugs 2016-12-16 16:24:24 -05:00
Connor Turland
6d8392d2e7 Make mailboxer look good and update email templates 2016-12-16 16:24:01 -05:00
Devin Howard
0960159265 Mailboxer notification pagination 2016-12-16 16:23:49 -05:00
Devin Howard
88e98c7342 polish mailboxer with bug fixes 2016-12-16 16:23:32 -05:00
Devin Howard
3f6f020ce1 grant/deny buttons mark access request notifications as read 2016-12-16 16:23:30 -05:00
Devin Howard
8e958ec9a8 invite to edit notifications marked as read in system once map is visited 2016-12-16 16:23:30 -05:00
Devin Howard
9debcdde39 Integrate rails mailers with mailboxer 2016-12-16 16:23:17 -05:00
Robert Best
b4ad51e69d reactify notification icon 2016-12-16 16:21:40 -05:00
Devin Howard
9b95e91f1a more style tweaks + brakeman fix 2016-12-16 16:21:23 -05:00
Connor Turland
c46e85529e little style tweaks to css and content 2016-12-16 16:21:01 -05:00
Devin Howard
85408a14d3 Initial notification centre using mailboxer 2016-12-16 16:20:53 -05:00
Connor Turland
3b8a5d0c2e Update message_policy.rb (#973) 2016-12-14 13:23:40 -05:00
Robert Best
6f88c2a7eb Update ISSUE_TEMPLATE.md 2016-12-12 13:49:26 -05:00
Robert Best
f1e62fb6c1 Update ISSUE_TEMPLATE.md
changed multiplication symbol so that double-clicking number placeholders works again.
2016-12-12 13:47:00 -05:00
Robert Best
0c52188014 Update ISSUE_TEMPLATE.md
reduced whitespace
2016-12-12 13:30:56 -05:00
Robert Best
7c0e0f731f Update ISSUE_TEMPLATE.md
changed multiplication sign from asterisks to x, because markdown treats asterisks as special.
2016-12-12 11:35:59 -05:00
Devin Howard
1ba339b3be subset of synapse creation changes (#970)
* esc cancels topic and synapse creation now

* close topic/synapse creation on right click

* backspace and delete don't close synapse creation anymore

* hitting tab saves the synapse you're creating
2016-12-11 17:15:09 -05:00
Devin Howard
6129a27ecf hit Ctrl+A a second time to select all synapses, too (#968) 2016-12-11 16:21:36 -05:00
Devin Howard
d51e3f3b52 update npm deps, EXCEPT socket.io and backbone (#950)
* update npm dependencies (with some exceptions)

* update autolinker, remove underscore
2016-12-11 16:09:12 -05:00
Robert Best
1317186f63 Update ISSUE_TEMPLATE.md
changed all place-holders to underscores, they ae easier to double-click so as to select/replace.
2016-12-09 13:40:58 -05:00
Robert Best
d6527ea80e Create ISSUE_TEMPLATE.md 2016-12-09 12:20:30 -05:00
Connor Turland
a133702be2 Some topics and synapses were hidden from users erroneously (#944)
* ensure topics and synapses have their permission match the map they're deferring to

* update permission of topics and synapses as map perm changes, when defer_to_map

* try enabling count threshold on rubocop

* remove unused mk_permission functions

* change *_count methods to use delegate to save lines in map.rb model

* rubocop topic.rb
2016-12-06 16:46:46 -05:00
Devin Howard
d2074ada79 fix policy scope errors in search controller (#947) 2016-12-06 13:09:42 -05:00
Devin Howard
00286fcc29 tag v3.0.4 2016-12-06 12:38:06 -05:00
Devin Howard
01cd624bfa add polyfill so chrome 49 can upload map thumbnail screenshots (#946) 2016-12-06 12:36:06 -05:00
Connor Turland
a5f793fe54 fixup topic card template 2016-12-02 21:21:37 +00:00
Devin Howard
d1aa62d382 fix policy scope error (#941) 2016-11-30 11:46:09 -05:00
Devin Howard
3f161c1076 make topic titles have width of 25 chars (#933) 2016-11-29 11:00:14 -05:00
Devin Howard
4da3a9d55f hide mobile menu if browser is resized to full size (#937) 2016-11-28 13:53:29 -05:00
Devin Howard
90c5bc26fc Active.Mapper was being initialized twice, causing errors (#934) 2016-11-27 21:12:05 -05:00
Devin Howard
5d8ff3efce realtime shouldn't poll forever if the dev server isn't up (#931) 2016-11-24 14:40:14 -05:00
Devin Howard
95b8b52224 fix NoMethodError in topics#autocomplete_topic (#930) 2016-11-24 14:16:58 -05:00
Devin Howard
55853c60f4 update user model with fixes, including style and recentMetacodes algorithm (#922) 2016-11-13 14:29:07 -08:00
Devin Howard
5b90c38b22 Merge pull request #902 from metamaps/fix/schema
fix db schema
2016-11-13 14:24:31 -08:00
Devin Howard
c03d6dd5f6 remove in_trash from schema to match production 2016-11-13 17:21:42 -05:00
Devin Howard
51d5d77629 Merge pull request #929 from metamaps/fix/develop-bugs
fix some develop bugs, merge master, and move realtime port to .env
2016-11-09 21:14:48 -05:00
Devin Howard
ce2d462578 fix bugs on develop branch 2016-11-09 20:44:00 -05:00
Devin Howard
4533a0f2fe merge changes from metamapscc instance branch (#913)
* homepage video fallback

* public/50x.html

* remove blog from public/ html pages

* remove video file since it's on metamaps.cc server

* eslint
2016-11-09 09:34:10 -05:00
Devin Howard
5851d57eef Merge branch 'master' into develop 2016-11-09 09:29:30 -05:00
Connor Turland
e1441acde0 synapse wasn't updating calculated_permission 2016-11-08 19:50:08 +00:00
Connor Turland
d1f75c8c24 oops! don't change rt server port 2016-11-08 19:45:51 +00:00
Connor Turland
83b58d43d5 only remove user once they've left all maps 2016-11-08 19:42:48 +00:00
Devin Howard
3759851621 fix access#access route (#926) 2016-11-08 09:37:06 -08:00
Devin Howard
a176cdf231 eslint frontend folder (#923) 2016-11-07 15:25:08 -05:00
Devin Howard
9df974a037 strip whitespace from search terms (#919) 2016-11-07 14:58:53 -05:00
Devin Howard
bd4072f81c Merge pull request #707 from metamaps/feature/split-out-backbone
finish removing global Metamaps references from frontend code
2016-11-07 14:58:20 -05:00
Devin Howard
6a2646c9cd fix mailer specs (#921) 2016-11-07 14:56:35 -05:00
Devin Howard
2f4fe525ce Fix a bunch of errors and style issues 2016-11-07 14:55:20 -05:00
Devin Howard
518782e1c7 remove Metamaps.Erb 2016-11-07 14:55:20 -05:00
Devin Howard
7c9b6a2205 try to move all rails data into Metamaps.ServerData
Metamaps.Erb and currentPage and currentSection are still not in; should they be?
2016-11-07 14:55:20 -05:00
Devin Howard
8026969799 start storing data in ServerData 2016-11-07 14:55:17 -05:00
Devin Howard
4b500a4428 move Metamaps.Loading into node modules 2016-11-07 14:40:43 -05:00
Devin Howard
0778179ba7 eslint 2016-11-07 14:40:43 -05:00
Devin Howard
bfd23c6d32 split Backbone.js into a bunch of different files. Still more work to do to modularize it 2016-11-07 14:40:43 -05:00
Devin Howard
9cb3074245 rename Metamaps.Backbone to Metamaps.DataModel 2016-11-07 14:40:43 -05:00
Devin Howard
e4d193572f fix mailer specs 2016-11-07 14:40:25 -05:00
Connor Turland
0f85abfda2 add channel to webhooks (#915) 2016-11-05 09:34:50 -07:00
Connor Turland
887c3f7570 fixes #903 and #831 (#911) 2016-11-04 15:02:56 -07:00
Connor Turland
667f5653a7 topic descriptions from old data can be nil 2016-11-04 21:03:11 +00:00
Connor Turland
48b93b2269 change grant to allow. fixes #909 (#910) 2016-11-04 13:22:06 -07:00
Connor Turland
9ad4684825 firefox needs e.pageX not e.x (#906) 2016-11-02 19:20:06 -07:00
Devin Howard
f516e1e73d fix up deploy docs 2016-11-01 16:31:36 +08:00
Devin Howard
2588636837 tag v3.0.1 - bugfixes for 3.0 2016-11-01 16:06:05 +08:00
Devin Howard
644df6fcdc fix pasting urls (#901) 2016-11-01 16:01:34 +08:00
Devin Howard
c10a4f4837 fix exception notification backtrace (#898) 2016-11-01 10:05:45 +08:00
Devin Howard
304722b528 fix api docs (#897)
* fix api docs

* more rake => rails
2016-11-01 09:52:10 +08:00
Devin Howard
a9c67e70d4 move webhook and event serializers back (#899) 2016-11-01 09:46:44 +08:00
Connor Turland
ed3e4780d2 bug when topic was in more than 5 maps fixes #891 (#894) 2016-10-31 17:10:44 -04:00
Connor Turland
b013499c76 misnamed variable errors out maps search (#893) 2016-10-31 16:41:37 -04:00
Devin Howard
5270c5a611 Merge branch 'develop' for v3.0 2016-10-31 19:51:02 +08:00
Devin Howard
5cfa8ffdc7 bump version to 3.0 2016-10-31 19:48:07 +08:00
Devin Howard
814c1acc0f a few markdown style updates (#885)
* markdown block padding

* a few more markdown style updates
2016-10-31 15:38:16 +08:00
Devin Howard
62e2acdd52 add about lightbox again (#884)
* add about lightbox again

* fix about lightbox style
2016-10-31 15:38:09 +08:00
Connor Turland
151e96f803 Metamaps.Realtime.synapseRemoved is not a function (#880) 2016-10-29 12:10:13 -04:00
Devin Howard
bc1f212c93 fix tab/shift-tab for metacode selection (#879) 2016-10-30 00:08:51 +08:00
Devin Howard
b9190233b1 enable sucker punch for heroku (#878) 2016-10-29 23:38:17 +08:00
Devin Howard
5e0e44b436 supercharge the schemas (#874)
* fix map schema - woot it works

* update other schemas to include embeddable attrs

* update current user schema/examples
2016-10-29 22:58:31 +08:00
Devin Howard
1fbfd56d57 filter maps by user_id in api (#872)
* filter maps by user_id in api

* test user_id map filter

* update starred maps example to make starred true lol

* add user id to map schema/examples
2016-10-29 22:07:27 +08:00
Devin Howard
a32f98bde2 to_json should be as_json or there's bugs (#870)
* to_json should be as_json or there's bugs

* revert explore controller, it's better without

* revert search controller and some topic methods
2016-10-29 18:28:29 +08:00
Connor Turland
6cc827d11c wasn't updating calculated_permission when updating permission (#869) 2016-10-28 18:26:40 -04:00
Devin Howard
de16420796 fix logCanvasAttributes error (#863) 2016-10-28 15:20:39 +08:00
Devin Howard
e49e5c258a make synapse permissions depend on topic1 and topic2 (#839)
* deep change to synapse policy - is this ok?

* make synapse policy resilient to nil topic1/topic2/map

* use a transaction to handle authorization vs invalid record in synapse controller

* more synapse controller tests

* inline documentation

* fix policy(Synapse).create?
2016-10-28 11:03:59 +08:00
Devin Howard
4dc32d7d2e fix metacodes page scrolling (#862)
* fix metacodes page scrolling

use scheme from
http://brandonhilkert.com/blog/page-specific-javascript-in-rails/

* switch overflow:hidden to be on explicit controllers
2016-10-28 10:55:04 +08:00
Devin Howard
9d821c920b reorder API authentication precedence to be: token, oauth, cookie (#860)
* reorder authentication to be: token, then oauth, then cookie

* all APIs but tokens are accessible anonymously (so add mappings to the list)

* fix mapping order
2016-10-28 10:51:58 +08:00
Devin Howard
6b1220b533 overflow-y: hidden on body to prevent openLightbox from showing a scrollbar (#859) 2016-10-27 18:40:42 -04:00
Devin Howard
4f3d12d7a5 fix import promises (#858) 2016-10-27 14:03:18 +08:00
Devin Howard
7b4a072fd8 attempt to fix import problems (#852) 2016-10-26 20:34:22 +08:00
Devin Howard
175a3ee73e policy_scope on has_many relationships in serializers (#840)
* token overrides current user in api

* policy scope has_many relationships

* fix hard coded topics - whoops

* handle policy_scope returning nil in application serializer
2016-10-26 19:56:30 +08:00
Devin Howard
b13587456d fix coordsToPixels calls even more 2016-10-26 19:11:40 +08:00
Devin Howard
f023a18069 fix pixel stuff for real? (#851)
* fix getPastelColor function (I think)

* fix pixelsToCoords and coordsToPixels function calls

* update signature of coord/pixel functions in Util.spec.js
2016-10-26 19:04:00 +08:00
Devin Howard
e640048386 fix topic card title word break css (#844) 2016-10-26 17:01:05 +08:00
Devin Howard
98725b3ee4 fix getPastelColor function (I think) (#850)
* fix getPastelColor function (I think)

* fix pixelsToCoords and coordsToPixels function calls

* update signature of coord/pixel functions in Util.spec.js
2016-10-26 14:26:48 +08:00
Devin Howard
8a95262f2c allow anonymous users to GET api routes (#842)
* make map methods use ActiveRecord relations so they don't error on pundit

* test for logged out maps GET api

* open up GET routes on maps/topics/synapses and update api docs
2016-10-26 08:37:23 +08:00
Robert Best
ed89f80f49 Update README.md
some small tweaks to grammar and word choice
2016-10-25 14:24:10 -04:00
Devin Howard
47bca5907e add tests for Metamaps.Util (#825)
* decouple Util from other Metamaps modules

* first few Util tests

* more Util tests

* remove dead code

* eslint
2016-10-25 12:28:51 +08:00
Devin Howard
5163794698 anonymous users are nil, so need to remove the raise (#841) 2016-10-25 12:26:22 +08:00
Robert Best
0b6348e13f This fix closes the topic creation spinner when the map is panned. (Since, sometimes a click turns into a really small pan) (#828) 2016-10-24 11:48:34 -04:00
Connor Turland
ce1205f6d7 one more mapper card style fix 2016-10-24 14:35:23 +00:00
Connor Turland
96d25cc91d mapper profile mobile styling 2016-10-24 14:23:05 +00:00
Connor Turland
a9ef6feebd mapper page bug fix and styling 2016-10-24 13:42:26 +00:00
Connor Turland
98e2de68da oooh was using ineffective media queries for desktop 2016-10-23 16:49:16 -04:00
Connor Turland
4c68fd90ca set useful num for desc truncation on map cards 2016-10-23 16:30:54 -04:00
Connor Turland
cda0c21a0b make it responsive (#820) 2016-10-23 16:12:07 -04:00
Connor Turland
a44edbb17e better transition from map to explore 2016-10-23 11:44:20 -04:00
Connor Turland
aa96d074af dont show import on topic page 2016-10-23 11:21:38 -04:00
Connor Turland
4f9b9460ad don't block all right clicks 2016-10-23 11:12:43 -04:00
Devin Howard
a63cd02bc6 fix develop branch bug 2016-10-23 22:51:16 +08:00
Devin Howard
fb6c8a74a7 scoping on topic json properties (#813) 2016-10-23 22:11:38 +08:00
Devin Howard
5db8e27496 make metacode selector reliable after switching metacode sets (#816) 2016-10-23 22:11:26 +08:00
Devin Howard
87dc20fa50 stop showing map info box on topic view (#815) 2016-10-23 22:07:38 +08:00
Devin Howard
154257d062 fix Ctrl+A (#814) 2016-10-23 18:02:59 +08:00
Connor Turland
497c6ae017 spelling mistake fix 2016-10-22 15:16:55 -04:00
Connor Turland
9600983311 remove Connor thinking out loud comment 2016-10-22 11:07:50 -04:00
Connor Turland
cbcdd912c9 Comments were for non-redux scenario 2016-10-22 11:04:14 -04:00
Connor Turland
1d13da4ab5 Update README.md 2016-10-22 10:59:43 -04:00
Connor Turland
d359eb063a fixed the oauth redirect bug and a bit more (#796) 2016-10-22 16:46:39 +08:00
Connor Turland
4187dbd803 fix it up (#804) 2016-10-22 03:58:19 -04:00
Connor Turland
d549083cce prefer variable height lightbox over scrolling visually 2016-10-22 03:10:33 -04:00
Connor Turland
bc8660c83e remove about lightbox in prep for homepage redo and about page 2016-10-22 03:10:09 -04:00
Robert Best
c0b35280f6 Middle.mouse.click features (Open contained link & copy text to clipboard) (#792)
* changed the code to be based off of the current dev branch

* Update JIT.js

* Update Util.js

* Update JIT.js

A few logical operators were replaced with their stricter counterpart.

* Update JIT.js

* Update index.js

* Update Util.js
2016-10-22 02:58:13 -04:00
Connor Turland
31078c554e just make it 'tutorial' 2016-10-22 02:41:36 -04:00
Robert Best
ea20ba45b3 Merge pull request #738 from metamaps/window.resize.fix
Makes it so that resizing the browser window doesn't change the user's current location on the map
2016-10-22 02:12:54 -04:00
Robert Best
37b989c38e Update Listeners.js 2016-10-22 01:52:43 -04:00
Robert Best
759ec7845b cleaned up the window resize function even further 2016-10-22 05:50:31 +00:00
Robert Best
cfb8f51214 simplified the window resize function by adding a Util function that logs the canvas attributes. 2016-10-22 05:21:32 +00:00
Robert Best
1cd7e22c40 Merge commit '858ca66d69ed9e43f4d3a4ce6be288508cf4efa1' of github.com:metamaps/metamaps into window.resize.fix 2016-10-22 05:00:10 +00:00
Robert Best
ad1889dfc5 Merge branch 'develop' of github.com:metamaps/metamaps into window.resize.fix 2016-10-22 04:54:31 +00:00
Connor Turland
cbc8e6cdd4 the return of the infinite scroll (#795) 2016-10-22 00:15:10 -04:00
Connor Turland
f8556c30a5 resize every time it renders 2016-10-21 19:10:28 -04:00
Connor Turland
8af1e69460 undo last commit, don't need for rails5 2016-10-21 18:25:07 -04:00
Connor Turland
d1e8ecbf3b readd 12factor for debugging on heroku 2016-10-21 18:22:15 -04:00
Connor Turland
8e38469b1f add border radius to mapper list 2016-10-21 18:10:37 -04:00
Connor Turland
abb997c75c some quick fixes for realtime server after devins refactor 2016-10-21 18:04:18 -04:00
Connor Turland
be8efa6025 add card features (#793) 2016-10-21 17:42:21 -04:00
Robert Best
439527c464 Merge pull request #724 from metamaps/feature/edge.shift
Made it so that the map pans when you drag a selection of topics near the edge of the window
2016-10-21 17:03:25 -04:00
Robert Best
f68deea202 changed all logical operators to be more strict 2016-10-21 20:59:16 +00:00
Robert Best
b61cdb04fc Fixed the glitchyness, and made it suitable to merge with develop 2016-10-21 20:47:14 +00:00
Robert Best
5c67fcbff7 this time I actually addressed the conflicts 2016-10-21 20:38:17 +00:00
Robert Best
2eeb0a671f Fixed cherry pick conflicts 2016-10-21 20:26:42 +00:00
Connor Turland
fb427a11f0 [WIP] keep client fresh with junto info globally (#791)
* push state to client

* junto status is live on map cards XD

* little fixes

* eslint stuff

* remove object rest spread

* i think this makes realtime work without needing babel-node
2016-10-21 09:29:04 -04:00
Connor Turland
7a09a1c620 last commit broke stuff 2016-10-20 18:27:14 -04:00
Connor Turland
103ed5cbd7 max at 4, use fewer if not enough maps 2016-10-20 18:10:28 -04:00
Devin Howard
b1a7e548a2 add email/twitter links 2016-10-20 07:01:15 +08:00
Connor Turland
52c340b8f5 center the explore maps div! (#787)
* ooh baby

* will add displayStyle again later if we actually build it
2016-10-19 14:40:42 -04:00
Connor Turland
9299ca5f2c dont do translate with arrow keys till we can block conflicts 2016-10-19 17:47:10 +00:00
Devin Howard
261ed49977 replace uservoice with docs.metamaps.cc + Hylo (#777)
* replace uservoice with docs.metamaps.cc + Hylo

* re-add the feedback tab as link to hylo
2016-10-19 13:39:57 -04:00
Devin Howard
e2d9b6aef2 Merge pull request #786 from metamaps/fix/empty-autocomplete
fix topic autocomplete controller action
2016-10-19 22:16:26 +08:00
Devin Howard
1042fb020d Merge pull request #778 from metamaps/feature/auto-copy-invite-link
copy share invite link to clipboard automatically where possible
2016-10-19 22:15:21 +08:00
Devin Howard
7f1c04015e fix topic autocomplete controller action 2016-10-19 22:10:38 +08:00
Devin Howard
f75d5253b3 Merge pull request #781 from metamaps/fix/registration
clean up and fix devise code
2016-10-19 14:36:39 +08:00
Devin Howard
bb6566a45e clean up and fix devise code 2016-10-19 12:40:52 +08:00
Devin Howard
2529e0d44f copy share invite link to clipboard automatically where possible 2016-10-19 11:07:20 +08:00
Connor Turland
139837e997 restructure realtime server for clarity (#780)
* restructure realtime server for clarity

* better indenting on signal.js

* don't need it because socketioconnection is being imported now
2016-10-18 20:29:21 -04:00
Connor Turland
d8cd536a95 too much logging 2016-10-18 14:10:41 -04:00
Connor Turland
29913cd10b fix for heroku 2016-10-18 14:08:10 -04:00
Connor Turland
d004e98ada holy insanity realtime refactor (#779)
* all the refactoring

* make it all work
2016-10-18 12:34:19 -04:00
Connor Turland
d2e097fd05 add webrtc logging 2016-10-17 22:59:28 -04:00
Connor Turland
fe0da255dd [WIP] display whether a map is live on every map card (#775)
* tidy up

* checkwhethertosave was no longer correct
2016-10-17 22:27:15 -04:00
Devin Howard
6e75274737 access request tests (#772)
* access request tests

* map mailer spec update
2016-10-17 10:53:53 -04:00
Devin Howard
6c9d464a9f Global => All Maps (#774) 2016-10-17 10:53:33 -04:00
Connor Turland
517cfcb913 remove static lib files in favor of npm ones (#773)
* remove static lib files in favor of npm ones

* update howler to work correctly

* patch npm modules to not use window
2016-10-17 10:39:08 -04:00
Devin Howard
0ee1b3284a fix check-canvas-support require 2016-10-17 13:47:42 +08:00
Devin Howard
b976c13db2 Merge pull request #770 from metamaps/feature/remove-canvas-function
remove check-canvas-support.js
2016-10-17 13:40:34 +08:00
Connor Turland
c0955d7c5e multiple policy issues (#771)
* multiple policy errors

* make some things more explicit
2016-10-17 01:20:48 -04:00
Connor Turland
332bb2ec08 Map Card changes (#769)
* map card rewrite underway

* star count

* css fix
2016-10-16 23:46:55 -04:00
Devin Howard
179849b639 remove check-canvas-support.js 2016-10-17 11:42:11 +08:00
Devin Howard
4f6dae304c Merge pull request #768 from metamaps/feature/default-rails-scripts
add scripts from default rails install
2016-10-17 10:51:47 +08:00
Devin Howard
3479fb7ff7 Merge pull request #767 from metamaps/fix/schema
schema update
2016-10-17 10:46:57 +08:00
Devin Howard
c113253fc5 add scripts from default rails install 2016-10-17 10:42:14 +08:00
Devin Howard
e46aa54ba3 schema update 2016-10-17 10:39:46 +08:00
Connor Turland
4602ded8a4 access requests (#762)
* start on access requests

* set up access requests further

* set default values for approved and answered
2016-10-16 20:22:00 -04:00
Devin Howard
14ea18a967 Merge pull request #764 from metamaps/fix/import-dialog-box
fix file upload box
2016-10-16 22:11:36 +08:00
Devin Howard
8180a8cc71 fix file upload box 2016-10-14 14:45:17 +08:00
Devin Howard
da5191171a Merge pull request #760 from metamaps/feature/mailer-tests
tests for map_mailer.rb
2016-10-14 11:24:31 +08:00
Devin Howard
26a8cddd14 mailer spec 2016-10-13 18:45:54 +08:00
Devin Howard
407ac1f29c more simplecov groups 2016-10-13 16:48:54 +08:00
Devin Howard
fc2849824f fix js syntax error 2016-10-13 16:48:46 +08:00
Devin Howard
6f3c74b7f1 token policy fix 2016-10-13 15:21:27 +08:00
Devin Howard
c3dbd59280 Merge pull request #758 from metamaps/feature/remove-gems
don't need coffeescript
2016-10-13 14:55:04 +08:00
Devin Howard
0e7e649f56 don't need coffeescript, tunemygc fails on Windows 2016-10-13 14:52:59 +08:00
Devin Howard
6e03132f1b fix spec 2016-10-13 14:51:58 +08:00
Devin Howard
b2a4acc99d make default category explicit in import.js 2016-10-13 14:24:08 +08:00
Devin Howard
7eae8deacb revamp HTML template a bit for api docs (#757)
* my_tokens endpoint moved to normal index

* remove secured_by from metacodes/users

* ch ch ch changes

* mess with template

* fix securedBy

* convenience open

* gross authentication notes at the top of every endpoint

* better ordering

* move login tutorials into security tab

* oauth tutorial

* getting closer

* remove unneeded Endpoints header

* ok looks OK
2016-10-12 13:54:43 -04:00
Devin Howard
62c489cba7 suggesting api doc updates (#756) 2016-10-12 12:22:38 -04:00
Devin Howard
3051723bcf [WIP] add markdown getting started page to api docs (#752)
* add markdown getting started page to api docs. TODO section 3

* Update getting-started.md
2016-10-11 12:08:31 -04:00
Devin Howard
858ca66d69 eslint updates 2016-10-10 17:22:22 +08:00
Devin Howard
a0c0dcbc79 Merge pull request #753 from metamaps/fix/screenshot-no-file
fix screenshot no file error
2016-10-10 13:01:50 +08:00
Devin Howard
6e6d33abbe fix screenshot no file error 2016-10-10 12:12:42 +08:00
Robert Best
b6da38e29e Update Listeners.js
Simplified based on Connor's suggestion about usage of variables.
2016-10-07 02:36:41 -04:00
Robert Best
3e4ff59a82 Update Listeners.js 2016-10-06 23:58:57 -04:00
Robert Best
08f89ee630 Update Listeners.js 2016-10-06 23:56:39 -04:00
Robert Best
b978247785 Put all the code within the if statement 2016-10-07 00:51:52 +00:00
Robert Best
0aeb6caadb Makes it so that resizing the browser window doesn't change the user's location on the map 2016-10-07 00:33:16 +00:00
Devin Howard
eaffc346fd v2.9.1 2016-09-13 14:30:09 +08:00
558 changed files with 22247 additions and 24861 deletions

1
.agignore Normal file
View file

@ -0,0 +1 @@
app/assets/javascripts/metamaps.secret.bundle.js

View file

@ -8,6 +8,7 @@ engines:
enabled: true enabled: true
config: config:
languages: languages:
count_threshold: 3 # rule of three
ruby: ruby:
mass_threshold: 36 # default: 18 mass_threshold: 36 # default: 18
javascript: javascript:
@ -19,6 +20,8 @@ engines:
enabled: true enabled: true
rubocop: rubocop:
enabled: true enabled: true
exclude_fingerprints:
- 74f18007b920e8d81148d2f6a2756534
ratings: ratings:
paths: paths:
- 'Gemfile.lock' - 'Gemfile.lock'

View file

@ -20,6 +20,7 @@ module.exports = {
"rules": { "rules": {
"react/jsx-uses-react": [2], "react/jsx-uses-react": [2],
"react/jsx-uses-vars": [2], "react/jsx-uses-vars": [2],
"space-before-function-paren": [2, "never"],
"yoda": [2, "never", { "exceptRange": true }] "yoda": [2, "never", { "exceptRange": true }]
} }
} }

View file

@ -1,10 +1,14 @@
# Node JS env
export NODE_REALTIME_PORT='5000' # should match REALTIME_SERVER, below
# Rails env
export DB_USERNAME='postgres' export DB_USERNAME='postgres'
export DB_PASSWORD='3112' export DB_PASSWORD='3112'
export DB_HOST='localhost' export DB_HOST='localhost'
export DB_PORT='5432' export DB_PORT='5432'
export DB_NAME='metamap002' export DB_NAME='metamaps'
export REALTIME_SERVER='http://localhost:5001' export REALTIME_SERVER='http://localhost:5000'
export MAILER_DEFAULT_URL='localhost:3000' export MAILER_DEFAULT_URL='localhost:3000'
export DEVISE_MAILER_SENDER='team@metamaps.cc' export DEVISE_MAILER_SENDER='team@metamaps.cc'
@ -18,7 +22,6 @@ export SECRET_KEY_BASE='267c8a84f63963282f45bc3010eaddf027abfab58fc759d6e239c800
# export S3_BUCKET_NAME # export S3_BUCKET_NAME
# export AWS_ACCESS_KEY_ID # export AWS_ACCESS_KEY_ID
# export AWS_SECRET_ACCESS_KEY # export AWS_SECRET_ACCESS_KEY
# export SSO_KEY
# #
# export SMTP_DOMAIN # export SMTP_DOMAIN
# export SMTP_PASSWORD # export SMTP_PASSWORD

4
.gitignore vendored
View file

@ -15,6 +15,7 @@ app/assets/javascripts/webpacked
#secrets and config #secrets and config
.env .env
*.swp
# Ignore bundler config # Ignore bundler config
.bundle .bundle
@ -22,6 +23,7 @@ app/assets/javascripts/webpacked
# Ignore all logfiles and tempfiles. # Ignore all logfiles and tempfiles.
log/*.log log/*.log
tmp tmp
.tmp
coverage coverage
@ -29,3 +31,5 @@ coverage
*/.DS_Store */.DS_Store
.DS_Store? .DS_Store?
.vagrant .vagrant
gentle/
startserver.sh

View file

@ -12,10 +12,18 @@ Rails:
Enabled: true Enabled: true
Metrics/LineLength: Metrics/LineLength:
Max: 100 Max: 120
Metrics/AbcSize: Metrics/AbcSize:
Max: 16 Max: 16
Style/Documentation: Style/Documentation:
Enabled: false Enabled: false
Style/EmptyMethod:
EnforcedStyle: expanded
# I like this cop, but occasionally code is more readable without a guard clause,
# and I don't want to write rubocop:disable comments every time that happens
Style/GuardClause:
Enabled: false

View file

@ -1,3 +1,7 @@
if ENV['COVERAGE'] == 'on' if ENV['COVERAGE'] == 'on'
SimpleCov.start 'rails' SimpleCov.start 'rails' do
add_group 'Policies', 'app/policies'
add_group 'Services', 'app/services'
add_group 'Serializers', 'app/serializers'
end
end end

View file

@ -22,3 +22,4 @@ script:
addons: addons:
code_climate: code_climate:
repo_token: 479d3bf56798fbc7fff3fc8151a5ed09e8ac368fd5af332c437b9e07dbebb44e repo_token: 479d3bf56798fbc7fff3fc8151a5ed09e8ac368fd5af332c437b9e07dbebb44e
postgresql: "9.4"

18
Gemfile
View file

@ -1,11 +1,12 @@
# frozen_string_literal: true # frozen_string_literal: true
source 'https://rubygems.org' source 'https://rubygems.org'
ruby '2.3.0' ruby '2.3.0'
gem 'rails', '~> 5.0.0' gem 'rails', '~> 5.0.0'
gem 'active_model_serializers' gem 'active_model_serializers'
gem 'aws-sdk' gem 'aws-sdk', '~> 2.7.0'
gem 'best_in_place' gem 'best_in_place'
gem 'delayed_job' gem 'delayed_job'
gem 'delayed_job_active_record' gem 'delayed_job_active_record'
@ -16,38 +17,41 @@ gem 'exception_notification'
gem 'httparty' gem 'httparty'
gem 'json' gem 'json'
gem 'kaminari' gem 'kaminari'
gem 'mailboxer'
gem 'paperclip' gem 'paperclip'
gem 'pg' gem 'pg'
gem 'puma'
gem 'pundit' gem 'pundit'
gem 'pundit_extra' gem 'pundit_extra'
gem 'rack-attack' gem 'rack-attack'
gem 'rack-cors' gem 'rack-cors'
gem 'redis' gem 'redis', '~> 3.3.3'
gem 'slack-notifier' gem 'slack-notifier'
gem 'snorlax' gem 'snorlax'
gem 'uservoice-ruby' gem 'sucker_punch'
# asset stuff # asset stuff
gem 'coffee-rails'
gem 'jquery-rails' gem 'jquery-rails'
gem 'jquery-ui-rails' gem 'jquery-ui-rails'
gem 'sass-rails' gem 'sass-rails'
gem 'uglifier' gem 'uglifier'
group :test do group :test do
gem 'factory_girl_rails' gem 'brakeman', require: false
gem 'factory_bot_rails'
gem 'json-schema' gem 'json-schema'
gem 'rspec-rails' gem 'rspec-rails'
gem 'shoulda-matchers' gem 'shoulda-matchers'
gem 'simplecov', require: false gem 'simplecov', require: false
gem 'brakeman', require: false
end end
group :development, :test do group :development, :test do
gem 'better_errors' gem 'better_errors'
gem 'binding_of_caller' gem 'binding_of_caller'
gem 'faker'
gem 'pry-byebug' gem 'pry-byebug'
gem 'pry-rails' gem 'pry-rails'
gem 'rubocop', '~> 0.48.1' # match code climate https://github.com/tootsuite/mastodon/issues/1758
gem 'timecop'
gem 'tunemygc' gem 'tunemygc'
gem 'rubocop'
end end

View file

@ -1,274 +1,297 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
actioncable (5.0.0.1) actioncable (5.0.5)
actionpack (= 5.0.0.1) actionpack (= 5.0.5)
nio4r (~> 1.2) nio4r (>= 1.2, < 3.0)
websocket-driver (~> 0.6.1) websocket-driver (~> 0.6.1)
actionmailer (5.0.0.1) actionmailer (5.0.5)
actionpack (= 5.0.0.1) actionpack (= 5.0.5)
actionview (= 5.0.0.1) actionview (= 5.0.5)
activejob (= 5.0.0.1) activejob (= 5.0.5)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
actionpack (5.0.0.1) actionpack (5.0.5)
actionview (= 5.0.0.1) actionview (= 5.0.5)
activesupport (= 5.0.0.1) activesupport (= 5.0.5)
rack (~> 2.0) rack (~> 2.0)
rack-test (~> 0.6.3) rack-test (~> 0.6.3)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2) rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.0.0.1) actionview (5.0.5)
activesupport (= 5.0.0.1) activesupport (= 5.0.5)
builder (~> 3.1) builder (~> 3.1)
erubis (~> 2.7.0) erubis (~> 2.7.0)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2) rails-html-sanitizer (~> 1.0, >= 1.0.3)
active_model_serializers (0.10.2) active_model_serializers (0.10.6)
actionpack (>= 4.1, < 6) actionpack (>= 4.1, < 6)
activemodel (>= 4.1, < 6) activemodel (>= 4.1, < 6)
jsonapi (~> 0.1.1.beta2) case_transform (>= 0.2)
railties (>= 4.1, < 6) jsonapi-renderer (>= 0.1.1.beta1, < 0.2)
activejob (5.0.0.1) activejob (5.0.5)
activesupport (= 5.0.0.1) activesupport (= 5.0.5)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (5.0.0.1) activemodel (5.0.5)
activesupport (= 5.0.0.1) activesupport (= 5.0.5)
activerecord (5.0.0.1) activerecord (5.0.5)
activemodel (= 5.0.0.1) activemodel (= 5.0.5)
activesupport (= 5.0.0.1) activesupport (= 5.0.5)
arel (~> 7.0) arel (~> 7.0)
activesupport (5.0.0.1) activesupport (5.0.5)
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7) i18n (~> 0.7)
minitest (~> 5.1) minitest (~> 5.1)
tzinfo (~> 1.1) tzinfo (~> 1.1)
addressable (2.3.8) addressable (2.5.2)
arel (7.1.2) public_suffix (>= 2.0.2, < 4.0)
arel (7.1.4)
ast (2.3.0) ast (2.3.0)
aws-sdk (2.6.3) aws-sdk (2.7.0)
aws-sdk-resources (= 2.6.3) aws-sdk-resources (= 2.7.0)
aws-sdk-core (2.6.3) aws-sdk-core (2.7.0)
aws-sigv4 (~> 1.0)
jmespath (~> 1.0) jmespath (~> 1.0)
aws-sdk-resources (2.6.3) aws-sdk-resources (2.7.0)
aws-sdk-core (= 2.6.3) aws-sdk-core (= 2.7.0)
aws-sigv4 (1.0.2)
bcrypt (3.1.11) bcrypt (3.1.11)
best_in_place (3.1.0) best_in_place (3.1.1)
actionpack (>= 3.2) actionpack (>= 3.2)
railties (>= 3.2) railties (>= 3.2)
better_errors (2.1.1) better_errors (2.3.0)
coderay (>= 1.0.0) coderay (>= 1.0.0)
erubis (>= 2.6.6) erubi (>= 1.0.0)
rack (>= 0.9.0) rack (>= 0.9.0)
binding_of_caller (0.7.2) binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1) debug_inspector (>= 0.0.1)
brakeman (3.4.0) brakeman (3.7.2)
builder (3.2.2) builder (3.2.3)
byebug (9.0.5) byebug (9.1.0)
climate_control (0.0.3) carrierwave (1.1.0)
activesupport (>= 3.0) activemodel (>= 4.0.0)
activesupport (>= 4.0.0)
mime-types (>= 1.16)
case_transform (0.2)
activesupport
climate_control (0.2.0)
cocaine (0.5.8) cocaine (0.5.8)
climate_control (>= 0.0.3, < 1.0) climate_control (>= 0.0.3, < 1.0)
coderay (1.1.1) coderay (1.1.2)
coffee-rails (4.2.1) concurrent-ruby (1.0.5)
coffee-script (>= 2.2.0) debug_inspector (0.0.3)
railties (>= 4.0.0, < 5.2.x) delayed_job (4.1.3)
coffee-script (2.4.1) activesupport (>= 3.0, < 5.2)
coffee-script-source delayed_job_active_record (4.1.2)
execjs activerecord (>= 3.0, < 5.2)
coffee-script-source (1.10.0)
concurrent-ruby (1.0.2)
debug_inspector (0.0.2)
delayed_job (4.1.2)
activesupport (>= 3.0, < 5.1)
delayed_job_active_record (4.1.1)
activerecord (>= 3.0, < 5.1)
delayed_job (>= 3.0, < 5) delayed_job (>= 3.0, < 5)
devise (4.2.0) devise (4.3.0)
bcrypt (~> 3.0) bcrypt (~> 3.0)
orm_adapter (~> 0.1) orm_adapter (~> 0.1)
railties (>= 4.1.0, < 5.1) railties (>= 4.1.0, < 5.2)
responders responders
warden (~> 1.2.3) warden (~> 1.2.3)
diff-lcs (1.2.5) diff-lcs (1.3)
docile (1.1.5) docile (1.1.5)
doorkeeper (4.2.0) doorkeeper (4.2.6)
railties (>= 4.2) railties (>= 4.2)
dotenv (2.1.1) dotenv (2.2.1)
dotenv-rails (2.1.1) dotenv-rails (2.2.1)
dotenv (= 2.1.1) dotenv (= 2.2.1)
railties (>= 4.0, < 5.1) railties (>= 3.2, < 5.2)
erubi (1.6.1)
erubis (2.7.0) erubis (2.7.0)
exception_notification (4.2.1) exception_notification (4.2.2)
actionmailer (>= 4.0, < 6) actionmailer (>= 4.0, < 6)
activesupport (>= 4.0, < 6) activesupport (>= 4.0, < 6)
execjs (2.7.0) execjs (2.7.0)
ezcrypto (0.7.2) factory_bot (4.8.2)
factory_girl (4.7.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
factory_girl_rails (4.7.0) factory_bot_rails (4.8.2)
factory_girl (~> 4.7.0) factory_bot (~> 4.8.2)
railties (>= 3.0.0) railties (>= 3.0.0)
globalid (0.3.7) faker (1.8.4)
activesupport (>= 4.1.0) i18n (~> 0.5)
httparty (0.14.0) ffi (1.9.18)
globalid (0.4.0)
activesupport (>= 4.2.0)
httparty (0.15.6)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
i18n (0.7.0) i18n (0.9.3)
concurrent-ruby (~> 1.0)
jmespath (1.3.1) jmespath (1.3.1)
jquery-rails (4.2.1) jquery-rails (4.3.1)
rails-dom-testing (>= 1, < 3) rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0) railties (>= 4.2.0)
thor (>= 0.14, < 2.0) thor (>= 0.14, < 2.0)
jquery-ui-rails (5.0.5) jquery-ui-rails (6.0.1)
railties (>= 3.2.16) railties (>= 3.2.16)
json (1.8.3) json (2.1.0)
json-schema (2.6.2) json-schema (2.8.0)
addressable (~> 2.3.8) addressable (>= 2.4)
jsonapi (0.1.1.beta2) jsonapi-renderer (0.1.3)
json (~> 1.8) kaminari (1.0.1)
kaminari (0.17.0) activesupport (>= 4.1.0)
actionpack (>= 3.0.0) kaminari-actionview (= 1.0.1)
activesupport (>= 3.0.0) kaminari-activerecord (= 1.0.1)
kaminari-core (= 1.0.1)
kaminari-actionview (1.0.1)
actionview
kaminari-core (= 1.0.1)
kaminari-activerecord (1.0.1)
activerecord
kaminari-core (= 1.0.1)
kaminari-core (1.0.1)
loofah (2.0.3) loofah (2.0.3)
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
mail (2.6.4) mail (2.6.6)
mime-types (>= 1.16, < 4) mime-types (>= 1.16, < 4)
mailboxer (0.15.1)
carrierwave (>= 0.5.8)
rails (>= 5.0.0)
method_source (0.8.2) method_source (0.8.2)
mime-types (3.1) mime-types (3.1)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521) mime-types-data (3.2016.0521)
mimemagic (0.3.2) mimemagic (0.3.2)
mini_portile2 (2.1.0) mini_portile2 (2.3.0)
minitest (5.9.1) minitest (5.11.1)
multi_xml (0.5.5) multi_xml (0.6.0)
nio4r (1.2.1) nio4r (2.1.0)
nokogiri (1.6.8) nokogiri (1.8.1)
mini_portile2 (~> 2.1.0) mini_portile2 (~> 2.3.0)
pkg-config (~> 1.1.7)
oauth (0.5.1)
orm_adapter (0.5.0) orm_adapter (0.5.0)
paperclip (5.1.0) paperclip (5.2.0)
activemodel (>= 4.2.0) activemodel (>= 4.2.0)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
cocaine (~> 0.5.5) cocaine (~> 0.5.5)
mime-types mime-types
mimemagic (~> 0.3.0) mimemagic (~> 0.3.0)
parser (2.3.1.4) parser (2.4.0.2)
ast (~> 2.2) ast (~> 2.3)
pg (0.19.0) pg (0.21.0)
pkg-config (1.1.7)
powerpack (0.1.1) powerpack (0.1.1)
pry (0.10.4) pry (0.10.4)
coderay (~> 1.1.0) coderay (~> 1.1.0)
method_source (~> 0.8.1) method_source (~> 0.8.1)
slop (~> 3.4) slop (~> 3.4)
pry-byebug (3.4.0) pry-byebug (3.5.0)
byebug (~> 9.0) byebug (~> 9.1)
pry (~> 0.10) pry (~> 0.10)
pry-rails (0.3.4) pry-rails (0.3.6)
pry (>= 0.9.10) pry (>= 0.10.4)
public_suffix (3.0.0)
puma (3.10.0)
pundit (1.1.0) pundit (1.1.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
pundit_extra (0.3.0) pundit_extra (0.3.0)
rack (2.0.1) rack (2.0.3)
rack-attack (5.0.1) rack-attack (5.0.1)
rack rack
rack-cors (0.4.0) rack-cors (1.0.1)
rack-test (0.6.3) rack-test (0.6.3)
rack (>= 1.0) rack (>= 1.0)
rails (5.0.0.1) rails (5.0.5)
actioncable (= 5.0.0.1) actioncable (= 5.0.5)
actionmailer (= 5.0.0.1) actionmailer (= 5.0.5)
actionpack (= 5.0.0.1) actionpack (= 5.0.5)
actionview (= 5.0.0.1) actionview (= 5.0.5)
activejob (= 5.0.0.1) activejob (= 5.0.5)
activemodel (= 5.0.0.1) activemodel (= 5.0.5)
activerecord (= 5.0.0.1) activerecord (= 5.0.5)
activesupport (= 5.0.0.1) activesupport (= 5.0.5)
bundler (>= 1.3.0, < 2.0) bundler (>= 1.3.0)
railties (= 5.0.0.1) railties (= 5.0.5)
sprockets-rails (>= 2.0.0) sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.1) rails-dom-testing (2.0.3)
activesupport (>= 4.2.0, < 6.0) activesupport (>= 4.2.0)
nokogiri (~> 1.6.0) nokogiri (>= 1.6)
rails-html-sanitizer (1.0.3) rails-html-sanitizer (1.0.3)
loofah (~> 2.0) loofah (~> 2.0)
railties (5.0.0.1) railties (5.0.5)
actionpack (= 5.0.0.1) actionpack (= 5.0.5)
activesupport (= 5.0.0.1) activesupport (= 5.0.5)
method_source method_source
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rainbow (2.1.0) rainbow (2.2.2)
rake (11.3.0) rake
redis (3.3.1) rake (12.3.0)
responders (2.3.0) rb-fsevent (0.10.2)
railties (>= 4.2.0, < 5.1) rb-inotify (0.9.10)
rspec-core (3.5.3) ffi (>= 0.5.0, < 2)
rspec-support (~> 3.5.0) redis (3.3.3)
rspec-expectations (3.5.0) responders (2.4.0)
actionpack (>= 4.2.0, < 5.3)
railties (>= 4.2.0, < 5.3)
rspec-core (3.6.0)
rspec-support (~> 3.6.0)
rspec-expectations (3.6.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0) rspec-support (~> 3.6.0)
rspec-mocks (3.5.0) rspec-mocks (3.6.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0) rspec-support (~> 3.6.0)
rspec-rails (3.5.2) rspec-rails (3.6.1)
actionpack (>= 3.0) actionpack (>= 3.0)
activesupport (>= 3.0) activesupport (>= 3.0)
railties (>= 3.0) railties (>= 3.0)
rspec-core (~> 3.5.0) rspec-core (~> 3.6.0)
rspec-expectations (~> 3.5.0) rspec-expectations (~> 3.6.0)
rspec-mocks (~> 3.5.0) rspec-mocks (~> 3.6.0)
rspec-support (~> 3.5.0) rspec-support (~> 3.6.0)
rspec-support (3.5.0) rspec-support (3.6.0)
rubocop (0.43.0) rubocop (0.48.1)
parser (>= 2.3.1.1, < 3.0) parser (>= 2.3.3.1, < 3.0)
powerpack (~> 0.1) powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0) rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1) unicode-display_width (~> 1.0, >= 1.0.1)
ruby-progressbar (1.8.1) ruby-progressbar (1.9.0)
sass (3.4.22) sass (3.5.1)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sass-rails (5.0.6) sass-rails (5.0.6)
railties (>= 4.0.0, < 6) railties (>= 4.0.0, < 6)
sass (~> 3.1) sass (~> 3.1)
sprockets (>= 2.8, < 4.0) sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0) sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3) tilt (>= 1.1, < 3)
shoulda-matchers (3.1.1) shoulda-matchers (3.1.2)
activesupport (>= 4.0.0) activesupport (>= 4.0.0)
simplecov (0.12.0) simplecov (0.15.0)
docile (~> 1.1.0) docile (~> 1.1.0)
json (>= 1.8, < 3) json (>= 1.8, < 3)
simplecov-html (~> 0.10.0) simplecov-html (~> 0.10.0)
simplecov-html (0.10.0) simplecov-html (0.10.2)
slack-notifier (1.5.1) slack-notifier (2.3.1)
slop (3.6.0) slop (3.6.0)
snorlax (0.1.6) snorlax (0.1.6)
rails (> 4.1) rails (> 4.1)
sprockets (3.7.0) sprockets (3.7.1)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
rack (> 1, < 3) rack (> 1, < 3)
sprockets-rails (3.2.0) sprockets-rails (3.2.1)
actionpack (>= 4.0) actionpack (>= 4.0)
activesupport (>= 4.0) activesupport (>= 4.0)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
thor (0.19.1) sucker_punch (2.0.3)
thread_safe (0.3.5) concurrent-ruby (~> 1.0.0)
tilt (2.0.5) thor (0.20.0)
tunemygc (1.0.68) thread_safe (0.3.6)
tzinfo (1.2.2) tilt (2.0.8)
timecop (0.9.1)
tunemygc (1.0.69)
tzinfo (1.2.4)
thread_safe (~> 0.1) thread_safe (~> 0.1)
uglifier (3.0.2) uglifier (3.2.0)
execjs (>= 0.3.0, < 3) execjs (>= 0.3.0, < 3)
unicode-display_width (1.1.1) unicode-display_width (1.3.0)
uservoice-ruby (0.0.11) warden (1.2.7)
ezcrypto (>= 0.7.2)
json (>= 1.7.5)
oauth (>= 0.4.7)
warden (1.2.6)
rack (>= 1.0) rack (>= 1.0)
websocket-driver (0.6.4) websocket-driver (0.6.5)
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2) websocket-extensions (0.1.2)
@ -277,48 +300,51 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
active_model_serializers active_model_serializers
aws-sdk aws-sdk (~> 2.7.0)
best_in_place best_in_place
better_errors better_errors
binding_of_caller binding_of_caller
brakeman brakeman
coffee-rails
delayed_job delayed_job
delayed_job_active_record delayed_job_active_record
devise devise
doorkeeper doorkeeper
dotenv-rails dotenv-rails
exception_notification exception_notification
factory_girl_rails factory_bot_rails
faker
httparty httparty
jquery-rails jquery-rails
jquery-ui-rails jquery-ui-rails
json json
json-schema json-schema
kaminari kaminari
mailboxer
paperclip paperclip
pg pg
pry-byebug pry-byebug
pry-rails pry-rails
puma
pundit pundit
pundit_extra pundit_extra
rack-attack rack-attack
rack-cors rack-cors
rails (~> 5.0.0) rails (~> 5.0.0)
redis redis (~> 3.3.3)
rspec-rails rspec-rails
rubocop rubocop (~> 0.48.1)
sass-rails sass-rails
shoulda-matchers shoulda-matchers
simplecov simplecov
slack-notifier slack-notifier
snorlax snorlax
sucker_punch
timecop
tunemygc tunemygc
uglifier uglifier
uservoice-ruby
RUBY VERSION RUBY VERSION
ruby 2.3.0p0 ruby 2.3.0p0
BUNDLED WITH BUNDLED WITH
1.13.2 1.16.1

View file

@ -1,3 +1,3 @@
web: bundle exec rails server -p $PORT web: bundle exec puma -p $PORT
worker: bundle exec rake jobs:work worker: bundle exec rake jobs:work

View file

@ -2,58 +2,45 @@ Metamaps
======= =======
[![Build Status](https://travis-ci.org/metamaps/metamaps.svg?branch=develop)](https://travis-ci.org/metamaps/metamaps) [![Build Status](https://travis-ci.org/metamaps/metamaps.svg?branch=develop)](https://travis-ci.org/metamaps/metamaps)
[![Code Climate](https://codeclimate.com/github/metamaps/metamaps/badges/gpa.svg)](https://codeclimate.com/github/metamaps/metamaps)
## What is Metamaps? ## What is Metamaps?
Metamaps is a free and open source technology for changemakers, innovators, educators and students. It enables individuals and communities to build and visualize their shared knowledge and unlock their collective intelligence. Metamaps is a free and open-source technology for changemakers, innovators, educators and students. It enables individuals and communities to build and visualize their shared knowledge and unlock their collective intelligence.
You can find a version of this software running at [metamaps.cc][site-beta], where the technology is being tested in a private beta. You can find a version of this software running at [metamaps.cc][site-beta], where the technology is being tested in an open beta.
Metamaps is created and maintained by a distributed, nomadic community comprised of technologists, artists and storytellers. You can get in touch by using whichever of these channels you prefer: Metamaps is developed and maintained by a distributed, nomadic community comprised of technologists, artists and storytellers. You can get in touch by using whichever of these channels you prefer:
## Community ## How do I learn more?
- To send us a personal message or request an invite to the open beta, get in touch with us at team@metamaps.cc or @metamapps on Twitter. - Contact: [team@metamaps.cc](mailto:team@metamaps.cc) or [@metamapps](https://twitter.com/metamapps) on Twitter
- User Documentation: [docs.metamaps.cc](https://docs.metamaps.cc)
- User Community: [hylo.com/c/metamaps](https://www.hylo.com/c/metamaps)
- To see what we're developing, or to weigh in on what you'd like to see developed, see our [Metamaps Feedback and Features](https://trello.com/b/uFOA6a2x/metamaps-feedback-feature-ideas-requests) board on trello
- To follow along with, or contribute,to our design process, see our [Metamaps Design](https://trello.com/b/8HlCikOX/metamaps-design) board on trello
- To follow along with, or contribute to, our development process, see our [Github Issues and Pull Requests](https://github.com/metamaps/metamaps/issues)
- Request an invite to the open beta [here](https://metamaps.cc/request)
<!-- markdown hack to split two lists -->
- To send us a personal message get in touch with us via email, Twitter, or Hylo
- If you would like to report a bug, please check the [issues][contributing-issues] section in our [contributing instructions][contributing]. - If you would like to report a bug, please check the [issues][contributing-issues] section in our [contributing instructions][contributing].
- If you would like to get set up as a developer, that's great! Read on for help getting your development environment set up. - If you would like to get set up as a developer, that's great! Read on for help getting your development environment set up.
## Installation ## Installation for local use or development of Metamaps
If you are on Mac or Ubuntu you can use the following instructions to quickly get a local copy of metamaps up and running using a Vagrant virtualbox. Don't be intimidated, it's easy! First off is getting the code downloaded to your computer. You can download a zip file from github, but if you've got `git` you can just run `git clone https://github.com/metamaps/metamaps` in your terminal.
```
git clone git@github.com:metamaps/metamaps.git
```
Now ensure you have VirtualBox and Vagrant installed on your computer
```
cd metamaps
./bin/configure.sh
```
This will do all the setup steps to make Metamaps work with a bit of behind the scenes ninja magick.
To start servers which will run metamaps you can then run: There are instructions for setup on various platforms, with particular support for Mac and Ubuntu, which can be found here:
``` - [Mac Install Walkthrough][mac-installation]
./bin/start - [Ubuntu Install Walkthrough][ubuntu-installation]
```
To stop them:
```
./bin/stop
```
With your webservers running, open a web browser and go to `http://localhost:3000`
You can sign in with the default account If you prefer to isolate your install in a virtual machine, you may find it simpler to setup using Vagrant:
email: `user@user.com` - [Vagrant installation][vagrant-installation]
password: `toolsplusconsciousness`
OR create a new account at `/join`, and use access code `qwertyui`
Start mapping and programming! We don't promise support for Windows, but at one point we had it running and we've kept those docs available for reference
- [Outdated Windows Walkthrough][windows-installation]
We haven't set up instructions for using Vagrant on Windows, but there are instructions for a manual setup here:
- [For Windows][windows-installation]
## Contributing guidelines
Cloning this repository directly is primarily for those wishing to contribute to our codebase. Check out our [contributing instructions][contributing] to get involved.
## Licensing information ## Licensing information
@ -63,11 +50,13 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
The license can be read [here][license]. The license can be read [here][license].
Copyright (c) 2016 Connor Turland Copyright (c) 2017 Connor Turland
[site-blog]: http://blog.metamaps.cc
[site-beta]: http://metamaps.cc [site-beta]: http://metamaps.cc
[license]: https://github.com/metamaps/metamaps/blob/develop/LICENSE [license]: https://github.com/metamaps/metamaps/blob/develop/LICENSE
[contributing]: https://github.com/metamaps/metamaps/blob/develop/doc/CONTRIBUTING.md [contributing]: https://github.com/metamaps/metamaps/blob/develop/doc/CONTRIBUTING.md
[contributing-issues]: https://github.com/metamaps/metamaps/blob/develop/doc/CONTRIBUTING.md#reporting-bugs-and-other-issues [contributing-issues]: https://github.com/metamaps/metamaps/blob/develop/doc/CONTRIBUTING.md#reporting-bugs-and-other-issues
[mac-installation]: https://github.com/metamaps/metamaps/blob/develop/doc/MacInstallation.md
[ubuntu-installation]: https://github.com/metamaps/metamaps/blob/develop/doc/UbuntuInstallation.md
[vagrant-installation]: https://github.com/metamaps/metamaps/blob/develop/doc/VagrantInstallation.md
[windows-installation]: https://github.com/metamaps/metamaps/blob/develop/doc/WindowsInstallation.md [windows-installation]: https://github.com/metamaps/metamaps/blob/develop/doc/WindowsInstallation.md

1
Rakefile Normal file → Executable file
View file

@ -1,5 +1,6 @@
#!/usr/bin/env rake #!/usr/bin/env rake
# frozen_string_literal: true # frozen_string_literal: true
# Add your own tasks in files placed in lib/tasks ending in .rake, # Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

2
Vagrantfile vendored
View file

@ -37,7 +37,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = 'trusty64' config.vm.box = 'trusty64'
config.vm.box_url = 'http://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box' config.vm.box_url = 'http://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box'
config.vm.network :forwarded_port, guest: 3000, host: 3000 config.vm.network :forwarded_port, guest: 3000, host: 3000
config.vm.network :forwarded_port, guest: 5001, host: 5001 config.vm.network :forwarded_port, guest: 5000, host: 5000
config.vm.network 'private_network', ip: '10.0.1.11' config.vm.network 'private_network', ip: '10.0.1.11'
config.vm.synced_folder '.', '/vagrant', nfs: true config.vm.synced_folder '.', '/vagrant', nfs: true

View file

@ -1,3 +1,4 @@
// eslint-disable spaced-comment
// JS and CSS bundles // JS and CSS bundles
//= link_directory ../javascripts .js //= link_directory ../javascripts .js
//= link_directory ../stylesheets .css //= link_directory ../stylesheets .css

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 325 B

BIN
app/assets/images/junto.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
app/assets/images/user_sprite.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 B

View file

@ -0,0 +1,21 @@
/* global Metamaps */
/* erb variables from rails */
Metamaps.ServerData = Metamaps.ServerData || {}
Metamaps.ServerData['junto_spinner_darkgrey.gif'] = '<%= asset_path('junto_spinner_darkgrey.gif') %>'
Metamaps.ServerData['user.png'] = '<%= asset_path('user.png') %>'
Metamaps.ServerData['icons/wildcard.png'] = '<%= asset_path('icons/wildcard.png') %>'
Metamaps.ServerData['topic_description_signifier.png'] = '<%= asset_path('topic_description_signifier.png') %>'
Metamaps.ServerData['topic_link_signifier.png'] = '<%= asset_path('topic_link_signifier.png') %>'
Metamaps.ServerData['synapse16.png'] = '<%= asset_path('synapse16.png') %>'
Metamaps.ServerData['sounds/MM_sounds.mp3'] = '<%= asset_path 'sounds/MM_sounds.mp3' %>'
Metamaps.ServerData['sounds/MM_sounds.ogg'] = '<%= asset_path 'sounds/MM_sounds.ogg' %>'
Metamaps.ServerData['exploremaps_sprite.png'] = '<%= asset_path 'exploremaps_sprite.png' %>'
Metamaps.ServerData['map_control_sprite.png'] = '<%= asset_path 'map_control_sprite.png' %>'
Metamaps.ServerData['user_sprite.png'] = '<%= asset_path 'user_sprite.png' %>'
Metamaps.ServerData.Metacodes = <%= Metacode.all.to_json.gsub(%r[(icon.*?)(\"},)], '\1?purple=stupid\2').html_safe %>
Metamaps.ServerData.REALTIME_SERVER = '<%= ENV['REALTIME_SERVER'] %>'
Metamaps.ServerData.RAILS_ENV = '<%= ENV['RAILS_ENV'] %>'
Metamaps.ServerData.VERSION = '<%= METAMAPS_VERSION %>'
Metamaps.ServerData.BUILD = '<%= METAMAPS_BUILD %>'
Metamaps.ServerData.LAST_UPDATED = '<%= METAMAPS_LAST_UPDATED %>'

View file

@ -0,0 +1,23 @@
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
/* eslint-disable spaced-comment */
//= require jquery
//= require jquery-ui
//= require jquery_ujs
//= require action_cable
//= require_directory ./lib
//= require ./cloudcarousel-secret
//= require ./metamaps.secret.bundle
//= require ./Metamaps.ServerData
//= require homepageVimeoFallback
/* eslint-enable spaced-comment */

View file

@ -10,10 +10,13 @@
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW. // GO AFTER THE REQUIRES BELOW.
// //
/* eslint-disable spaced-comment */
//= require jquery //= require jquery
//= require jquery-ui //= require jquery-ui
//= require jquery_ujs //= require jquery_ujs
//= require action_cable
//= require_directory ./lib //= require_directory ./lib
//= require ./src/Metamaps.Erb
//= require ./webpacked/metamaps.bundle //= require ./webpacked/metamaps.bundle
//= require ./src/check-canvas-support //= require ./Metamaps.ServerData
//= require homepageVimeoFallback
/* eslint-enable spaced-comment */

View file

@ -0,0 +1,438 @@
//////////////////////////////////////////////////////////////////////////////////
// CloudCarousel V1.0.5
// (c) 2011 by R Cecco. <http://www.professorcloud.com>
// MIT License
//
// Reflection code based on plugin by Christophe Beyls <http://www.digitalia.be>
//
// Please retain this copyright header in all versions of the software
//////////////////////////////////////////////////////////////////////////////////
var matched, browser;
jQuery.uaMatch = function( ua ) {
ua = ua.toLowerCase();
var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
/(webkit)[ \/]([\w.]+)/.exec( ua ) ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
/(msie) ([\w.]+)/.exec( ua ) ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
[];
return {
browser: match[ 1 ] || "",
version: match[ 2 ] || "0"
};
};
matched = jQuery.uaMatch( navigator.userAgent );
browser = {};
if ( matched.browser ) {
browser[ matched.browser ] = true;
browser.version = matched.version;
}
// Chrome is Webkit, but Webkit is also Safari.
if ( browser.chrome ) {
browser.webkit = true;
} else if ( browser.webkit ) {
browser.safari = true;
}
jQuery.browser = browser;
(function($) {
// START Reflection object.
// Creates a reflection for underneath an image.
// IE uses an image with IE specific filter properties, other browsers use the Canvas tag.
// The position and size of the reflection gets updated by updateAll() in Controller.
function Reflection(img, reflHeight, opacity) {
var reflection, cntx, imageWidth = img.width, imageHeight = img.width, gradient, parent;
parent = $(img.parentNode);
this.element = reflection = parent.append("<canvas class='reflection' style='position:absolute'/>").find(':last')[0];
if ( !reflection.getContext && $.browser.msie) {
this.element = reflection = parent.append("<img class='reflection' style='position:absolute'/>").find(':last')[0];
reflection.src = img.src;
reflection.style.filter = "flipv progid:DXImageTransform.Microsoft.Alpha(opacity=" + (opacity * 100) + ", style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy=" + (reflHeight / imageHeight * 100) + ")";
} else {
cntx = reflection.getContext("2d");
try {
$(reflection).attr({width: imageWidth, height: reflHeight});
cntx.save();
cntx.translate(0, imageHeight-1);
cntx.scale(1, -1);
cntx.drawImage(img, 0, 0, imageWidth, imageHeight);
cntx.restore();
cntx.globalCompositeOperation = "destination-out";
gradient = cntx.createLinearGradient(0, 0, 0, reflHeight);
gradient.addColorStop(0, "rgba(255, 255, 255, " + (1 - opacity) + ")");
gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)");
cntx.fillStyle = gradient;
cntx.fillRect(0, 0, imageWidth, reflHeight);
} catch(e) {
return;
}
}
// Store a copy of the alt and title attrs into the reflection
$(reflection).attr({ 'alt': $(img).attr('alt'), title: $(img).attr('title')} );
} //END Reflection object
// START Item object.
// A wrapper object for items within the carousel.
var Item = function(imgIn, options)
{
this.orgWidth = imgIn.width;
this.orgHeight = imgIn.height;
this.image = imgIn;
this.reflection = null;
this.alt = imgIn.alt;
this.title = imgIn.title;
this.imageOK = false;
this.options = options;
this.imageOK = true;
if (this.options.reflHeight > 0)
{
this.reflection = new Reflection(this.image, this.options.reflHeight, this.options.reflOpacity);
}
$(this.image).css('position','absolute'); // Bizarre. This seems to reset image width to 0 on webkit!
};// END Item object
// Controller object.
// This handles moving all the items, dealing with mouse clicks etc.
var Controller = function(container, images, options)
{
var items = [], funcSin = Math.sin, funcCos = Math.cos, ctx=this;
this.controlTimer = 0;
this.stopped = false;
//this.imagesLoaded = 0;
this.container = container;
this.xRadius = options.xRadius;
this.yRadius = options.yRadius;
this.showFrontTextTimer = 0;
this.autoRotateTimer = 0;
if (options.xRadius === 0)
{
this.xRadius = ($(container).width()/2.3);
}
if (options.yRadius === 0)
{
this.yRadius = ($(container).height()/6);
}
this.xCentre = options.xPos;
this.yCentre = options.yPos;
this.frontIndex = 0; // Index of the item at the front
// Start with the first item at the front.
this.rotation = this.destRotation = Math.PI/2;
this.timeDelay = 1000/options.FPS;
// Turn on the infoBox
if(options.altBox !== null)
{
$(options.altBox).css('display','block');
$(options.titleBox).css('display','block');
}
// Turn on relative position for container to allow absolutely positioned elements
// within it to work.
$(container).css({ position:'relative', overflow:'hidden'} );
$(options.buttonLeft).css('display','inline');
$(options.buttonRight).css('display','inline');
// Setup the buttons.
$(options.buttonLeft).bind('mouseup',this,function(event){
event.data.rotate(-1);
return false;
});
$(options.buttonRight).bind('mouseup',this,function(event){
event.data.rotate(1);
return false;
});
// START METAMAPS CODE
// Add code that makes tab and shift+tab scroll through metacodes
$('.new_topic').bind('keydown',this,function(event){
if (event.keyCode == 9 && event.shiftKey) {
$(container).show()
event.data.rotate(-1);
event.preventDefault();
event.stopPropagation();
} else if (event.keyCode == 9) {
$(container).show()
event.data.rotate(1);
event.preventDefault();
event.stopPropagation();
}
});
// END METAMAPS CODE
// You will need this plugin for the mousewheel to work: http://plugins.jquery.com/project/mousewheel
if (options.mouseWheel)
{
// START METAMAPS CODE
/*$('body').bind('mousewheel',this,function(event, delta) {
if (Metamaps.Create.newTopic.beingCreated &&
!Metamaps.Create.isSwitchingSet &&
!Metamaps.Create.newTopic.pinned) {
event.data.rotate(delta);
return false;
}
});*/
// END METAMAPS CODE
// ORIGINAL CODE
// $(container).bind('mousewheel',this,function(event, delta) {
// event.data.rotate(delta);
// return false;
// });
//
}
$(container).unbind('mouseover click').bind('mouseover click',this,function(event){
clearInterval(event.data.autoRotateTimer); // Stop auto rotation if mouse over.
var text = $(event.target).attr('alt');
// If we have moved over a carousel item, then show the alt and title text.
if ( text !== undefined && text !== null )
{
clearTimeout(event.data.showFrontTextTimer);
$(options.altBox).html( ($(event.target).attr('alt') ));
//$(options.titleBox).html( ($(event.target).attr('title') ));
if ( options.bringToFront && event.type == 'click' )
{
$(options.titleBox).html( ($(event.target).attr('title') ));
// START METAMAPS CODE
Metamaps.Create.newTopic.metacode = $(event.target).attr('data-id');
// END METAMAPS CODE
var idx = $(event.target).data('itemIndex');
var frontIndex = event.data.frontIndex;
//var diff = idx - frontIndex;
var diff = (idx - frontIndex) % images.length;
if (Math.abs(diff) > images.length / 2) {
diff += (diff > 0 ? -images.length : images.length);
}
event.data.rotate(-diff);
}
}
});
// START METAMAPS CODE - initialize newTopic.metacode
var first = $(this.container).find('img').get(0)
Metamaps.Create.newTopic.metacode = $(first).data('id')
// END METAMAPS CODE
// If we have moved out of a carousel item (or the container itself),
// restore the text of the front item in 1 second.
$(container).bind('mouseout',this,function(event){
var context = event.data;
clearTimeout(context.showFrontTextTimer);
context.showFrontTextTimer = setTimeout( function(){context.showFrontText();},1000);
context.autoRotate(); // Start auto rotation.
});
// Prevent items from being selected as mouse is moved and clicked in the container.
$(container).bind('mousedown',this,function(event){
event.data.container.focus();
return false;
});
container.onselectstart = function () { return false; }; // For IE.
this.innerWrapper = $(container).wrapInner('<div style="position:absolute;width:100%;height:100%;"/>').children()[0];
// Shows the text from the front most item.
this.showFrontText = function()
{
if ( items[this.frontIndex] === undefined ) { return; } // Images might not have loaded yet.
// METAMAPS CODE
Metamaps.Create.newTopic.setMetacode($(items[this.frontIndex].image).attr('data-id'))
// NOT METAMAPS CODE
//$(options.titleBox).html( $(items[this.frontIndex].image).attr('title'));
//$(options.altBox).html( $(items[this.frontIndex].image).attr('alt'));
};
this.go = function()
{
if(this.controlTimer !== 0) { return; }
var context = this;
this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);
};
this.stop = function()
{
clearTimeout(this.controlTimer);
this.controlTimer = 0;
// METAMAPS CODE
$(container).hide()
// END METAMAPS CODE
};
// Starts the rotation of the carousel. Direction is the number (+-) of carousel items to rotate by.
this.rotate = function(direction)
{
this.frontIndex -= direction;
if (this.frontIndex == -1) this.frontIndex = items.length - 1;
this.frontIndex %= items.length;
this.destRotation += ( Math.PI / items.length ) * ( 2*direction );
this.showFrontText();
this.go();
};
this.autoRotate = function()
{
if ( options.autoRotate !== 'no' )
{
var dir = (options.autoRotate === 'right')? 1 : -1;
this.autoRotateTimer = setInterval( function(){ctx.rotate(dir); }, options.autoRotateDelay );
}
};
// This is the main loop function that moves everything.
this.updateAll = function()
{
var minScale = options.minScale; // This is the smallest scale applied to the furthest item.
var smallRange = (1-minScale) * 0.5;
var w,h,x,y,scale,item,sinVal;
var change = (this.destRotation - this.rotation);
var absChange = Math.abs(change);
this.rotation += change * options.speed;
if ( absChange < 0.001 ) { this.rotation = this.destRotation; }
var itemsLen = items.length;
var spacing = (Math.PI / itemsLen) * 2;
//var wrapStyle = null;
var radians = this.rotation;
var isMSIE = $.browser.msie;
// Turn off display. This can reduce repaints/reflows when making style and position changes in the loop.
// See http://dev.opera.com/articles/view/efficient-javascript/?page=3
this.innerWrapper.style.display = 'none';
var style;
var px = 'px', reflHeight;
var context = this;
for (var i = 0; i<itemsLen ;i++)
{
item = items[i];
sinVal = funcSin(radians);
scale = ((sinVal+1) * smallRange) + minScale;
x = this.xCentre + (( (funcCos(radians) * this.xRadius) - (item.orgWidth*0.5)) * scale);
y = this.yCentre + (( (sinVal * this.yRadius) ) * scale);
if (item.imageOK)
{
var img = item.image;
img.style.zIndex = "" + (scale * 100)>>0; // >>0 = Math.foor(). Firefox doesn't like fractional decimals in z-index.
w = img.width = item.orgWidth * scale;
h = img.height = item.orgHeight * scale;
img.style.left = x + px ;
img.style.top = y + px;
if (item.reflection !== null)
{
reflHeight = options.reflHeight * scale;
style = item.reflection.element.style;
style.left = x + px;
style.top = y + h + options.reflGap * scale + px;
style.width = w + px;
if (isMSIE)
{
style.filter.finishy = (reflHeight / h * 100);
}else
{
style.height = reflHeight + px;
}
}
}
radians += spacing;
}
// Turn display back on.
this.innerWrapper.style.display = 'block';
// If we have a preceptable change in rotation then loop again next frame.
if ( absChange >= 0.001 )
{
this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);
}else
{
// Otherwise just stop completely.
this.stop();
}
}; // END updateAll
// Create an Item object for each image
// func = function(){return;ctx.updateAll();} ;
// Check if images have loaded. We need valid widths and heights for the reflections.
this.checkImagesLoaded = function()
{
var i;
for(i=0;i<images.length;i++) {
if ( (images[i].width === undefined) || ( (images[i].complete !== undefined) && (!images[i].complete) ))
{
return;
}
}
for(i=0;i<images.length;i++) {
items.push( new Item( images[i], options ) );
$(images[i]).data('itemIndex',i);
}
// If all images have valid widths and heights, we can stop checking.
clearInterval(this.tt);
// METAMAPS COMMENT this.showFrontText();
this.autoRotate();
this.updateAll();
};
this.tt = setInterval( function(){ctx.checkImagesLoaded();},50);
}; // END Controller object
// The jQuery plugin part. Iterates through items specified in selector and inits a Controller class for each one.
$.fn.CloudCarousel = function(options) {
this.each( function() {
options = $.extend({}, {
reflHeight:0,
reflOpacity:0.5,
reflGap:0,
minScale:0.5,
xPos:0,
yPos:0,
xRadius:0,
yRadius:0,
altBox:null,
titleBox:null,
FPS: 30,
autoRotate: 'no',
autoRotateDelay: 1500,
speed:0.2,
mouseWheel: false,
bringToFront: false
},options );
// Create a Controller for each carousel.
$(this).data('cloudcarousel', new Controller( this, $('.cloudcarousel',$(this)), options) );
});
return this;
};
})(jQuery);

View file

@ -0,0 +1,29 @@
/* global $ */
$(document).ready(function() {
if (window.location.pathname === '/') {
$.ajax({
type: 'GET',
url: 'https://i.vimeocdn.com/video/',
error: function(e) {
$('.homeVideo').hide()
$('.homeVideo').replaceWith($('<video/>', {
poster: '<%= asset_path('metamaps-intro-poster.webp') %>',
width: '560',
height: '315',
class: 'homeVideo',
controls: ''
}))
$('.homeVideo').append($('<source/>', {
src: 'https://metamaps.cc/videos/metamaps-intro.mp4',
type: 'video/mp4'
}))
$('.homeVideo').append(
'<p>You can watch our instruction video at ' +
'<a href="https://metamaps.cc/videos/metamaps-intro.mp4">' +
'https://metamaps.cc/videos/metamaps-intro.mp4</a>.'
)
}
})
}// if
})

View file

@ -0,0 +1,161 @@
// AjaxQ jQuery Plugin
// Copyright (c) 2012 Foliotek Inc.
// MIT License
// https://github.com/Foliotek/ajaxq
// Uses CommonJS, AMD or browser globals to create a jQuery plugin.
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node/CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
var queues = {};
var activeReqs = {};
// Register an $.ajaxq function, which follows the $.ajax interface, but allows a queue name which will force only one request per queue to fire.
// opts can be the regular $.ajax settings plainObject, or a callback returning the settings object, to be evaluated just prior to the actual call to $.ajax.
$.ajaxq = function(qname, opts) {
if (typeof opts === "undefined") {
throw ("AjaxQ: queue name is not provided");
}
// Will return a Deferred promise object extended with success/error/callback, so that this function matches the interface of $.ajax
var deferred = $.Deferred(),
promise = deferred.promise();
promise.success = promise.done;
promise.error = promise.fail;
promise.complete = promise.always;
// Check whether options are to be evaluated at call time or not.
var deferredOpts = typeof opts === 'function';
// Create a deep copy of the arguments, and enqueue this request.
var clonedOptions = !deferredOpts ? $.extend(true, {}, opts) : null;
enqueue(function() {
// Send off the ajax request now that the item has been removed from the queue
var jqXHR = $.ajax.apply(window, [deferredOpts ? opts() : clonedOptions]);
// Notify the returned deferred object with the correct context when the jqXHR is done or fails
// Note that 'always' will automatically be fired once one of these are called: http://api.jquery.com/category/deferred-object/.
jqXHR.done(function() {
deferred.resolve.apply(this, arguments);
});
jqXHR.fail(function() {
deferred.reject.apply(this, arguments);
});
jqXHR.always(dequeue); // make sure to dequeue the next request AFTER the done and fail callbacks are fired
return jqXHR;
});
return promise;
// If there is no queue, create an empty one and instantly process this item.
// Otherwise, just add this item onto it for later processing.
function enqueue(cb) {
if (!queues[qname]) {
queues[qname] = [];
var xhr = cb();
activeReqs[qname] = xhr;
}
else {
queues[qname].push(cb);
}
}
// Remove the next callback from the queue and fire it off.
// If the queue was empty (this was the last item), delete it from memory so the next one can be instantly processed.
function dequeue() {
if (!queues[qname]) {
return;
}
var nextCallback = queues[qname].shift();
if (nextCallback) {
var xhr = nextCallback();
activeReqs[qname] = xhr;
}
else {
delete queues[qname];
delete activeReqs[qname];
}
}
};
// Register a $.postq and $.getq method to provide shortcuts for $.get and $.post
// Copied from jQuery source to make sure the functions share the same defaults as $.get and $.post.
$.each( [ "getq", "postq" ], function( i, method ) {
$[ method ] = function( qname, url, data, callback, type ) {
if ( $.isFunction( data ) ) {
type = type || callback;
callback = data;
data = undefined;
}
return $.ajaxq(qname, {
type: method === "postq" ? "post" : "get",
url: url,
data: data,
success: callback,
dataType: type
});
};
});
var isQueueRunning = function(qname) {
return (queues.hasOwnProperty(qname) && queues[qname].length > 0) || activeReqs.hasOwnProperty(qname);
};
var isAnyQueueRunning = function() {
for (var i in queues) {
if (isQueueRunning(i)) return true;
}
return false;
};
$.ajaxq.isRunning = function(qname) {
if (qname) return isQueueRunning(qname);
else return isAnyQueueRunning();
};
$.ajaxq.getActiveRequest = function(qname) {
if (!qname) throw ("AjaxQ: queue name is required");
return activeReqs[qname];
};
$.ajaxq.abort = function(qname) {
if (!qname) throw ("AjaxQ: queue name is required");
var current = $.ajaxq.getActiveRequest(qname);
delete queues[qname];
delete activeReqs[qname];
if (current) current.abort();
};
$.ajaxq.clear = function(qname) {
if (!qname) {
for (var i in queues) {
if (queues.hasOwnProperty(i)) {
queues[i] = [];
}
}
}
else {
if (queues[qname]) {
queues[qname] = [];
}
}
};
}));

View file

@ -1,39 +0,0 @@
var attachMediaStream = function (stream, el, options) {
var URL = window.URL;
var opts = {
autoplay: true,
mirror: false,
muted: false
};
var element = el || document.createElement('video');
var item;
if (options) {
for (item in options) {
opts[item] = options[item];
}
}
if (opts.autoplay) element.autoplay = 'autoplay';
if (opts.muted) element.muted = true;
if (opts.mirror) {
['', 'moz', 'webkit', 'o', 'ms'].forEach(function (prefix) {
var styleName = prefix ? prefix + 'Transform' : 'transform';
element.style[styleName] = 'scaleX(-1)';
});
}
// this first one should work most everywhere now
// but we have a few fallbacks just in case.
if (URL && URL.createObjectURL) {
element.src = URL.createObjectURL(stream);
} else if (element.srcObject) {
element.srcObject = stream;
} else if (element.mozSrcObject) {
element.mozSrcObject = stream;
} else {
return false;
}
return element;
};

View file

@ -0,0 +1,2 @@
!function(t){"use strict";var e=t.HTMLCanvasElement&&t.HTMLCanvasElement.prototype,o=t.Blob&&function(){try{return Boolean(new Blob)}catch(t){return!1}}(),n=o&&t.Uint8Array&&function(){try{return 100===new Blob([new Uint8Array(100)]).size}catch(t){return!1}}(),r=t.BlobBuilder||t.WebKitBlobBuilder||t.MozBlobBuilder||t.MSBlobBuilder,a=/^data:((.*?)(;charset=.*?)?)(;base64)?,/,i=(o||r)&&t.atob&&t.ArrayBuffer&&t.Uint8Array&&function(t){var e,i,l,u,b,c,d,B,f;if(e=t.match(a),!e)throw new Error("invalid data URI");for(i=e[2]?e[1]:"text/plain"+(e[3]||";charset=US-ASCII"),l=!!e[4],u=t.slice(e[0].length),b=l?atob(u):decodeURIComponent(u),c=new ArrayBuffer(b.length),d=new Uint8Array(c),B=0;B<b.length;B+=1)d[B]=b.charCodeAt(B);return o?new Blob([n?d:c],{type:i}):(f=new r,f.append(c),f.getBlob(i))};t.HTMLCanvasElement&&!e.toBlob&&(e.mozGetAsFile?e.toBlob=function(t,o,n){t(n&&e.toDataURL&&i?i(this.toDataURL(o,n)):this.mozGetAsFile("blob",o))}:e.toDataURL&&i&&(e.toBlob=function(t,e,o){t(i(this.toDataURL(e,o)))})),"function"==typeof define&&define.amd?define(function(){return i}):"object"==typeof module&&module.exports?module.exports=i:t.dataURLtoBlob=i}(window);
//# sourceMappingURL=canvas-to-blob.min.js.map

View file

@ -161,18 +161,21 @@ jQuery.browser = browser;
return false; return false;
}); });
// START METAMAPS CODE
// Add code that makes tab and shift+tab scroll through metacodes // Add code that makes tab and shift+tab scroll through metacodes
$('.new_topic').bind('keydown',this,function(event){ $('.new_topic').bind('keydown',this,function(event){
if (event.keyCode == 9 && event.shiftKey) { if (event.keyCode == 9) {
event.data.rotate(-1); if (event.shiftKey) {
event.preventDefault(); event.data.rotate(-1)
event.stopPropagation(); } else {
} else if (event.keyCode == 9) { event.data.rotate(1)
event.data.rotate(1); }
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
Metamaps.Create.newTopic.metacode = $(items[event.data.frontIndex].image).attr('data-id');
} }
}); });
// END METAMAPS CODE
// You will need this plugin for the mousewheel to work: http://plugins.jquery.com/project/mousewheel // You will need this plugin for the mousewheel to work: http://plugins.jquery.com/project/mousewheel
if (options.mouseWheel) if (options.mouseWheel)
@ -187,14 +190,14 @@ jQuery.browser = browser;
} }
}); });
// END METAMAPS CODE // END METAMAPS CODE
/* ORIGINAL CODE // ORIGINAL CODE
$(container).bind('mousewheel',this,function(event, delta) { // $(container).bind('mousewheel',this,function(event, delta) {
event.data.rotate(delta); // event.data.rotate(delta);
return false; // return false;
}); // });
*/ //
} }
$(container).bind('mouseover click',this,function(event){ $(container).unbind('mouseover click').bind('mouseover click',this,function(event){
clearInterval(event.data.autoRotateTimer); // Stop auto rotation if mouse over. clearInterval(event.data.autoRotateTimer); // Stop auto rotation if mouse over.
var text = $(event.target).attr('alt'); var text = $(event.target).attr('alt');
@ -209,9 +212,9 @@ jQuery.browser = browser;
if ( options.bringToFront && event.type == 'click' ) if ( options.bringToFront && event.type == 'click' )
{ {
$(options.titleBox).html( ($(event.target).attr('title') )); $(options.titleBox).html( ($(event.target).attr('title') ));
// METAMAPS CODE // START METAMAPS CODE
Metamaps.Create.newTopic.metacode = $(event.target).attr('data-id'); Metamaps.Create.newTopic.metacode = $(event.target).attr('data-id');
// NOT METAMAPS CODE // END METAMAPS CODE
var idx = $(event.target).data('itemIndex'); var idx = $(event.target).data('itemIndex');
var frontIndex = event.data.frontIndex; var frontIndex = event.data.frontIndex;
//var diff = idx - frontIndex; //var diff = idx - frontIndex;
@ -224,6 +227,11 @@ jQuery.browser = browser;
} }
} }
}); });
// START METAMAPS CODE - initialize newTopic.metacode
var first = $(this.container).find('img').get(0)
Metamaps.Create.newTopic.metacode = $(first).data('id')
// END METAMAPS CODE
// If we have moved out of a carousel item (or the container itself), // If we have moved out of a carousel item (or the container itself),
// restore the text of the front item in 1 second. // restore the text of the front item in 1 second.
$(container).bind('mouseout',this,function(event){ $(container).bind('mouseout',this,function(event){
@ -247,11 +255,6 @@ jQuery.browser = browser;
this.showFrontText = function() this.showFrontText = function()
{ {
if ( items[this.frontIndex] === undefined ) { return; } // Images might not have loaded yet. if ( items[this.frontIndex] === undefined ) { return; } // Images might not have loaded yet.
// METAMAPS CODE
Metamaps.Create.newTopic.metacode = $(items[this.frontIndex].image).attr('data-id');
//$('img.cloudcarousel').css({"background":"none", "width":"","height":""});
//$(items[this.frontIndex].image).css({"width":"45px","height":"45px"});
// NOT METAMAPS CODE
$(options.titleBox).html( $(items[this.frontIndex].image).attr('title')); $(options.titleBox).html( $(items[this.frontIndex].image).attr('title'));
$(options.altBox).html( $(items[this.frontIndex].image).attr('alt')); $(options.altBox).html( $(items[this.frontIndex].image).attr('alt'));
}; };

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,23 +0,0 @@
function SocketIoConnection(config) {
this.connection = io.connect(config.url, config.socketio);
}
SocketIoConnection.prototype.on = function (ev, fn) {
this.connection.on(ev, fn);
};
SocketIoConnection.prototype.emit = function () {
this.connection.emit.apply(this.connection, arguments);
};
SocketIoConnection.prototype.removeAllListeners = function () {
this.connection.removeAllListeners();
};
SocketIoConnection.prototype.getSessionid = function () {
return this.connection.socket.sessionid;
};
SocketIoConnection.prototype.disconnect = function () {
return this.connection.disconnect();
};

View file

@ -1,41 +0,0 @@
var USERVOICE;
if(USERVOICE == undefined) {
USERVOICE = {};
}
USERVOICE.load = function (name, id, email, sso_token) {
// Include the UserVoice JavaScript SDK (only needed once on a page)
UserVoice=window.UserVoice||[];(function(){var uv=document.createElement('script');uv.type='text/javascript';uv.async=true;uv.src='//widget.uservoice.com/wybK0nSMNuhlWkIKzTyWg.js';var s=document.getElementsByTagName('script')[0];s.parentNode.insertBefore(uv,s)})();
//
// UserVoice Javascript SDK developer documentation:
// https://www.uservoice.com/o/javascript-sdk
//
// Set colors
UserVoice.push(['set', {
accent_color: '#448dd6',
trigger_color: 'white',
trigger_background_color: 'rgba(46, 49, 51, 0.6)'
}]);
// Identify the user and pass traits
// To enable, replace sample data with actual user traits and uncomment the line
if (name) {
UserVoice.push(['setSSO', sso_token]);
UserVoice.push(['identify', {
'email': email, // Users email address
'name': name, // Users real name
'id': id, // Optional: Unique id of the user
}]);
}
// Add default trigger to the bottom-left corner of the window:
UserVoice.push(['addTrigger', { mode: 'contact', trigger_position: 'bottom-left' }]);
// Or, use your own custom trigger:
//UserVoice.push(['addTrigger', '#barometer_tab', { mode: 'contact' }]);
// Autoprompt for Satisfaction and SmartVote (only displayed under certain conditions)
UserVoice.push(['autoprompt', {}]);
};

File diff suppressed because one or more lines are too long

View file

@ -1,24 +0,0 @@
/* global Metamaps */
/*
* Metamaps.Erb.js.erb
*/
/* erb variables from rails */
window.Metamaps = window.Metamaps || {}
Metamaps.Erb = {}
Metamaps.Erb['REALTIME_SERVER'] = '<%= ENV['REALTIME_SERVER'] %>'
Metamaps.Erb['RAILS_ENV'] = '<%= ENV['RAILS_ENV'] %>'
Metamaps.Erb['junto_spinner_darkgrey.gif'] = '<%= asset_path('junto_spinner_darkgrey.gif') %>'
Metamaps.Erb['user.png'] = '<%= asset_path('user.png') %>'
Metamaps.Erb['icons/wildcard.png'] = '<%= asset_path('icons/wildcard.png') %>'
Metamaps.Erb['topic_description_signifier.png'] = '<%= asset_path('topic_description_signifier.png') %>'
Metamaps.Erb['topic_link_signifier.png'] = '<%= asset_path('topic_link_signifier.png') %>'
Metamaps.Erb['synapse16.png'] = '<%= asset_path('synapse16.png') %>'
Metamaps.Erb['import-example.png'] = '<%= asset_path('import-example.png') %>'
Metamaps.Erb['sounds/MM_sounds.mp3'] = '<%= asset_path 'sounds/MM_sounds.mp3' %>'
Metamaps.Erb['sounds/MM_sounds.ogg'] = '<%= asset_path 'sounds/MM_sounds.ogg' %>'
Metamaps.Metacodes = <%= Metacode.all.to_json.gsub(%r[(icon.*?)(\"},)], '\1?purple=stupid\2').html_safe %>
Metamaps.VERSION = '<%= METAMAPS_VERSION %>'
Metamaps.BUILD = '<%= METAMAPS_BUILD %>'
Metamaps.LAST_UPDATED = '<%= METAMAPS_LAST_UPDATED %>'

View file

@ -1,15 +0,0 @@
// TODO document this user agent function
var labelType, useGradients, nativeTextSupport, animate
;(function () {
var ua = navigator.userAgent,
iStuff = ua.match(/iPhone/i) || ua.match(/iPad/i),
typeOfCanvas = typeof HTMLCanvasElement,
nativeCanvasSupport = (typeOfCanvas == 'object' || typeOfCanvas == 'function'),
textSupport = nativeCanvasSupport && (typeof document.createElement('canvas').getContext('2d').fillText == 'function')
// I'm setting this based on the fact that ExCanvas provides text support for IE
// and that as of today iPhone/iPad current text support is lame
labelType = (!nativeCanvasSupport || (textSupport && !iStuff)) ? 'Native' : 'HTML'
nativeTextSupport = labelType == 'Native'
useGradients = nativeCanvasSupport
animate = !(iStuff || !nativeCanvasSupport)
})()

View file

@ -0,0 +1,12 @@
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the top of the
* compiled file, but it's generally better to create a new file per style scope.
*
*= require ./special
*/

View file

@ -0,0 +1,109 @@
#metacodeSelector {
display: none;
}
.metacodeSelect {
border-top: 1px solid #DDD;
padding: 0;
background: #FFF;
.metacodeFilterInput {
width: 100px;
outline: none;
border: 0;
padding: 8px;
font-size: 14px;
line-height: 14px;
color: #424242;
font-family: 'din-medium', helvetica, sans-serif;
}
.metacodeList {
list-style: none;
background: #FFF;
li {
padding: 8px;
cursor: pointer;
&:hover, &.keySelect {
background: #4CAF50;
}
}
img {
width: 24px;
height: 24px;
display: inline-block;
vertical-align: middle;
padding-right: 6px;
}
}
}
.selectedMetacode {
float: left;
background: #FFF;
border-top-left-radius: 2px;
border-bottom-left-radius: 2px;
padding: 5px 10px 5px 6px;
vertical-align: top;
border-right: 1px solid #DDD;
cursor: pointer;
}
.selectedMetacode:hover, .selectedMetacode.isBeingSelected {
background: #EDEDED;
}
.selectedMetacode img {
width: 24px;
height: 24px;
display: inline-block;
vertical-align: middle;
}
.selectedMetacode span {
vertical-align: middle;
}
.selectedMetacode .downArrow {
display: inline-block;
vertical-align: middle;
width: 0;
height: 0;
border-style: solid;
border-width: 8px 6px 0 6px;
border-color: #777 transparent transparent transparent;
margin-left: 2px;
margin-top: 4px;
}
.new_topic {
margin: 0;
margin-top: -17px;
white-space: nowrap;
}
#new_topic .twitter-typeahead {
position: relative !important;
top: 0;
left: 0;
}
.new_topic #topic_name,
.new_topic .tt-hint {
border-radius: none;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
}
.openMetacodeSwitcher {
top: -16px;
left: -16px;
}
#metacodeImg {
height: 120px;
width: 380px;
display: none;
position: absolute !important;
top: -30px;
z-index: -1;
}
#metacodeImgTitle {
display: none;
float: left;
width: 120px;
text-align: center;
margin-left: 110px;
}

View file

@ -56,16 +56,15 @@
} }
li.toggledOff { li.toggledOff {
opacity: 0.4; opacity: 0.6;
} }
} }
.blackBox { .centerContent {
width: 760px; width: 760px;
margin: 0 auto; margin: 0 auto;
padding: 80px 0 60px 20px; padding: 80px 0 60px 20px;
background: rgba(0, 0, 0, 0.4); background: rgba(125, 125, 125, 0.4);
color: white;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
@ -85,10 +84,10 @@
display: table-row; display: table-row;
} }
tr:nth-child(odd) { tr:nth-child(odd) {
background: rgba(0, 0, 0, 0.2); background: rgba(125, 125, 125, 0.2);
} }
tr:nth-child(even) { tr:nth-child(even) {
background: rgba(0, 0, 0, 0.3); background: rgba(125, 125, 125, 0.3);
} }
th, th,
td { td {

View file

@ -78,11 +78,18 @@ html {
} }
body { body {
background: #d8d9da url(<%= asset_data_uri('shattered_@2X.png') %>); background: #d8d9da url(<%= asset_path('shattered_@2X.png') %>);
font-family: 'din-medium', helvetica, sans-serif; font-family: 'din-medium', helvetica, sans-serif;
color: #424242; color: #424242;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
overflow-x: hidden; overflow-x: hidden;
&.controller-main,
&.controller-maps,
&.controller-topics,
&.controller-explore {
overflow-y: hidden;
}
} }
h1, h1,
h2, h2,
@ -186,10 +193,6 @@ button.button.btn-no:hover {
display: block; display: block;
width: 830px; width: 830px;
} }
.requestInvite {
display: block;
margin: -720px auto 0;
}
.new_session, .new_session,
.new_user, .new_user,
.edit_user, .edit_user,
@ -524,10 +527,12 @@ button.button.btn-no:hover {
left: -1000px; left: -1000px;
display: block; display: block;
position: absolute; position: absolute;
width: 340px;
margin: -40px 0 0 -35px; margin: -40px 0 0 -35px;
z-index: 1; z-index: 1;
} }
body:not(.action-conversation) .new_topic {
width: 340px;
}
#new_topic .twitter-typeahead { #new_topic .twitter-typeahead {
position: absolute !important; position: absolute !important;
@ -663,9 +668,21 @@ label {
position: relative; position: relative;
/*overflow:hidden; */ /*overflow:hidden; */
} }
.main.compressed { .compressed {
width: calc(100% - 300px); .upperRightUI {
right: 324px;
} }
.upperRightMapButtons {
right: 434px;
}
.mapControls {
right: 324px;
}
.infoAndHelp {
right: 370px;
}
}
#infovis-canvas { #infovis-canvas {
-webkit-touch-callout: none; -webkit-touch-callout: none;
-webkit-user-select: none; -webkit-user-select: none;
@ -766,9 +783,9 @@ label {
} }
.sidebarAccountIcon img { .sidebarAccountIcon img {
border-radius: 16px; border-radius: 16px;
width: 32px;
} }
.sidebarAccountBox { .sidebarAccountBox {
display: none;
height: auto; height: auto;
} }
.authenticated .sidebarAccountBox { .authenticated .sidebarAccountBox {
@ -809,6 +826,7 @@ label {
font-size: 14px; font-size: 14px;
line-height: 14px; line-height: 14px;
color: #757575; color: #757575;
cursor: pointer;
} }
.accountListItem:hover { .accountListItem:hover {
color: #424242; color: #424242;
@ -819,7 +837,7 @@ label {
position:absolute; position:absolute;
pointer-events:none; pointer-events:none;
background-repeat:no-repeat; background-repeat:no-repeat;
background-image: url(<%= asset_data_uri('user_sprite.png') %>); background-image: url(<%= asset_path('user_sprite.png') %>);
} }
.accountSettings .accountIcon { .accountSettings .accountIcon {
background-position: 0 0; background-position: 0 0;
@ -827,6 +845,9 @@ label {
.accountAdmin .accountIcon { .accountAdmin .accountIcon {
background-position: 0 -32px; background-position: 0 -32px;
} }
.accountApps .accountIcon {
background-position: 0 -32px;
}
.accountInvite .accountIcon { .accountInvite .accountIcon {
background-position: 0 -64px; background-position: 0 -64px;
} }
@ -1027,7 +1048,6 @@ label[for="user_remember_me"] {
} }
.sidebarFilterBox { .sidebarFilterBox {
display:none;
width: 319px; width: 319px;
padding: 16px 0; padding: 16px 0;
overflow-y: auto; overflow-y: auto;
@ -1238,7 +1258,7 @@ h3.filterBox {
box-shadow: 0px 3px 3px rgba(0,0,0,0.12), 0 3px 3px rgba(0,0,0,0.24); box-shadow: 0px 3px 3px rgba(0,0,0,0.12), 0 3px 3px rgba(0,0,0,0.24);
} }
.rightclickmenu .rc-permission:hover > ul, .rightclickmenu .rc-permission:hover > ul,
.rightclickmenu .rc-metacode:hover > ul, .rightclickmenu .rc-metacode:hover #metacodeOptions > ul,
.rightclickmenu .rc-siblings:hover > ul { .rightclickmenu .rc-siblings:hover > ul {
display: block; display: block;
} }
@ -1267,7 +1287,7 @@ h3.filterBox {
.rightclickmenu li.toPrivate .rc-perm-icon { .rightclickmenu li.toPrivate .rc-perm-icon {
background-position: -24px 0; background-position: -24px 0;
} }
.rightclickmenu .rc-metacode > ul > li, .rightclickmenu .rc-metacode #metacodeOptions > ul > li,
.rightclickmenu .rc-siblings > ul > li { .rightclickmenu .rc-siblings > ul > li {
padding: 6px 24px 6px 8px; padding: 6px 24px 6px 8px;
white-space: nowrap; white-space: nowrap;
@ -1548,6 +1568,7 @@ h3.filterBox {
box-sizing: border-box; box-sizing: border-box;
margin: 0.75em; margin: 0.75em;
padding: 0.75em; padding: 0.75em;
padding-top: 0.85em;
height: 3em; height: 3em;
background-color: #AAB0FB; background-color: #AAB0FB;
border-radius: 0.3em; border-radius: 0.3em;
@ -1894,14 +1915,10 @@ input.collaboratorSearchField {
background-position: -32px 0; background-position: -32px 0;
} }
.yourMap .mapPermission:hover { .yourMap .mapPermission:hover {
background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>);
cursor: pointer; cursor: pointer;
background-position: -32px 0;
} }
.yourMap .mapPermission.minimize { .yourMap .mapPermission.minimize {
background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>) !important;
cursor: pointer; cursor: pointer;
background-position: 0 0;
} }
.mapInfoBox .mapPermission .permissionSelect { .mapInfoBox .mapPermission .permissionSelect {
list-style: none; list-style: none;
@ -2002,6 +2019,7 @@ input.collaboratorSearchField {
position: relative; position: relative;
cursor: pointer; cursor: pointer;
display: none; display: none;
padding: 0 2px;
} }
.mapInfoShareIcon { .mapInfoShareIcon {
width: 24px; width: 24px;
@ -2041,6 +2059,43 @@ and it won't be important on password protected instances */
.yourMap .mapInfoDelete { .yourMap .mapInfoDelete {
display: block; display: block;
} }
.mapInfoButtonsWrapper .mapInfoThumbnail {
display: block;
background-image: url(<%= asset_path('screenshot_sprite.png') %>);
width: 32px;
height: 32px;
& > span {
bottom: -8px;
right: 2px;
font-size: 12px;
color: #e0e0e0;
&:hover {
color: white;
}
}
.tooltip {
display: none;
}
&:hover {
background-position: -32px 0;
.tooltip {
display: block;
position: absolute;
bottom: 30px;
background: black;
color: white;
border-radius: 2px;
padding: 3px 5px 2px 5px;
}
}
}
.mapInfoButtonsWrapper span { .mapInfoButtonsWrapper span {
position: absolute; position: absolute;
width: 100%; width: 100%;
@ -2105,7 +2160,6 @@ and it won't be important on password protected instances */
} }
#lightbox_content { #lightbox_content {
width: 800px; width: 800px;
height: 500px;
max-height: 90vh; max-height: 90vh;
box-sizing: border-box; box-sizing: border-box;
overflow-y: auto; overflow-y: auto;
@ -2190,42 +2244,35 @@ and it won't be important on password protected instances */
color: #00bcd4; color: #00bcd4;
} }
.lightbox_links .lightboxAboutIcon { .lightbox_links .lightboxAboutIcon {
background-image: url(<%= asset_data_uri('about_sprite.png') %>);
background-repeat: no-repeat;
width:32px; width:32px;
height:32px; height:32px;
margin:10px auto; margin:10px auto;
} }
#lightbox_metamapps .lightboxAboutIcon { .icon_twitter .lightboxAboutIcon,
.icon_source_code .lightboxAboutIcon,
.icon_terms .lightboxAboutIcon {
background-image: url(<%= asset_data_uri('about_sprite.png') %>);
background-repeat: no-repeat;
background-position: 0 0; background-position: 0 0;
} }
#lightbox_community .lightboxAboutIcon { .icon_twitter .lightboxAboutIcon {
background-position: -32px 0; background-position: 0 0;
} &:hover {
#lightbox_source .lightboxAboutIcon {
background-position: -64px 0;
}
#lightbox_blog .lightboxAboutIcon {
background-position: -96px 0;
}
#lightbox_term .lightboxAboutIcon {
background-position: -128px 0;
}
#lightbox_metamapps:hover .lightboxAboutIcon {
background-position: 0 -32px; background-position: 0 -32px;
} }
#lightbox_community:hover .lightboxAboutIcon {
background-position: -32px -32px;
} }
#lightbox_source:hover .lightboxAboutIcon { .icon_source_code .lightboxAboutIcon {
background-position: -64px 0;
&:hover {
background-position: -64px -32px; background-position: -64px -32px;
} }
#lightbox_blog:hover .lightboxAboutIcon {
background-position: -96px -32px;
} }
#lightbox_term:hover .lightboxAboutIcon { .icon_terms .lightboxAboutIcon {
background-position: -128px 0;
&:hover {
background-position: -128px -32px; background-position: -128px -32px;
} }
}
/* jquery ui tabs */ /* jquery ui tabs */
@ -2268,6 +2315,9 @@ and it won't be important on password protected instances */
} }
/* switch metacode set */ /* switch metacode set */
#switchMetacodes > p {
margin: 16px 0 16px 0;
}
#metacodeSwitchTabs { #metacodeSwitchTabs {
width: 100%; width: 100%;
font-size: 17px; font-size: 17px;
@ -2275,29 +2325,44 @@ and it won't be important on password protected instances */
border: none; border: none;
background: none; background: none;
padding: 0; padding: 0;
}
#metacodeSwitchTabs .setDesc { .setDesc,
.selectAll,
.selectNone {
margin-bottom: 5px; margin-bottom: 5px;
font-family: 'din-medium', helvetica, sans-serif; font-family: 'din-medium', helvetica, sans-serif;
color: #424242; color: #424242;
font-size: 14px; font-size: 14px;
text-align: justify; text-align: justify;
padding-right: 16px; padding-right: 16px;
display: inline-block;
} }
#switchMetacodes > p {
margin: 16px 0 16px 0; .selectAll,
.selectNone {
float: right;
cursor: pointer;
&:hover,
&.selected {
color: #00bcd4;
} }
#metacodeSwitchTabs > ul { }
& > ul {
width: 130px; width: 130px;
}
#metacodeSwitchTabs > ul li { li {
font-size: 14px; font-size: 14px;
text-transform: uppercase; text-transform: uppercase;
} }
#metacodeSwitchTabs li.ui-state-active a { }
li.ui-state-active a {
color: #00BCD4; color: #00BCD4;
cursor: pointer; cursor: pointer;
} }
}
.metacodeSwitchTab { .metacodeSwitchTab {
max-height: 300px; max-height: 300px;
overflow-y: auto; overflow-y: auto;
@ -2865,146 +2930,18 @@ and it won't be important on password protected instances */
color: #424242; color: #424242;
} }
/* Admin Pages */
.blackBox {
width: 760px;
margin: 0 auto;
padding: 20px 0 60px 20px;
background: rgba(0, 0, 0, 0.4);
color: white;
overflow: hidden;
position: relative;
}
.blackBox .metacodeSetsDescription {
width: 314px;
}
.blackBox td.metacodeSetDesc {
width: 314px;
word-wrap: break-word;
}
.blackBox .metacodeSetImage {
width: 36px;
height: 36px;
float: left;
}
.blackBox tr {
display: table-row;
}
.blackBox tr:nth-child(odd) {
background: rgba(0, 0, 0, 0.2);
}
.blackBox tr:nth-child(even) {
background: rgba(0, 0, 0, 0.3);
}
.blackBox th,
.blackBox td {
padding: 10px;
}
.blackBox td.iconURL {
max-width: 415px;
word-wrap: break-word;
}
.blackBox td.iconColor {
}
.blackBox .field {
margin: 15px 0 5px;
}
.blackBox label {
float: left;
width: 100px;
margin-right: 15px;
}
.blackBox input[type="text"] {
width: 336px;
height: 32px;
font-size: 15px;
direction: ltr;
-webkit-appearance: none;
appearance: none;
display: inline-block;
margin: 0;
padding: 0 8px;
background: #fff;
border: 1px solid #d9d9d9;
border-top: 1px solid #c0c0c0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-border-radius: 1px;
-moz-border-radius: 1px;
border-radius: 1px;
font: -webkit-small-control;
color: initial;
letter-spacing: normal;
word-spacing: normal;
text-transform: none;
text-indent: 0px;
text-shadow: none;
display: inline-block;
text-align: start;
font-family: arial;
}
.blackBox input[type="text"]:hover,
.blackBox textarea:hover {
border: 1px solid #b9b9b9;
border-top: 1px solid #a0a0a0;
-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
-moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
}
.blackBox textarea {
padding: 8px;
border: 1px solid #d9d9d9;
border-top: 1px solid #c0c0c0;
resize: none;
font: -webkit-small-control;
letter-spacing: normal;
word-spacing: normal;
text-transform: none;
text-indent: 0px;
text-shadow: none;
text-align: start;
font-family: arial;
font-size: 15px;
line-height: 17px;
width: 318px;
}
.blackBox .allMetacodes {
padding: 5px 0;
}
.blackBox a.button {
margin-right: 20px;
line-height: 40px;
}
.blackBox a.button,
.blackBox input.add {
float: left;
margin-top: 5px;
height: 40px;
font-size: 17px;
width: auto;
padding: 0 30px;
cursor: pointer;
font-weight: normal;
}
.blackBox a.button:hover,
.blackBox input.add:hover {
-webkit-box-shadow: none;
box-shadow: none;
}
/* request */ /* request */
#wrapper .requestInvite { .requestInvite {
width: 700px; width: 700px;
margin: 0 auto;
padding: 0 0 60px 0;
background: #FFFFFF; background: #FFFFFF;
color: white; color: white;
height: 100%; height: calc(100% - 52px);
overflow: hidden; z-index: 1;
position: relative;
left: 50%;
margin-left: -350px;
margin-top: 52px;
} }
.home_bg { .home_bg {
@ -3074,3 +3011,21 @@ script.data-gratipay-username {
display: inline; display: inline;
float: left; float: left;
} }
.inline {
display: inline-block;
}
.topicFollow {
height: 24px;
line-height: 24px;
cursor: pointer;
font-family: helvetica, sans-serif;
float: left;
width: 72px;
text-align: right;
padding: 12px 0;
color: #4fb5c0;
font-size: 13px;
font-weight: bold;
}

View file

@ -1,17 +1,14 @@
.centerContent { .centerContent {
position: relative; position: relative;
margin: 92px auto 0 auto; margin: 0 auto;
padding: 20px 0 60px 20px; width: auto;
width: 760px; max-width: 800px;
overflow: hidden; overflow: hidden;
box-shadow: 0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24); box-shadow: 0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24);
background: #fff; background: #fff;
-webkit-border-radius: 3px; box-sizing: border-box;
-moz-border-radius: 3px;
border-radius: 3px;
border: 1px solid #dcdcdc;
margin-bottom: 10px;
padding: 15px; padding: 15px;
font-family: 'din-regular', sans-serif;
} }
.centerContent .page-header { .centerContent .page-header {
@ -129,3 +126,9 @@
box-sizing: border-box; box-sizing: border-box;
border-radius: 2px; border-radius: 2px;
} }
.centerContent.withPadding {
margin-top: 1em;
margin-bottom: 1em;
}

View file

@ -1,11 +1,19 @@
$mid-gray: #8A8A8A;
$mid-gray-opacity: rgba(66, 66, 66, 0.6);
.nameCounter { .nameCounter {
position: absolute; position: absolute;
bottom: 1px; bottom: 1px;
right: 2px; right: 2px;
font-size: 11px; font-size: 11px;
font-family: helvetica; font-family: helvetica, sans-serif;
color: #727272; color: #727272;
line-height: 11px; line-height: 11px;
display: none;
}
.riek-editing + .nameCounter {
display: block;
} }
.nameCounter.forMap { .nameCounter.forMap {
@ -17,7 +25,6 @@
} }
#center-container { #center-container {
position:relative; position:relative;
height:100%; height:100%;
@ -29,7 +36,6 @@
.showcard { .showcard {
position:absolute; position:absolute;
display:none;
top:100px; top:100px;
left:100px; left:100px;
width:300px; width:300px;
@ -39,7 +45,7 @@
z-index:2; z-index:2;
color: #424242; color: #424242;
border-radius:2px; border-radius:2px;
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16); box-shadow: 2px 3px 3px rgba(125, 125, 125, 0.23), -2px -1px 3px rgba(125, 125, 125, 0.16);
} }
.text { .text {
@ -50,7 +56,6 @@
width:100%; width:100%;
height:100%; height:100%;
position: absolute; position: absolute;
display: none;
} }
.showcard .permission { .showcard .permission {
@ -62,7 +67,6 @@
display:block; display:block;
position:relative; position:relative;
width:100%; width:100%;
min-height:360px;
z-index: 25; z-index: 25;
} }
.CardOnGraph.hasAttachment { .CardOnGraph.hasAttachment {
@ -70,11 +74,11 @@
} }
.CardOnGraph .title { .CardOnGraph .title {
font-size: 18px; word-break: break-word;
line-height: 22px; font-size: 20px;
line-height: 24px;
display: table; display: table;
padding: 8px 0 16px; padding: 20px 0;
height: 80px;
text-align: center; text-align: center;
font-family: 'din-regular', sans-serif; font-family: 'din-regular', sans-serif;
width: 300px; width: 300px;
@ -93,12 +97,11 @@
cursor: text; cursor: text;
} }
.showcard .best_in_place_name textarea, .showcard .best_in_place_name input { .showcard .title .riek-editing {
font-family: 'din-regular', sans-serif; font-family: 'din-regular', sans-serif;
color: #424242; color: #424242;
font-size: 18px; font-size: 20px;
line-height: 22px; line-height: 24px;
height: 15px;
padding: 5px 0; padding: 5px 0;
width: 100%; width: 100%;
margin: 0; margin: 0;
@ -112,54 +115,76 @@
.CardOnGraph .scroll { .CardOnGraph .scroll {
display:block; display:block;
padding: 8px 0 8px 16px; padding: 8px 0 8px 16px;
height: 152px;
font-size: 13px; font-size: 13px;
line-height:15px; line-height:15px;
font-family: helvetica, sans-serif; font-family: helvetica, sans-serif;
overflow-y: auto; overflow-y: auto;
p.emptyDesc {
color: $mid-gray-opacity;
}
a.mdSupport {
color: #4fb5c0;
font-size: 11px;
display: none;
}
.riek-editing + .mdSupport {
display: block;
}
} }
.CardOnGraph.hasAttachment .scroll { .CardOnGraph.hasAttachment .scroll {
height: auto; height: auto;
} }
.CardOnGraph .best_in_place_desc textarea { .CardOnGraph .desc .riek-editing {
font-size: 13px; font-size: 13px;
line-height:15px; line-height:15px;
font-family: helvetica, sans-serif; font-family: helvetica, sans-serif;
color: #424242; color: #424242;
padding: 0; padding: 0;
width: 100%; width: 258px;
margin: 0; margin: 0;
border: 0; border: 0;
outline: none; outline: none;
font-size: 12px;
line-height: 15px;
background: none; background: none;
resize: none; overflow-y: scroll;
} }
.CardOnGraph .desc h3 { /*
* Styling for Markdown in topic cards
*/
.CardOnGraph .desc {
p, ol, ul {
padding: 0.15em 0;
}
h1, h2, h3, h4, h5, h6 {
font-style: normal; font-style: normal;
margin-top:5px; padding: 0.25em 0;
} }
.CardOnGraph .desc ol, ol,
.CardOnGraph .desc ul { ul {
margin-left: 1em; margin-left: 1em;
} }
.CardOnGraph .desc a:hover {
a:hover {
text-decoration: underline; text-decoration: underline;
opacity: 0.9; opacity: 0.9;
} }
.CardOnGraph .best_in_place_desc {
display:block;
margin-top:2px;
padding-right: 18px;
margin-right: 8px;
} }
.canEdit .CardOnGraph .best_in_place_desc:hover {
/*
* End Markdown styling
*/
.CardOnGraph .riek_desc {
display:block;
padding-right: 26px;
}
.canEdit .CardOnGraph .riek_desc:not(.riek-editing):hover {
background-image: url(<%= asset_data_uri('edit.png') %>); background-image: url(<%= asset_data_uri('edit.png') %>);
background-position: top right; background-position: top right;
background-repeat: no-repeat; background-repeat: no-repeat;
@ -172,117 +197,136 @@
.CardOnGraph .links { .CardOnGraph .links {
position: relative; position: relative;
border-bottom: 1px solid #BDBDBD; z-index: 2;
border-top: 1px solid #BDBDBD;
background-color: #e0e0e0;
}
.linkItem { .linkItem {
float: left; float: left;
height:46px;
z-index: 1; z-index: 1;
position: relative; position: relative;
color: #424242; color: #424242;
font-size: 14px; font-size: 14px;
line-height: 14px; line-height: 14px;
height:12px;
padding:17px 0; a {
}
.linkItem a {
color: #424242; color: #424242;
} }
}
.CardOnGraph .icon { .icon {
position:absolute;
width:100%;
z-index:1;
padding: 0; padding: 0;
height: 48px; height: 48px;
} margin-right: 10px;
.linkItem.contributor {
margin-left:40px; .metacodeImage {
z-index:1; cursor: move;
padding:17px 16px 17px 30px;
position: relative;
}
.contributor .contributorIcon {
position: absolute; position: absolute;
top: 8px; left: -18px;
left: 0; top: 6px;
border-radius: 16px; width: 36px;
height: 36px;
background-size:36px 36px;
background-position:0 0;
background-repeat:no-repeat;
}
}
} }
.contributor:hover .contributorName { .CardOnGraph .info {
display: block; position: relative;
.linkItem {
float: left;
z-index: 1;
position: relative;
color: $mid-gray-opacity;
font-size: 14px;
line-height: 14px;
a {
color: $mid-gray-opacity;
}
}
.contributor {
bottom: 7px;
margin-left: 16px;
.contributorIcon {
position: relative;
display: inline-block;
vertical-align: middle;
border-radius: 16px;
margin: 5px 5px 5px 0;
top: 11px;
left: 0;
}
span {
font-family: 'din-regular', sans-serif;
font-size: 14px;
} }
.contributorName { .contributorName {
display: none;
position: absolute;
background: black;
text-align: center;
color: white;
border-radius: 2px;
font-family: din-regular; font-family: din-regular;
line-height: 15px; margin-top: 20px;
font-size: 12px; display: inline-block;
padding: 3px 5px 2px; vertical-align: middle;
width: 97px;
padding: 0 8px 0 4px;
white-space: nowrap; white-space: nowrap;
margin-top: 36px; overflow: hidden;
margin-left: -32px; text-overflow: ellipsis;
}
} }
.contributor div:before { .mapCount {
content: ''; padding:17px 38px 17px 0;
position: absolute; width: 22px;
top: 128%; text-align: right;
left: 13px;
margin-top: -30px;
width: 0;
height: 0;
border-bottom: 4px solid #000000;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
.linkItem.mapCount { .mapCountIcon {
margin-left: 12px;
width: 24px;
padding:17px 0 17px 36px;
}
.linkItem.mapCount .mapCountIcon {
position: absolute; position: absolute;
top: 8px; top: 8px;
left: 0; right: 0;
width: 32px; width: 32px;
height: 32px; height: 32px;
background-image: url(<%= asset_data_uri('map32_sprite.png') %>); background-image: url(<%= asset_data_uri('map32_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 0; background-position: 0 0;
cursor: pointer; cursor: pointer;
opacity: 0.6;
} }
.linkItem.mapCount:hover .mapCountIcon {
&:hover .mapCountIcon {
background-position: 0 -32px; background-position: 0 -32px;
} }
.linkItem.mapCount:hover .hoverTip { .tip, .hoverTip {
display: block;
}
.CardOnGraph .mapCount .tip, .CardonGraph .mapCount .hoverTip {
top: 44px; top: 44px;
left: 0px; right: 0px;
font-size: 12px !important; font-size: 12px !important;
&:before {
content: '';
position: absolute;
top: 26px;
right: 10px;
margin-top: -30px;
width: 0;
height: 0;
border-bottom: 4px solid $mid-gray;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
} }
.hoverTip { .hoverTip {
white-space: nowrap; white-space: nowrap;
font-family: 'din-regular'; font-family: 'din-regular';
top: 44px; top: 44px;
left: 0px;
font-size: 12px !important; font-size: 12px !important;
display: none;
position: absolute; position: absolute;
background: black; background: $mid-gray;
color: white; color: white;
border-radius: 4px; border-radius: 4px;
line-height: 17px; line-height: 17px;
@ -290,21 +334,15 @@
z-index: 100; z-index: 100;
} }
.tip a {
.CardOnGraph .mapCount .tip:before, .CardOnGraph .mapCount .hoverTip:before { color: white;
content: '';
position: absolute;
top: 26px;
left: 10px;
margin-top: -30px;
width: 0;
height: 0;
border-bottom: 4px solid #000000;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
} }
.CardOnGraph .mapCount .tip li { .tip a:hover {
color: #757575;
}
.tip li {
list-style-type: none; list-style-type: none;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
@ -317,49 +355,34 @@
line-height: 14px; line-height: 14px;
position: relative; position: relative;
} }
.CardOnGraph .mapCount li.hideExtra {
display: none;
} }
.showMore { .synapseCount {
cursor: pointer; width: 22px;
color: #4FC059; padding:17px 38px 17px 0;
} text-align: right;
margin-right: 4px;
.mapCount .tip a { .synapseCountIcon {
color: white;
}
.mapCount .tip a:hover {
color: #757575;
}
.linkItem.synapseCount {
margin-left: 2px;
width: 24px;
padding:17px 0 17px 32px;
}
.linkItem.synapseCount .synapseCountIcon {
position: absolute; position: absolute;
top: 8px; top: 8px;
left: 0; right: 0;
width: 32px; width: 32px;
height: 32px; height: 32px;
background-image: url(<%= asset_data_uri('synapse32_sprite.png') %>); background-image: url(<%= asset_data_uri('synapse32_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 0; background-position: 0 0;
opacity: 0.6;
} }
.linkItem.synapseCount:hover .synapseCountIcon { hover .synapseCountIcon {
background-position: 0 -32px; background-position: 0 -32px;
} }
.tip {
.CardOnGraph .synapseCount .tip {
position: absolute; position: absolute;
background: black; background: $mid-gray;
width: auto; width: auto;
top: 44px; top: 44px;
right: 0px;
color: white; color: white;
white-space: nowrap; white-space: nowrap;
border-radius: 2px; border-radius: 2px;
@ -370,22 +393,28 @@
z-index: 100; z-index: 100;
} }
.CardOnGraph .synapseCount:hover .tip { .tip:before {
display: block;
}
.CardOnGraph .synapseCount .tip:before {
content: ''; content: '';
position: absolute; position: absolute;
margin-top: -8px; margin-top: -8px;
margin-left: 6px; right: 12px;
width: 0; width: 0;
height: 0; height: 0;
border-bottom: 4px solid black; border-bottom: 4px solid $mid-gray;
border-left: 5px solid transparent; border-left: 5px solid transparent;
border-right: 5px solid transparent; border-right: 5px solid transparent;
} }
}
}
.showMore {
cursor: pointer;
color: #4FC059;
}
.linkItem.mapPerm {
margin-right: 8px;
}
.mapPerm { .mapPerm {
width: 32px; width: 32px;
@ -408,13 +437,9 @@
} }
.yourTopic .mapPerm:hover, .yourEdge .mapPerm:hover { .yourTopic .mapPerm:hover, .yourEdge .mapPerm:hover {
background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>);
background-position: -32px 0;
cursor:pointer; cursor:pointer;
} }
.yourTopic .mapPerm.minimize, .yourEdge .mapPerm.minimize { .yourTopic .mapPerm.minimize, .yourEdge .mapPerm.minimize {
background-image: url(<%= asset_data_uri('arrowperms_sprite.png') %>) !important;
background-position: 0 0;
cursor: pointer; cursor: pointer;
} }
.mapPerm .permissionSelect { .mapPerm .permissionSelect {
@ -451,60 +476,52 @@ cursor: pointer;
} }
.CardOnGraph .metacodeTitle { .CardOnGraph .metacodeTitle {
font-style: italic; font-family: 'din-regular';
font-family: 'vinyl';
text-transform: uppercase;
position: absolute;
line-height: 24px; line-height: 24px;
height:24px; height: 26px;
font-size: 24px; font-size: 18px;
display: none; padding: 13px 24px 9px 24px;
width: 90%;
padding: 13px 0 9px 10%;
background-color: #E0E0E0;
color: #424242; color: #424242;
width: 120px;
max-width: 120px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
} }
.permission.canEdit .metacodeTitle { .permission.canEdit .metacodeTitle {
cursor:pointer; cursor:pointer;
} }
.permission.canEdit .expandMetacodeSelect { .permission.canEdit .expandMetacodeSelect {
position: absolute; position: relative;
top: 16px; top: 2px;
right: 16px; left: 4px;
width: 16px; width: 16px;
height: 16px; height: 16px;
background-image: url(<%= asset_data_uri('arrowright_sprite.png') %>); background-image: url(<%= asset_data_uri('arrowright_sprite.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0 -32px; background-position: 0 -32px;
display: inline-block;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
} }
.permission.canEdit .minimize .expandMetacodeSelect { .permission.canEdit .minimize .expandMetacodeSelect {
} }
.CardOnGraph .metacodeImage { .CardOnGraph .metacodeName {
cursor:move; display: inline-block;
width:46px;
height:46px;
position:absolute;
left:-23px;
top:0;
background-size:46px 46px;
background-position:0 0;
background-repeat:no-repeat;
} }
#metacodeOptions {
display:none;
}
.CardOnGraph .metacodeSelect { .CardOnGraph .metacodeSelect {
display:none; display:none;
width:auto; width:auto;
z-index: 2; z-index: 2;
position: absolute;
background: #EAEAEA; background: #EAEAEA;
left: 300px;
white-space: nowrap; white-space: nowrap;
position: absolute;
top: 48px;
box-shadow: 2px 2px 2px rgba(125, 125, 125, 0.23), -2px -1px 3px rgba(125, 125, 125, 0.16);
} }
.CardOnGraph .metacodeSelect ul { .CardOnGraph .metacodeSelect ul {
position: relative; position: relative;
@ -592,15 +609,14 @@ background-color: #E0E0E0;
position: relative; position: relative;
} }
.CardOnGraph .hoverForTip:hover .tip, .mapCard .hoverForTip:hover .tip, #mapContribs:hover .tip { .CardOnGraph .hoverForTip:hover .tip, #mapContribs:hover .tip {
display:block; display:block;
} }
.CardOnGraph .tip, .mapCard .tip { .CardOnGraph .tip {
display:none;
position: absolute; position: absolute;
background: black; background: $mid-gray;
top: 35px; top: 35px;
left: 0; right: 0;
color: white; color: white;
border-radius: 4px; border-radius: 4px;
font-size:15px !important; font-size:15px !important;
@ -609,21 +625,18 @@ background-color: #E0E0E0;
z-index:100; z-index:100;
} }
#embedlyLink {
display: none;
}
#embedlyLinkLoader { #embedlyLinkLoader {
margin: 0 auto; margin: 0 auto;
width: 28px; width: 28px;
} }
.CardOnGraph .attachments { .CardOnGraph .link-adder {
border-top: 1px solid #BDBDBD;
width:100%; width:100%;
height:47px; height:47px;
position: relative;
} }
.attachments a { .link-adder a {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
@ -682,9 +695,9 @@ background-color: #E0E0E0;
} }
#addLinkInput input{ #addLinkInput input{
padding: 9px 7px 9px 31px; padding: 9px 27px 9px 31px;
height: 12px; height: 12px;
width: 198px; width: 210px;
margin: 0 0 0 0; margin: 0 0 0 0;
border: none; border: none;
outline: none; outline: none;
@ -738,7 +751,6 @@ font-family: 'din-regular', helvetica, sans-serif;
-moz-border-radius-bottomright: 8px; -moz-border-radius-bottomright: 8px;
-webkit-border-bottom-right-radius: 8px; -webkit-border-bottom-right-radius: 8px;
border-bottom-right-radius: 8px; border-bottom-right-radius: 8px;
display: none;
margin: 8px; margin: 8px;
} }
@ -825,10 +837,10 @@ font-family: 'din-regular', helvetica, sans-serif;
line-height: 16px; line-height: 16px;
} }
.canEdit #edit_synapse_desc:hover { .canEdit span.titleWrapper:hover {
background-image: url(<%= asset_data_uri('edit.png') %>); background-image: url(<%= asset_data_uri('edit.png') %>);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 164px center; background-position: 95% 95%;
cursor: text; cursor: text;
} }
@ -952,160 +964,14 @@ font-family: 'din-regular', helvetica, sans-serif;
background-position: 0 -24px; background-position: 0 -24px;
} }
/* Map Cards */
.map {
display:inline-block;
width:220px;
height:340px;
font-size: 12px;
text-align: left;
overflow: visible;
background: #e8e8e8;
border-radius:2px;
margin:16px 16px 16px 19px;
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
}
.map:hover {
background: #dcdcdc;
}
.map.newMap {
float: left;
position: relative;
}
.map.newMap a {
height: 340px;
display: block;
position: relative;
}
.newMap .newMapImage {
display: block;
width: 72px;
height: 72px;
background-image: url("<%= asset_data_uri('newmap_sprite.png') %>");
background-repeat: no-repeat;
background-position: 0 0;
position: absolute;
left: 50%;
margin-left: -36px;
top: 50%;
margin-top: -36px;
}
.map:hover .newMapImage {
background-position: 0 -72px;
}
.newMap span {
font-family: 'din-regular', sans-serif;
font-size: 18px;
line-height: 22px;
text-align: center;
display: block;
padding-top: 220px;
}
.mapCard {
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
display: -ms-flexbox; /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Chrome */
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-webkit-box-direction: normal;
-moz-box-direction: normal;
-ms-flex-direction: column;
-webkit-flex-direction: column;
flex-direction: column;
position:relative;
width:100%;
height:308px;
padding: 16px 0;
color: #424242;
}
.mapCard .title {
word-wrap: break-word;
font-size:18px;
line-height:22px;
height: 44px;
display:block;
padding: 0 16px;
text-align: center;
-webkit-box-flex: none; /* OLD - iOS 6-, Safari 3.1-6 */
-moz-box-flex: none; /* OLD - Firefox 19- */
-webkit-flex: none; /* Chrome */
-ms-flex: none; /* IE 10 */
flex: none; /* NEW, Spec - Opera 12.1, Firefox 20+ */
font-family: 'din-regular', sans-serif;
}
.mapCard .mapScreenshot {
width: 188px;
height: 126px;
padding: 8px 16px;
}
.mapCard .mapScreenshot img {
width: 188px;
height: 126px;
border-radius: 2px;
}
.mapCard .scroll {
display:block;
-webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */
-moz-box-flex: 1; /* OLD - Firefox 19- */
-webkit-flex: 1; /* Chrome */
-ms-flex: 1; /* IE 10 */
flex: 1; /* NEW, Spec - Opera 12.1, Firefox 20+ */
padding:0 16px 8px;
font-family: helvetica, sans-serif;
font-style: italic;
font-size: 12px;
word-wrap: break-word;
}
.mCS_no_scrollbar {
padding-right: 5px;
}
.mapCard .mapMetadata {
font-family: 'din-regular', sans-serif;
font-size: 12px;
position:relative;
border-top: 1px solid #BDBDBD;
-webkit-box-flex: none; /* OLD - iOS 6-, Safari 3.1-6 */
-moz-box-flex: none; /* OLD - Firefox 19- */
-webkit-flex: none; /* Chrome */
-ms-flex: none; /* IE 10 */
flex: none; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
.mapCard .metadataSection {
padding: 8px 16px 0 16px;
width: 78px;
float: left;
}
.mapPermission {
font-family: 'din-medium', sans-serif;
}
.cCountColor {
font-family: 'din-medium', sans-serif;
color: #DB5D5D;
}
.tCountColor {
font-family: 'din-medium', sans-serif;
color: #4FC059;
}
.sCountColor {
font-family: 'din-medium', sans-serif;
color: #DAB539;
}
/* mapper card */ /* mapper card */
.mapper { .mapper {
float: left; display: inline-block;
vertical-align: bottom;
width:220px; width:220px;
height:340px; height:340px;
font-size: 12px; font-size: 12px;
@ -1113,7 +979,7 @@ font-family: 'din-regular', helvetica, sans-serif;
overflow: visible; overflow: visible;
background: #E0E0E0; background: #E0E0E0;
border-radius:2px; border-radius:2px;
margin:16px 16px 16px 19px; margin:16px;
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16); box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
} }
@ -1137,10 +1003,10 @@ font-family: 'din-regular', helvetica, sans-serif;
font-size: 24px; font-size: 24px;
text-align: center; text-align: center;
margin-top: 24px; margin-top: 24px;
padding: 0 16px; padding: 0 5%;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
width: 189px; width: 90%;
overflow: hidden; overflow: hidden;
} }

View file

@ -28,6 +28,9 @@
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
box-sizing: border-box;
padding-top: 92px;
overflow-y: auto;
} }
/*.animations { /*.animations {
@ -44,23 +47,9 @@
transition-timing-function: ease-in-out; transition-timing-function: ease-in-out;
}*/ }*/
.mapElement {
display: none;
}
.mapPage .mapElement, .topicPage .mapElement {
display: block;
}
.mapPage .mapElementHidden {
display:none;
}
.topicPage .starMap {
display: none;
}
/* loading */ /* loading */
#loading { #loading {
display: none;
width: 28px; width: 28px;
height: 28px; height: 28px;
position: fixed; position: fixed;
@ -179,10 +168,14 @@
} }
.upperRightMapButtons { .upperRightMapButtons {
top: -42px; /* puts it just offscreen */ right: 138px;
padding-right: 7px;
border-right: 1px solid #747474;
} }
.mapPage .upperRightMapButtons, .topicPage .upperRightMapButtons { .unauthenticated .upperRightMapButtons {
top: 0; right: 115px;
padding-right: 0;
border-right: none;
} }
.upperRightIcon { .upperRightIcon {
@ -192,30 +185,47 @@
background-repeat: no-repeat; background-repeat: no-repeat;
cursor: pointer; cursor: pointer;
} }
.sidebarFilterIcon { .sidebarFilterIcon {
background-position: -64px 0; background-position: -32px 0;
} }
.sidebarForkIcon { .sidebarForkIcon {
background-position: -96px 0; background-position: -64px 0;
} }
.addMap { .addMap {
background-position: -96px 0;
}
.notificationsIcon {
background-position: -128px 0; background-position: -128px 0;
margin-right:10px; margin-right: 10px; // make it look more natural next to the account menu icon
}
.notificationsIcon:hover {
background-position: -128px -32px;
}
.importDialog:hover {
background-position: 0 -32px;
} }
.sidebarFilterIcon:hover { .sidebarFilterIcon:hover {
background-position: -64px -32px; background-position: -32px -32px;
} }
.sidebarForkIcon:hover { .sidebarForkIcon:hover {
background-position: -96px -32px; background-position: -64px -32px;
} }
.addMap:hover { .addMap:hover {
background-position: -128px -32px; background-position: -96px -32px;
margin-right:10px;
} }
/* end upperRightUI */ /* end upperRightUI */
/* map wrapper */
.mapWrapper {
position:absolute;
width: 100%;
height: 100%;
}
/* end map wrapper */
/* yield */ /* yield */
@ -336,22 +346,15 @@
/* infoAndHelp */ /* infoAndHelp */
.mapPage .infoAndHelp, .topicPage .infoAndHelp { .openCheatsheet .tooltipsAbove {
right: 70px;
}
.mapPage .openCheatsheet .tooltipsAbove, .topicPage .openCheatsheet .tooltipsAbove {
right: 1px; right: 1px;
left: auto; left: auto;
} }
.unauthenticated .homePage .infoAndHelp {
display:none;
}
.infoAndHelp { .infoAndHelp {
position: absolute; position: absolute;
bottom: 20px; bottom: 20px;
right: 20px; right: 70px;
z-index: 3; z-index: 3;
width: auto; width: auto;
font-style: italic; font-style: italic;
@ -372,22 +375,13 @@
} }
.mapInfoIcon { .mapInfoIcon {
position: relative; position: relative;
top: 56px; /* puts it just offscreen */
background-image: url(<%= asset_path('mapinfo_sprite.png') %>); background-image: url(<%= asset_path('mapinfo_sprite.png') %>);
background-repeat:no-repeat; background-repeat:no-repeat;
} }
.mapInfoIcon:hover { .mapInfoIcon:hover {
background-position: 0 -32px; background-position: 0 -32px;
} }
.mapPage .mapInfoIcon {
top: 0;
}
.importDialog {
background-image: url(<%= asset_path('import.png') %>);
background-position: 0 0;
background-repeat: no-repeat;
width: 32px;
}
.starMap { .starMap {
background-image: url(<%= asset_path('starmap_sprite.png') %>); background-image: url(<%= asset_path('starmap_sprite.png') %>);
background-position: 0 0; background-position: 0 0;
@ -404,9 +398,6 @@
background-position: 0 0; background-position: 0 0;
} }
.unauthenticated .mapPage .starMap {
display: none;
}
/* end infoAndHelp */ /* end infoAndHelp */
@ -415,17 +406,10 @@
.mapControls { .mapControls {
position: absolute; position: absolute;
bottom: 24px; bottom: 24px;
right:-32px; /* puts it just offscreen */ right:24px;
width:32px; width:32px;
z-index: 3; z-index: 3;
} }
.mapPage .mapControls, .topicPage .mapControls {
right: 24px;
}
.topicPage .zoomExtents {
display: none;
}
.mapControl { .mapControl {
width:32px; width:32px;
@ -440,19 +424,6 @@
z-index: 4; z-index: 4;
} }
.takeScreenshot {
margin-bottom: 5px;
border-radius: 2px;
background-image: url(<%= asset_path 'screenshot_sprite.png' %>);
display: none;
}
.takeScreenshot:hover {
background-position: -32px 0;
}
.canEditMap .takeScreenshot {
display: block;
}
.zoomExtents { .zoomExtents {
margin-bottom:5px; margin-bottom:5px;
border-radius: 2px; border-radius: 2px;
@ -463,8 +434,8 @@
background-position: -32px 0; background-position: -32px 0;
} }
.zoomExtents:hover .tooltips, .zoomIn:hover .tooltips, .zoomOut:hover .tooltips, .takeScreenshot:hover .tooltips, .sidebarFilterIcon:hover .tooltipsUnder, .sidebarForkIcon:hover .tooltipsUnder, .addMap:hover .tooltipsUnder, .authenticated .sidebarAccountIcon:hover .tooltipsUnder, .zoomExtents:hover .tooltips, .zoomIn:hover .tooltips, .zoomOut:hover .tooltips, .sidebarFilterIcon:hover .tooltipsUnder, .sidebarForkIcon:hover .tooltipsUnder, .notificationsIcon:hover .tooltipsUnder, .addMap:hover .tooltipsUnder, .authenticated .sidebarAccountIcon:hover .tooltipsUnder,
.mapInfoIcon:hover .tooltipsAbove, .openCheatsheet:hover .tooltipsAbove, .chat-button:hover .tooltips, importDialog:hover .tooltipsAbove, .starMap:hover .tooltipsAbove, .openMetacodeSwitcher:hover .tooltipsAbove, .pinCarousel:not(.isPinned):hover .tooltipsAbove.helpPin, .pinCarousel.isPinned:hover .tooltipsAbove.helpUnpin { .mapInfoIcon:hover .tooltipsAbove, .openCheatsheet:hover .tooltipsAbove, .chat-button:hover .tooltips, .importDialog:hover .tooltipsUnder, .starMap:hover .tooltipsAbove, .openMetacodeSwitcher:hover .tooltipsAbove, .pinCarousel:not(.isPinned):hover .tooltipsAbove.helpPin, .pinCarousel.isPinned:hover .tooltipsAbove.helpUnpin {
display: block; display: block;
} }
@ -520,9 +491,16 @@
font-style: normal; font-style: normal;
} }
.importDialog .tooltipsUnder {
left: -22px;
}
.sidebarFilterIcon .tooltipsUnder { .sidebarFilterIcon .tooltipsUnder {
margin-left: -4px; margin-left: -4px;
} }
.notificationsIcon .tooltipsUnder {
left: -20px;
}
.sidebarForkIcon .tooltipsUnder { .sidebarForkIcon .tooltipsUnder {
margin-left: -34px; margin-left: -34px;
@ -578,16 +556,12 @@
left: -8px; left: -8px;
} }
.openCheatsheet .tooltipsAbove {
left: -4px;
}
.sidebarAccountIcon .tooltipsUnder { .sidebarAccountIcon .tooltipsUnder {
margin-left: -12px; margin-left: -12px;
margin-top: 40px; margin-top: 40px;
} }
.zoomExtents div::after, .zoomIn div::after, .zoomOut div::after, .takeScreenshot div:after, .chat-button div.tooltips::after { .zoomExtents div::after, .zoomIn div::after, .zoomOut div::after, .chat-button div.tooltips::after {
content: ''; content: '';
position: absolute; position: absolute;
top: 57%; top: 57%;
@ -600,7 +574,12 @@
border-bottom: 5px solid transparent; border-bottom: 5px solid transparent;
} }
.sidebarFilterIcon div:after, .sidebarForkIcon div:after, .addMap div:after, .sidebarAccountIcon .tooltipsUnder:after { .addMap div:after,
.importDialog div:after,
.sidebarForkIcon div:after,
.sidebarFilterIcon div:after,
.notificationsIcon div:after,
.sidebarAccountIcon .tooltipsUnder:after {
content: ''; content: '';
position: absolute; position: absolute;
right: 40%; right: 40%;
@ -611,9 +590,15 @@
border-left: 5px solid transparent; border-left: 5px solid transparent;
border-right: 5px solid transparent; border-right: 5px solid transparent;
} }
.notificationsIcon .unread-notifications-dot:after {
content: none;
}
.sidebarFilterIcon div:after { .sidebarFilterIcon div:after {
right: 37% !important; right: 37% !important;
} }
.notificationsIcon div:after {
right: 46% !important;
}
.mapInfoIcon div:after, .openCheatsheet div:after, .starMap div:after, .openMetacodeSwitcher div:after, .pinCarousel div:after { .mapInfoIcon div:after, .openCheatsheet div:after, .starMap div:after, .openMetacodeSwitcher div:after, .pinCarousel div:after {
content: ''; content: '';
@ -651,20 +636,22 @@
/* explore maps */ /* explore maps */
#explore { #react-app {
display: none; position: absolute;
height: 100%;
width: 100%;
overflow-y: auto;
} }
#exploreMaps { #exploreMaps {
padding: 0 5%;
position: absolute; position: absolute;
width: 90%;
height: 100%; height: 100%;
width: 100%;
overflow-y: auto; overflow-y: auto;
} }
#exploreMaps > div { #exploreMaps > div {
margin-top: 110px; margin: 110px auto 0 auto;
} }
.button.loadMore { .button.loadMore {
@ -672,23 +659,28 @@
display: block; display: block;
} }
.appsPage #exploreMapsHeader { .requestInviteHeader {
display: block; position: absolute;
width: 100%;
z-index:2;
background-color:#FAFAFA;
height: 52px;
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
} }
#exploreMapsHeader { #navBar {
position: absolute; position: absolute;
width: 100%; width: 100%;
} }
.exploreMapsBar { .navBarContainer {
z-index:2; z-index:2;
background-color:#FAFAFA; background-color:#FAFAFA;
height: 42px; height: 42px;
padding-top: 52px; padding-top: 52px;
} }
.exploreMapsMenu { .navBarMenu {
display: block; display: block;
width: 100%; width: 100%;
height:42px; height:42px;
@ -697,30 +689,29 @@
text-align: center; text-align: center;
} }
.exploreMapsCenter { .navBarCenter {
display: block; display: block;
} }
.exploreMapsButton { .navBarButton {
color: #757575; color: #757575;
cursor: default; cursor: default;
font-weight: normal; font-weight: normal;
font-family: 'din-medium'; font-family: 'din-medium';
font-size: 14px; font-size: 14px;
height: 14px; padding: 0 8px;
padding: 14px 8px 12px 40px;
border-bottom: 2px solid rgba(0,0,0,0); border-bottom: 2px solid rgba(0,0,0,0);
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
position:relative; position:relative;
} }
.exploreMapsButton:hover, .exploreMapsButton.active { .navBarButton:hover, .navBarButton.active {
text-decoration: none; text-decoration: none;
color: #424242; color: #424242;
border-bottom: 2px solid #00BCD4; border-bottom: 2px solid #00BCD4;
} }
.exploreMapsButton.mapperButton { .navBarButton.mapperButton {
height: 40px; height: 40px;
padding: 0; padding: 0;
} }
@ -737,49 +728,71 @@
} }
.exploreMapsButton .exploreMapsIcon { .navBarButton .navBarIcon {
background-repeat: no-repeat; background-repeat: no-repeat;
width:32px; width:32px;
height:32px; height:32px;
position:absolute; margin-top:5px;
top:5px; margin-left:5px;
left:5px; margin-right: 5px;
display: inline-block;
vertical-align: top;
} }
.exploreMapsCenter .myMaps .exploreMapsIcon {
.navBarLinkText {
padding: 11px 0 12px 0;
display: inline-block;
}
.navBarCenter .authedApps .navBarIcon {
background-image: url(<%= asset_path('user_sprite.png') %>);
background-position: 0 -32px;
}
.navBarCenter .myMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>); background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -32px 0; background-position: -32px 0;
} }
.exploreMapsCenter .sharedMaps .exploreMapsIcon { .navBarCenter .sharedMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>); background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -128px 0; background-position: -128px 0;
} }
.exploreMapsCenter .activeMaps .exploreMapsIcon { .navBarCenter .activeMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>); background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: 0 0; background-position: 0 0;
} }
.exploreMapsCenter .featuredMaps .exploreMapsIcon { .navBarCenter .featuredMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>); background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -96px 0; background-position: -96px 0;
} }
.exploreMapsCenter .starredMaps .exploreMapsIcon { .navBarCenter .starredMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>); background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -96px 0; background-position: -96px 0;
} }
.myMaps:hover .exploreMapsIcon, .myMaps.active .exploreMapsIcon { .navBarCenter .notificationsLink .navBarIcon {
background-image: url(<%= asset_path 'topright_sprite.png' %>);
background-position: -128px 0;
}
.authedApps:hover .navBarIcon, .authedApps.active .navBarIcon {
background-position-x: -32px;
}
.myMaps:hover .navBarIcon, .myMaps.active .navBarIcon {
background-position: -32px -32px; background-position: -32px -32px;
} }
.activeMaps:hover .exploreMapsIcon, .activeMaps.active .exploreMapsIcon { .activeMaps:hover .navBarIcon, .activeMaps.active .navBarIcon {
background-position: 0 -32px; background-position: 0 -32px;
} }
.featuredMaps:hover .exploreMapsIcon, .featuredMaps.active .exploreMapsIcon { .featuredMaps:hover .navBarIcon, .featuredMaps.active .navBarIcon {
background-position: -96px -32px; background-position: -96px -32px;
} }
.starredMaps:hover .exploreMapsIcon, .starredMaps.active .exploreMapsIcon { .starredMaps:hover .navBarIcon, .starredMaps.active .navBarIcon {
background-position: -96px -32px; background-position: -96px -32px;
} }
.sharedMaps:hover .exploreMapsIcon, .sharedMaps.active .exploreMapsIcon { .sharedMaps:hover .navBarIcon, .sharedMaps.active .navBarIcon {
background-position: -128px -32px; background-position: -128px -32px;
} }
.notificationsLink:hover .navBarIcon, .notificationsLink.active .navBarIcon {
background-position-y: -32px;
}
.mapsWrapper { .mapsWrapper {
/*overflow-y: auto; */ /*overflow-y: auto; */
@ -795,7 +808,6 @@
height: 80px; height: 80px;
font-family: 'din-regular', helvetica, sans-serif; font-family: 'din-regular', helvetica, sans-serif;
font-size: 32px; font-size: 32px;
display: none;
text-align: center; text-align: center;
color: #999999; color: #999999;
z-index: 0; z-index: 0;
@ -811,7 +823,6 @@
/* toast */ /* toast */
.toast { .toast {
display: none;
position: fixed; position: fixed;
bottom: 20px; bottom: 20px;
left: 20px; left: 20px;

View file

@ -0,0 +1,263 @@
.emoji-mart,
.emoji-mart * {
box-sizing: border-box;
line-height: 1.15;
}
.emoji-mart {
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
font-size: 16px;
display: inline-block;
color: #222427;
border: 1px solid #d9d9d9;
border-radius: 5px;
background: #fff;
}
.emoji-mart .emoji-mart-emoji {
padding: 6px;
}
.emoji-mart-bar:first-child {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.emoji-mart-bar:last-child {
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
.emoji-mart-anchors {
display: flex;
justify-content: space-between;
padding: 0 6px;
color: #858585;
line-height: 0;
}
.emoji-mart-anchor {
position: relative;
flex: 1;
text-align: center;
padding: 12px 4px;
overflow: hidden;
transition: color .1s ease-out;
}
.emoji-mart-anchor:hover,
.emoji-mart-anchor-selected {
color: #464646;
}
.emoji-mart-anchor-selected .emoji-mart-anchor-bar {
bottom: 0;
}
.emoji-mart-anchor-bar {
position: absolute;
bottom: -3px; left: 0;
width: 100%; height: 3px;
background-color: #464646;
}
.emoji-mart-anchors i {
display: inline-block;
width: 100%;
max-width: 22px;
}
.emoji-mart-anchors svg {
fill: currentColor;
}
.emoji-mart-scroll {
overflow-y: scroll;
height: 270px;
padding: 0 6px 6px 6px;
border: solid #d9d9d9;
border-width: 1px 0;
}
.emoji-mart-search {
font-size: 16px;
display: block;
width: 100%;
padding: .2em .6em;
margin-top: 6px;
border-radius: 25px;
border: 1px solid #d9d9d9;
outline: 0;
}
.emoji-mart-category .emoji-mart-emoji span {
z-index: 1;
position: relative;
}
.emoji-mart-category .emoji-mart-emoji:hover:before {
z-index: 0;
content: "";
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background-color: #f4f4f4;
border-radius: 100%;
}
.emoji-mart-category-label {
z-index: 2;
position: relative;
position: -webkit-sticky;
top: 0;
}
.emoji-mart-category-label span {
display: block;
width: 100%;
font-weight: 500;
padding: 5px 6px;
background-color: #fff;
background-color: rgba(255, 255, 255, .95);
}
.emoji-mart-emoji {
position: relative;
display: inline-block;
font-size: 0;
}
.emoji-mart-no-results {
font-size: 14px;
text-align: center;
padding-top: 70px;
color: #858585;
}
.emoji-mart-no-results span {
display: inline-block;
vertical-align: middle;
}
.emoji-mart-preview {
position: relative;
height: 70px;
}
.emoji-mart-preview-emoji,
.emoji-mart-preview-data,
.emoji-mart-preview-skins {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.emoji-mart-preview-emoji {
left: 12px;
}
.emoji-mart-preview-data {
left: 68px; right: 12px;
word-break: break-word;
}
.emoji-mart-preview-skins {
right: 30px;
text-align: right;
}
.emoji-mart-preview-name {
font-size: 14px;
}
.emoji-mart-preview-shortname {
font-size: 12px;
color: #888;
}
.emoji-mart-preview-shortname + .emoji-mart-preview-shortname,
.emoji-mart-preview-shortname + .emoji-mart-preview-emoticon,
.emoji-mart-preview-emoticon + .emoji-mart-preview-emoticon {
margin-left: .5em;
}
.emoji-mart-preview-emoticon {
font-size: 11px;
color: #bbb;
}
.emoji-mart-title span {
display: inline-block;
vertical-align: middle;
}
.emoji-mart-title .emoji-mart-emoji {
padding: 0;
}
.emoji-mart-title-label {
color: #999A9C;
font-size: 26px;
font-weight: 300;
}
.emoji-mart-skin-swatches {
font-size: 0;
padding: 2px 0;
border: 1px solid #d9d9d9;
border-radius: 12px;
background-color: #fff;
}
.emoji-mart-skin-swatches-opened .emoji-mart-skin-swatch {
width: 16px;
padding: 0 2px;
}
.emoji-mart-skin-swatches-opened .emoji-mart-skin-swatch-selected:after {
opacity: .75;
}
.emoji-mart-skin-swatch {
display: inline-block;
width: 0;
vertical-align: middle;
transition-property: width, padding;
transition-duration: .125s;
transition-timing-function: ease-out;
}
.emoji-mart-skin-swatch:nth-child(1) { transition-delay: 0 }
.emoji-mart-skin-swatch:nth-child(2) { transition-delay: .03s }
.emoji-mart-skin-swatch:nth-child(3) { transition-delay: .06s }
.emoji-mart-skin-swatch:nth-child(4) { transition-delay: .09s }
.emoji-mart-skin-swatch:nth-child(5) { transition-delay: .12s }
.emoji-mart-skin-swatch:nth-child(6) { transition-delay: .15s }
.emoji-mart-skin-swatch-selected {
position: relative;
width: 16px;
padding: 0 2px;
}
.emoji-mart-skin-swatch-selected:after {
content: "";
position: absolute;
top: 50%; left: 50%;
width: 4px; height: 4px;
margin: -2px 0 0 -2px;
background-color: #fff;
border-radius: 100%;
pointer-events: none;
opacity: 0;
transition: opacity .2s ease-out;
}
.emoji-mart-skin {
display: inline-block;
width: 100%; padding-top: 100%;
max-width: 12px;
border-radius: 100%;
}
.emoji-mart-skin-tone-1 { background-color: #ffc93a }
.emoji-mart-skin-tone-2 { background-color: #fadcbc }
.emoji-mart-skin-tone-3 { background-color: #e0bb95 }
.emoji-mart-skin-tone-4 { background-color: #bf8f68 }
.emoji-mart-skin-tone-5 { background-color: #9b643d }
.emoji-mart-skin-tone-6 { background-color: #594539 }

View file

@ -1,11 +1,9 @@
/* =USERVOICE ICON DEFINE .unauthenticated .feedback-icon {
--------------------------------------------------------*/
.unauthenticated .uv-icon {
display: none; display: none;
} }
div.uv-icon.uv-bottom-left { .feedback-icon {
position: fixed;
background-image: url(<%= asset_data_uri 'feedback_sprite.png' %>); background-image: url(<%= asset_data_uri 'feedback_sprite.png' %>);
background-repeat: no-repeat; background-repeat: no-repeat;
color:#FFFFFF; color:#FFFFFF;
@ -20,6 +18,8 @@ div.uv-icon.uv-bottom-left {
opacity: 1; opacity: 1;
} }
div.uv-icon.uv-bottom-left:hover { .feedback-icon:hover {
background-position: 0 -110px; background-position: 0 -110px;
} }

View file

@ -1,348 +0,0 @@
.collaborator-video {
z-index: 1;
position: absolute;
width: 150px;
height: 150px;
cursor: default;
color: #FFF;
}
.collaborator-video .video-receive {
position: absolute;
width: 160px;
padding: 20px 20px 20px 170px;
background: #424242;
height: 110px;
border-top-left-radius: 75px;
border-bottom-left-radius: 75px;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
}
.collaborator-video .video-receive .video-statement {
margin-bottom: 10px;
}
.collaborator-video .video-receive .btn-group .btn-yes {
margin-right: 10px;
}
.collaborator-video .video-receive .btn-group .btn-no {
background-color: #c04f4f;
}
.collaborator-video .video-receive .btn-group .btn-no:hover {
background-color: #A54242;
}
.collaborator-video .video-cutoff {
width: 150px;
height: 150px;
overflow: hidden;
border-radius: 75px;
z-index: 0;
position: relative;
-webkit-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
-moz-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
}
.collaborator-video .video-cutoff video {
height: 150px;
margin-left: -25px;
}
.collaborator-video .video-cutoff .collaborator-video-avatar {
position: absolute;
top: 0;
left: 0;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
-webkit-user-drag: none;
display: none;
}
.collaborator-video .video-audio {
position: absolute;
width: 24px;
height: 24px;
top: 85%;
right: 0px;
cursor: pointer;
background: url(<%= asset_path 'audio_sprite.png' %>) no-repeat;
}
.collaborator-video .video-audio:hover {
background-position-x: -24px;
}
.collaborator-video .video-audio.active {
background-position-y: -24px;
}
.collaborator-video .video-video {
position: absolute;
width: 24px;
height: 24px;
top: 85%;
left: 0px;
cursor: pointer;
background: url(<%= asset_path 'camera_sprite.png' %>) no-repeat;
}
.collaborator-video .video-video:hover {
background-position-x: -24px;
}
.collaborator-video .video-video.active {
background-position-y: -24px;
}
.collaborator-video.my-video {
left: 30px;
top: 72px;
}
.chat-box {
position: relative;
display: flex;
flex-direction: column;
z-index: 1;
width: 300px;
float: right;
height: 100%;
background: #424242;
box-shadow: -8px 0px 16px 2px rgba(0, 0, 0, 0.23);
}
.chat-box .chat-button {
position: absolute;
top: 50%;
left: -36px;
width: 36px;
height: 49px;
background: url(<%= asset_path 'junto.png' %>) no-repeat 2px 9px, url(<%= asset_path 'tray_tab.png' %>) no-repeat;
cursor: pointer;
}
.chat-box .chat-button.active {
background: url(<%= asset_path 'junto_spinner_dark.gif' %>) no-repeat 2px 8px, url(<%= asset_path 'tray_tab.png' %>) no-repeat !important;
}
.chat-box .chat-button .chat-unread {
display: none;
background: #DAB539;
position: absolute;
top: -3px;
left: -11px;
width: 20px;
height: 20px;
border-radius: 11px;
border: 2px solid #424242;
color: #424242;
text-align: center;
font-size: 12px;
font-weight: bold;
line-height: 20px;
}
.chat-box .junto-header {
width: 276px;
padding: 16px 8px 16px 16px;
font-size: 16px;
text-align: left;
font-weight: bold;
background-color: #000000;
color: #f5f5f5;
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23);
}
.chat-box .junto-header .cursor-toggle {
width: 32px;
height: 32px;
margin-right: 8px;
margin-top: -8px;
float: right;
background: url(<%= asset_path 'cursor_sprite.png' %>) no-repeat;
}
.chat-box .junto-header .cursor-toggle:hover {
background-position-x: -32px;
}
.chat-box .junto-header .cursor-toggle.active {
background-position-y: -32px;
}
.chat-box .junto-header .video-toggle {
width: 32px;
height: 32px;
margin-right: 10px;
margin-top: -8px;
float: right;
background: url(<%= asset_path 'video_sprite.png' %>) no-repeat;
}
.chat-box .junto-header .video-toggle:hover {
background-position-x: -32px;
}
.chat-box .junto-header .video-toggle.active {
background-position-y: -32px;
}
.chat-box .participants {
width: 100%;
min-height: 150px;
padding: 16px 0px 16px 0px;
text-align: left;
color: #f5f5f5;
overflow-y: auto;
}
.chat-box .participants .conversation-live {
display: none;
padding: 5px 10px 5px 10px;
background: #c04f4f;
margin: 5px 10px;
border-radius: 2px;
}
.chat-box .participants .conversation-live .call-action {
float: right;
cursor: pointer;
color: #EBFF00;
}
.chat-box .participants .conversation-live .leave {
display: none;
}
.chat-box .participants.is-participating .conversation-live .leave {
display: block;
}
.chat-box .participants.is-participating .conversation-live .join {
display: none;
}
.chat-box .participants .participant {
width: 89%;
padding: 8px 8px 2px 8px;
color: #f5f5f5;
font-family: arial, sans-serif;
font-size: 13px;
line-height: 14px;
}
.chat-box .participants .participant .chat-participant-image {
width: 15%;
float: left;
overflow: hidden;
color: #BBB;
padding-top: 2px;
}
.chat-box .participants .participant .chat-participant-image img {
width: 32px;
height: 32px;
border-radius: 18px;
}
.chat-box .participants .participant .chat-participant-name {
width: 53%;
float: left;
font-size: 13px;
font-weight: bold;
margin-top: 12px;
padding: 2px 8px 0;
text-align: left;
}
.chat-box .participants .participant.is-self .chat-participant-invite-call,
.chat-box .participants .participant.is-self .chat-participant-invite-join {
display: none !important;
}
.chat-box .participants.is-live .participant .chat-participant-invite-call {
display: none;
}
.chat-box .participants .participant .chat-participant-invite-join {
display: none;
}
.chat-box .participants.is-live.is-participating .participant:not(.active) .chat-participant-invite-join {
display: block;
}
.chat-box .participants .participant .chat-participant-invite-call,
.chat-box .participants .participant .chat-participant-invite-join
{
float: right;
background: #4FC059 url(<%= asset_path 'invitepeer16.png' %>) no-repeat center center;
}
.chat-box .participants .participant.pending .chat-participant-invite-call,
.chat-box .participants .participant.pending .chat-participant-invite-join {
background: #dab539 url(<%= asset_path 'ellipsis.gif' %>) no-repeat center center;
}
.chat-box .participants .participant .chat-participant-participating {
float: right;
display: none;
margin-top: 14px;
}
.chat-box .participants .participant .chat-participant-participating .green-dot {
background: #4fc059;
width: 12px;
height: 12px;
border-radius: 6px;
}
.chat-box .participants .participant.active .chat-participant-participating {
display: block;
}
.chat-box .chat-header {
width: 276px;
padding: 16px 8px 16px 16px;
font-size: 16px;
text-align: left;
font-weight: bold;
background-color: #000000;
color: #f5f5f5;
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23);
}
.chat-box .chat-header .sound-toggle {
width: 24px;
height: 24px;
margin-right: 10px;
margin-top: -2px;
float: right;
background: url(<%= asset_path 'sound_sprite.png' %>) no-repeat;
}
.chat-box .chat-header .sound-toggle:hover {
background-position-x: -24px;
}
.chat-box .chat-header .sound-toggle.active {
background-position-y: -24px;
}
.chat-box .chat-input {
min-height: 80px;
width: 94%;
padding: 8px 3% 8px 3%;
font-size: 13px;
outline: none;
resize: none;
}
.chat-box .chat-messages {
width: 100%;
padding: 16px 0px 0px 0px;
overflow-y: auto;
flex-grow: 1;
}
.chat-box .chat-messages .chat-message {
width: 89%;
padding: 8px 8px 2px 8px;
color: #f5f5f5;
font-family: arial, sans-serif;
font-size: 13px;
line-height: 14px;
}
.chat-box .chat-messages .chat-message a:link {
color: #4fb5c0;
text-decoration: underline;
}
.chat-box .chat-messages .chat-message a:visited {
color: #aea9fd;
text-decoration: underline;
}
.chat-box .chat-messages .chat-message a:hover {
color: #dab539;
text-decoration: underline;
}
.chat-box .chat-messages .chat-message .chat-message-user {
width: 15%;
float: left;
overflow: hidden;
color: #BBB;
padding-top: 2px;
}
.chat-box .chat-messages .chat-message .chat-message-user img {
border: 2px solid #424242;
width: 32px;
height: 32px;
border-radius: 18px;
}
.chat-box .chat-messages .chat-message .chat-message-text {
width: 73%;
float: left;
margin-top: 12px;
padding: 2px 8px 0;
text-align: left;
word-wrap: break-word;
}
.chat-box .chat-messages .chat-message .chat-message-time {
float: right;
font-size: 10px;
color: #757575;
}

View file

@ -0,0 +1,375 @@
.collaborator-video {
z-index: 1;
position: absolute;
width: 150px;
height: 150px;
cursor: default;
color: #FFF;
.video-receive {
position: absolute;
width: 160px;
padding: 20px 20px 20px 170px;
background: #424242;
height: 110px;
border-top-left-radius: 75px;
border-bottom-left-radius: 75px;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
.video-statement {
margin-bottom: 10px;
}
.btn-group {
.btn-yes {
margin-right: 10px;
}
.btn-no {
background-color: #c04f4f;
&:hover {
background-color: #A54242;
}
}
}
}
.video-cutoff {
width: 150px;
height: 150px;
overflow: hidden;
border-radius: 75px;
z-index: 0;
position: relative;
-webkit-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
-moz-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
video {
height: 150px;
margin-left: -25px;
}
.collaborator-video-avatar {
position: absolute;
top: 0;
left: 0;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
-webkit-user-drag: none;
display: none;
}
}
.video-audio {
position: absolute;
width: 24px;
height: 24px;
top: 85%;
right: 0px;
cursor: pointer;
background: url(<%= asset_path 'audio_sprite.png' %>) no-repeat;
}
.video-audio:hover {
background-position-x: -24px;
}
.video-audio.active {
background-position-y: -24px;
}
.video-video {
position: absolute;
width: 24px;
height: 24px;
top: 85%;
left: 0px;
cursor: pointer;
background: url(<%= asset_path 'camera_sprite.png' %>) no-repeat;
}
.video-video:hover {
background-position-x: -24px;
}
.video-video.active {
background-position-y: -24px;
}
}
.collaborator-video.my-video {
left: 30px;
top: 72px;
}
.chat-box {
position: absolute;
right: 0;
z-index: 1;
height: 100%;
background: #424242;
box-shadow: -8px 0px 16px 2px rgba(0, 0, 0, 0.23);
.chat-panel {
width: 300px;
display: flex;
flex-direction: column;
height: 100%;
}
.chat-button {
position: absolute;
top: 50%;
left: -36px;
width: 36px;
height: 49px;
background: url(<%= asset_path 'junto.png' %>) no-repeat 2px 9px, url(<%= asset_path 'tray_tab.png' %>) no-repeat;
cursor: pointer;
&.active {
background: url(<%= asset_path 'junto_spinner_dark.gif' %>) no-repeat 2px 8px, url(<%= asset_path 'tray_tab.png' %>) no-repeat !important;
}
.chat-unread {
background: #DAB539;
position: absolute;
top: -3px;
left: -11px;
width: 20px;
height: 20px;
border-radius: 11px;
border: 2px solid #424242;
color: #424242;
text-align: center;
font-size: 12px;
font-weight: bold;
line-height: 20px;
}
}
.junto-header {
width: 276px;
padding: 16px 8px 16px 16px;
font-size: 16px;
text-align: left;
font-weight: bold;
background-color: #000000;
color: #f5f5f5;
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23);
.cursor-toggle {
width: 32px;
height: 32px;
margin-right: 8px;
margin-top: -8px;
float: right;
background: url(<%= asset_path 'cursor_sprite.png' %>) no-repeat;
}
.cursor-toggle:hover {
background-position-x: -32px;
}
.cursor-toggle.active {
background-position-y: -32px;
}
.video-toggle {
width: 32px;
height: 32px;
margin-right: 10px;
margin-top: -8px;
float: right;
background: url(<%= asset_path 'video_sprite.png' %>) no-repeat;
}
.video-toggle:hover {
background-position-x: -32px;
}
.video-toggle.active {
background-position-y: -32px;
}
}
.participants {
width: 100%;
min-height: 150px;
padding: 16px 0px 16px 0px;
text-align: left;
color: #f5f5f5;
overflow-y: auto;
.conversation-live {
padding: 5px 10px 5px 10px;
background: #c04f4f;
margin: 5px 10px;
border-radius: 2px;
}
.conversation-live .call-action {
float: right;
cursor: pointer;
color: #EBFF00;
}
.participant {
width: 89%;
padding: 8px 8px 2px 8px;
color: #f5f5f5;
font-family: arial, sans-serif;
font-size: 13px;
line-height: 14px;
.chat-participant-image {
width: 15%;
float: left;
overflow: hidden;
color: #BBB;
padding-top: 2px;
}
.chat-participant-image img {
width: 32px;
height: 32px;
border-radius: 18px;
}
.chat-participant-name {
width: 53%;
float: left;
font-size: 13px;
font-weight: bold;
margin-top: 12px;
padding: 2px 8px 0;
text-align: left;
}
.chat-participant-invite-call,
.chat-participant-invite-join
{
float: right;
background: #4FC059 url(<%= asset_path 'invitepeer16.png' %>) no-repeat center center;
}
.chat-participant-invite-call.pending,
.chat-participant-invite-join.pending {
background: #dab539 url(<%= asset_path 'ellipsis.gif' %>) no-repeat center center;
}
.chat-participant-participating {
float: right;
margin-top: 14px;
}
.chat-participant-participating .green-dot {
background: #4fc059;
width: 12px;
height: 12px;
border-radius: 6px;
}
}
}
.chat-header {
width: 276px;
padding: 16px 8px 16px 16px;
font-size: 16px;
text-align: left;
font-weight: bold;
background-color: #000000;
color: #f5f5f5;
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23);
.sound-toggle {
width: 24px;
height: 24px;
margin-right: 10px;
margin-top: -2px;
float: right;
background: url(<%= asset_path 'sound_sprite.png' %>) no-repeat;
}
.sound-toggle:hover {
background-position-x: -24px;
}
.sound-toggle.active {
background-position-y: -24px;
}
}
$chat_font_size: 16px;
.chat-input {
min-height: 80px;
width: 88%;
padding: 8px 9% 8px 3%;
font-size: $chat_font_size;
outline: none;
resize: none;
}
.chat-messages {
width: 100%;
padding: 16px 0px;
overflow-y: auto;
flex-grow: 1;
.chat-message {
width: 89%;
padding: 8px 8px 2px 8px;
color: #f5f5f5;
font-family: arial, sans-serif;
font-size: $chat_font_size;
line-height: $chat_font_size + 1px;
a:link {
color: #4fb5c0;
text-decoration: underline;
}
a:visited {
color: #aea9fd;
text-decoration: underline;
}
a:hover {
color: #dab539;
text-decoration: underline;
}
.chat-message-user {
width: 12%;
float: left;
overflow: hidden;
color: #BBB;
padding-top: 2px;
}
.chat-message-user img {
border: 2px solid #424242;
width: 28px;
height: 28px;
border-radius: 16px;
}
.chat-message-meta {
padding: 0 8px;
float: left;
}
.chat-message-username {
color: #4fc059;
}
.chat-message-text {
width: 80%;
float: left;
padding: 2px 8px 0;
text-align: left;
word-wrap: break-word;
}
.chat-message-time {
font-size: 12px;
color: #757575;
}
}
}
.new-message-area {
position: relative;
.emoji-mart {
position: absolute;
bottom: 98px;
}
.extra-message-options {
height: 20px;
position: absolute;
right: 2px;
bottom: 74px;
.emoji-picker-button {
font-size: 16px;
line-height: 20px;
cursor: pointer;
padding: 4px;
}
}
}
}

View file

@ -0,0 +1,288 @@
/* Map Cards */
.map {
display:inline-block;
width:220px;
height:340px;
font-size: 12px;
text-align: left;
overflow: visible;
background: #e8e8e8;
border-radius:2px;
margin:16px;
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
&.newMap {
float: left;
position: relative;
&:hover {
background: #dcdcdc;
.newMapImage {
background-position: 0 -72px;
}
}
a {
height: 340px;
display: block;
position: relative;
}
.newMapImage {
display: block;
width: 72px;
height: 72px;
background-image: url("<%= asset_data_uri('newmap_sprite.png') %>");
background-repeat: no-repeat;
background-position: 0 0;
position: absolute;
left: 50%;
margin-left: -36px;
top: 50%;
margin-top: -36px;
}
span {
font-family: 'din-regular', sans-serif;
font-size: 18px;
line-height: 22px;
text-align: center;
display: block;
padding-top: 220px;
}
}
.mapCard {
position:relative;
width:100%;
height:308px;
padding: 0 0 16px 0;
color: #424242;
&:hover {
.dropdownMenu .menuToggle .circle {
background-color: #FFF;
}
.dropdownMenu .menuToggle:hover .circle {
background-color: #DDD;
}
.mainContent {
filter: blur(2px);
}
.mapMetadata {
display: block;
}
}
.mapHasMapper, .mapHasConversation {
position: absolute;
top: 8px;
left: 8px;
min-width: 32px;
min-height: 32px;
&:hover {
background-color: #FFF;
border-radius: 2px;
.mapperList {
display: block;
}
}
.mapperList {
display: none;
padding: 8px;
list-style-type: none;
li {
&.live {
height: 32px;
padding-left: 32px;
font-size: 16px;
}
img {
width: 24px;
height: 24px;
border-radius: 12px;
display: inline-block;
vertical-align: middle;
}
span {
padding-left: 10px;
font-size: 14px;
}
}
}
}
.mapHasMapper {
background: url('<%= asset_path('junto.png') %>') no-repeat 4px 0;
}
.mapHasConversation {
background: url('<%= asset_path('junto.gif') %>') no-repeat 4px 0;
}
.dropdownMenu {
position: absolute;
top: 8px;
right: 8px;
cursor: pointer;
.menuToggle {
width: 30px;
height: 10px;
.circle {
display: inline-block;
background-color: #454545;
width: 6px;
height: 6px;
border-radius: 3px;
margin: 2px;
}
&:hover .circle {
background-color: #222;
}
}
.menuItems {
position: absolute;
top: 18px;
right: 0px;
background: #FFF;
border-radius: 2px;
list-style-type: none;
color: #454545;
li {
white-space: nowrap;
padding: 6px;
&:hover {
background-color: #DDD;
}
}
}
}
.mapScreenshot {
width: 100%;
height: 220px;
}
.mapScreenshot img {
width: 100%;
}
.title {
word-wrap: break-word;
font-size:18px;
line-height:22px;
height: 71px;
display:table;
padding: 0 16px;
font-family: 'din-regular', sans-serif;
margin: 0 auto;
.innerTitle {
display: table-cell;
vertical-align: middle;
text-align: center;
}
}
.creatorAndPerm {
padding: 8px;
}
.creatorImage {
display: inline-block;
border-radius: 16px;
vertical-align: middle;
width: 32px;
height: 32px;
}
span.creatorName {
margin-left: 8px;
max-width: 162px;
display: inline-block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
vertical-align: middle;
}
.creatorAndPerm.cardHasViewOnly span.creatorName {
max-width: 95px;
}
.cardViewOnly {
float: right;
line-height: 32px;
padding-right: 10px;
color: #454545;
}
.scroll {
display:block;
font-family: helvetica, sans-serif;
font-size: 12px;
word-wrap: break-word;
text-align: center;
margin-top: 16px;
}
.mapMetadata {
display: none;
position: absolute;
top: 0;
left: 0;
padding: 40px 20px 0;
height: 300px;
font-family: 'din-regular', sans-serif;
font-size: 12px;
color: #FFF;
background: -moz-linear-gradient(top, rgba(0,0,0,0.65) 0%, rgba(0,0,0,0.43) 81%, rgba(0,0,0,0) 100%);
background: -webkit-linear-gradient(top, rgba(0,0,0,0.65) 0%,rgba(0,0,0,0.43) 81%,rgba(0,0,0,0) 100%);
background: linear-gradient(to bottom, rgba(0,0,0,0.65) 0%,rgba(0,0,0,0.43) 81%,rgba(0,0,0,0) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a6000000', endColorstr='#00000000',GradientType=0 );
}
.metadataSection {
padding: 16px 0;
width: 90px;
float: left;
font-family: 'din-medium', sans-serif;
text-align: center;
div {
background: url('<%= asset_path('metadata.png') %>') no-repeat;
width: 32px;
height: 32px;
margin: 0 auto;
}
.numTopicsIcon {
background-position: 0 -32px;
}
.numStarsIcon {
background-position: 0 0;
}
.numSynapsesIcon {
background-position: -32px -32px;
}
.numContributorsIcon {
background-position: -32px 0;
}
}
}
}

View file

@ -1,15 +1,50 @@
#mobile_header { @media only screen and (max-width : 752px) and (min-width : 504px) {
display: none; .sidebarSearch .tt-hint, .sidebarSearch .sidebarSearchField {
width: 160px !important;
}
} }
/* Smartphones (portrait and landscape) ----------- */ /* when this switches to two lines */
@media only screen and (max-device-width : 480px) { @media only screen and (max-width : 728px) {
.upperLeftUI, .upperRightUI, .openCheatsheet, .mapInfoIcon, .uv-icon, .chat-box, #exploreMapsHeader { .controller-notifications .notificationsPage .notification .notification-read-unread a {
margin-top: -20px !important;
}
}
@media only screen and (max-width : 390px) {
.map .mapCard .mobileMetadata {
width: 190px;
}
}
@media only screen and (min-width : 390px) {
.map .mapCard .mobileMetadata {
width: 390px;
}
}
/* 800 is the max-width for centerContent */
@media only screen and (max-width : 800px) {
.centerContent.withPadding {
margin-top: 0;
margin-bottom: 0;
}
}
/* Smartphones (portrait and landscape) ----------- the minimum space that two map cards can fit side by side */
@media only screen and (max-width : 504px) {
.upperLeftUI, .upperRightUI, .openCheatsheet, .mapInfoIcon, .feedback-icon, .chat-box, #navBar {
display: none !important; display: none !important;
} }
#mobile_header { .notificationsPage .page-header {
display: block; display: none;
}
.controller-notifications .notificationsPage .notification .notification-read-unread {
display: block !important;
}
.controller-notifications .notificationsPage .notification .notification-date {
display: none;
} }
.homeWrapper { .homeWrapper {
@ -29,7 +64,7 @@
height: auto; height: auto;
} }
.homeVideo { .homeVideo {
width: 100%; width: 100% !important;
height: auto; height: auto;
} }
.fullWidthWrapper.withPartners { .fullWidthWrapper.withPartners {
@ -40,7 +75,7 @@
} }
#yield { #yield {
height: 100%; padding-top: 50px;
} }
.new_session, .new_user, .edit_user, .login, .forgotPassword { .new_session, .new_user, .edit_user, .login, .forgotPassword {
@ -49,7 +84,7 @@
left: auto; left: auto;
width: 78%; width: 78%;
padding: 16px 10%; padding: 16px 10%;
margin: 50px auto 0 auto; margin: 0 auto;
} }
.centerGreyForm input[type="text"], .centerGreyForm input[type="email"], .centerGreyForm input[type="password"] { .centerGreyForm input[type="text"], .centerGreyForm input[type="email"], .centerGreyForm input[type="password"] {
@ -65,15 +100,28 @@
max-width: 360px; max-width: 360px;
} }
#wrapper .requestInvite { .requestInviteHeader {
display: none;
}
.requestInvite {
width: 100%; width: 100%;
padding: 0; height: calc(100% - 50px);
z-index: 1;
position: relative;
left: 0;
margin-left: 0px;
margin-top: 50px;
} }
#exploreMaps > div { #exploreMaps > div {
margin-top: 70px; margin-top: 70px;
} }
.mapper {
width: 100%;
margin: 0 0 30px 0;
}
.map.newMap { .map.newMap {
a { a {
height: auto; height: auto;
@ -100,29 +148,67 @@
.map.newMap:hover .newMapImage { .map.newMap:hover .newMapImage {
background-position: 0 -40px; background-position: 0 -40px;
} }
}
/* Smartphones (portrait) ----------- */
@media only screen and (max-width : 400px) {
.map { .map {
width: 100%; width: 100%;
margin: 0 0 30px 0; margin: 0 0 30px 0;
height: auto; height: auto;
}
.mapCard { .mapCard {
height: auto; height: auto;
padding: 0;
&:hover {
.mainContent {
filter: none;
}
}
.mobileHasMapper, .mobileHasConversation {
.mapperList {
padding: 8px 16px;
list-style-type: none;
li {
&.live {
height: 32px;
padding-left: 32px;
font-size: 16px;
} }
.mapCard .title { img {
width: 24px;
height: 24px;
border-radius: 12px;
display: inline-block;
vertical-align: middle;
}
span {
padding-left: 10px;
font-size: 14px;
}
}
}
}
.mobileHasMapper {
background: url('<%= asset_path('junto.png') %>') no-repeat 12px 0;
}
.mobileHasConversation {
background: url('<%= asset_path('junto.gif') %>') no-repeat 12px 0;
}
.mobileMetadata {
margin: 0 auto;
}
.title {
text-align: left; text-align: left;
display: block;
height: auto;
padding: 16px;
}
.desc {
padding: 0 16px;
}
} }
.mapCard .mapScreenshot {
display: none;
} }
} }
#mobile_header { #mobile_header {
@ -131,6 +217,7 @@
width: 100%; width: 100%;
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16); box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
position: fixed; position: fixed;
z-index: 1;
} }
#menu_icon { #menu_icon {
@ -153,8 +240,16 @@
line-height: 50px; line-height: 50px;
} }
#mobile_header #menu_icon .unread-notifications-dot {
top: 5px;
left: 29px;
width: 12px;
height: 12px;
border: 3px solid #eee;
border-radius: 9px;
}
#mobile_menu { #mobile_menu {
display: none;
background: #EEE; background: #EEE;
position: fixed; position: fixed;
top: 50px; top: 50px;
@ -162,11 +257,30 @@
padding: 10px; padding: 10px;
width: 200px; width: 200px;
box-shadow: 3px 3px 3px rgba(0,0,0,0.23), 3px 3px 3px rgba(0,0,0,0.16); box-shadow: 3px 3px 3px rgba(0,0,0,0.23), 3px 3px 3px rgba(0,0,0,0.16);
z-index: 2;
li {
padding: 7px 10px;
list-style: none;
font-family: 'din-regular', arial, sans-serif;
.sprite {
margin-right: 6px;
margin-top: -2px;
display: inline-block;
vertical-align: middle;
} }
#mobile_menu li { &.notifications {
padding: 10px; position: relative;
list-style: none;
.unread-notifications-dot {
top: 50%;
left: 0px;
margin-top: -4px;
}
}
}
} }
li.mobileMenuUser { li.mobileMenuUser {

View file

@ -0,0 +1,237 @@
$notifications-border-color: #DDDDDD;
$notifications-hover-color: #F6F6F6;
$unread_notifications_dot_size: 8px;
.unread-notifications-dot {
width: $unread_notifications_dot_size;
height: $unread_notifications_dot_size;
background-color: #e22;
border-radius: $unread_notifications_dot_size / 2;
position: absolute;
top: 0;
right: 0;
}
.upperRightUI {
.notificationsIcon {
position: relative;
}
.notificationsBox {
position: absolute;
background: #FFFFFF;
border-radius: 2px;
width: 350px;
right: 0;
top: 50px;
box-shadow: 0 3px 6px rgba(0,0,0,0.16);
border: 1px solid $notifications-border-color;
.notificationsBoxTriangle {
min-width: 0 !important;
display: block;
position: absolute;
right: 48px;
width: 20px !important;
height: 20px !important;
margin-left: -10px;
top: -11px;
border-left: 1px solid $notifications-border-color;
border-top: 1px solid $notifications-border-color;
border-bottom: 0 !important;
border-right: 0 !important;
background-color: #fff;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
}
ul.notifications {
max-height: 500px;
overflow-y: auto;
.notification {
font-size: 13px;
.notification-body {
border-bottom: 1px solid $notifications-border-color;
}
}
.notificationsEmpty {
font-family: din-regular, helvetica, sans-serif;
margin: 50px 10px;
text-align: center;
}
}
.notificationsBoxSeeAll {
display: block;
width: 100%;
text-align: center;
padding: 6px 0;
font-family: din-regular, helvetica, sans-serif;
border-top: 1px solid rgba(0, 0, 0, 0.1);
&:hover {
color: #333;
background: $notifications-hover-color;
}
}
}
}
.controller-notifications {
.notificationPage,
.notificationsPage {
font-family: 'din-regular', Sans-Serif;
& a:hover {
text-decoration: none;
}
& > .notification-title {
border-bottom: 1px solid #eee;
padding-bottom: 0.25em;
margin-bottom: 0.5em;
}
.back {
margin-top: 1em;
}
}
.notificationsPage {
header {
margin-bottom: 0;
}
.emptyInbox {
padding-top: 15px;
}
}
.notificationPage {
.thirty-two-avatar {
display: inline-block;
width: 32px;
height: 32px;
border-radius: 16px;
vertical-align: middle;
}
.button {
line-height: 32px;
img {
margin-top: 8px;
}
&.decline {
background: #DB5D5D;
&:hover {
background: #DC4B4B;
}
}
}
.notification-body {
p, div {
margin: 1em auto;
line-height: 20px;
}
}
}
}
ul.notifications {
list-style: none;
li:nth-last-child(2) {
.notification-body {
border-bottom: none !important;
}
}
}
.notification {
padding: 10px 10px 0 10px;
position: relative;
font-family: 'din-regular', Sans-Serif;
&.unread {
background: #EEE;
}
&:hover {
background: $notifications-hover-color;
.notification-read-unread {
display:block;
}
.notification-date {
display: none;
}
}
& > a {
float: left;
width: 85%;
box-sizing: border-box;
padding-right: 10px;
}
.notification-actor {
float: left;
img {
width: 32px;
height: 32px;
border-radius: 16px;
}
}
.notification-body {
margin-left: 50px;
line-height: 20px;
padding-bottom: 10px;
.in-bold {
font-family: 'din-medium', Sans-Serif;
}
.action {
background: #4fb5c0;
color: #FFF;
padding: 2px 6px;
border-radius: 3px;
display: inline-block;
margin: 5px 0;
}
}
.notification-date {
position: absolute;
top: 50%;
right: 10px;
color: #607d8b;
margin-top: -6px;
}
.notification-read-unread {
display: none;
float: left;
width: 15%;
a, div {
position: absolute;
top: 50%;
margin-top: -10px;
text-align: center;
cursor: pointer;
}
}
}

View file

@ -0,0 +1,87 @@
.viewOnly {
float: left;
margin-left: 16px;
height: 32px;
border: 1px solid #BDBDBD;
border-radius: 2px;
background-color: #424242;
color: #FFF;
font-size: 14px;
line-height: 32px;
&.isViewOnly {
display: block;
}
.eyeball {
background: url('<%= asset_path('view-only.png') %>') no-repeat 4px 0;
padding-left: 40px;
border-right: #747474;
padding-right: 10px;
display: inline-block;
}
.requestNotice {
display: inline-block;
padding: 0 8px;
}
.requestAccess {
background-color: #a354cd;
&:hover {
background-color: #9150bc;
}
cursor: pointer;
}
.requestPending {
background-color: #4fc059;
}
.requestNotAccepted {
background-color: #c04f4f;
}
}
.request_access {
position: absolute;
width: 90%;
margin: 0 5%;
.monkey {
width: 250px;
height: 250px;
border: 6px solid #424242;
border-radius: 125px;
background: url(https://s3.amazonaws.com/metamaps-assets/site/monkeyselfie.jpg) no-repeat;
background-position: 50% 20%;
background-size: 100%;
margin: 80px auto 20px auto;
}
.explainer_text {
padding: 0 20% 0 20%;
font-size: 24px;
line-height: 30px;
margin-bottom: 20px;
text-align: center;
}
.make_request {
background-color: #a354cd;
display: block;
width: 220px;
height: 14px;
padding: 16px 0;
margin-bottom: 16px;
text-align: center;
border-radius: 2px;
font-size: 14px;
box-shadow: 0px 1px 1.5px rgba(0,0,0,0.12), 0 1px 1px rgba(0,0,0,0.24);
margin: 0 auto 20px auto;
text-decoration: none;
color: #FFFFFF !important;
cursor: pointer;
}
}

View file

@ -93,7 +93,7 @@
.sidebarSearchField { .sidebarSearchField {
float: left; float: left;
width: 380px; width: 379px;
padding: 7px 10px 3px 10px; padding: 7px 10px 3px 10px;
height: 20px; height: 20px;
border-top: 1px solid #BDBDBD; border-top: 1px solid #BDBDBD;

View file

@ -0,0 +1,6 @@
# frozen_string_literal: true
module ApplicationCable
class Channel < ActionCable::Channel::Base
end
end

View file

@ -0,0 +1,23 @@
# frozen_string_literal: true
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
logger.add_tags 'ActionCable', current_user.name
end
protected
def find_verified_user
verified_user = User.find_by(id: cookies.signed['user.id'])
if verified_user && cookies.signed['user.expires_at'] > Time.now.getlocal
verified_user
else
reject_unauthorized_connection
end
end
end
end

View file

@ -0,0 +1,18 @@
# frozen_string_literal: true
class MapChannel < ApplicationCable::Channel
# Called when the consumer has successfully
# become a subscriber of this channel.
def subscribed
map = Map.find(params[:id])
return unless Pundit.policy(current_user, map).show?
stream_from "map_#{params[:id]}"
Events::UserPresentOnMap.publish!(map, current_user)
end
def unsubscribed
map = Map.find(params[:id])
return unless Pundit.policy(current_user, map).show?
Events::UserNotPresentOnMap.publish!(map, current_user)
end
end

View file

@ -0,0 +1,90 @@
# frozen_string_literal: true
class AccessController < ApplicationController
before_action :require_user, only: %i[access access_request
approve_access approve_access_post
deny_access deny_access_post request_access]
before_action :set_map, only: %i[access access_request
approve_access approve_access_post
deny_access deny_access_post request_access]
after_action :verify_authorized
# GET maps/:id/request_access
def request_access
@map = nil
respond_to do |format|
format.html do
render 'maps/request_access'
end
end
end
# POST maps/:id/access_request
def access_request
AccessRequest.create(user: current_user, map: @map)
respond_to do |format|
format.json { head :ok }
end
end
# POST maps/:id/access
def access
user_ids = params[:access].to_a.map(&:to_i) || []
@map.add_new_collaborators(user_ids)
@map.remove_old_collaborators(user_ids)
respond_to do |format|
format.json { head :ok }
end
end
# GET maps/:id/approve_access/:request_id
def approve_access
request = AccessRequest.find(params[:request_id])
request.approve # also marks mailboxer notification as read
respond_to do |format|
format.html { redirect_to map_path(@map), notice: 'Request was approved' }
end
end
# GET maps/:id/deny_access/:request_id
def deny_access
request = AccessRequest.find(params[:request_id])
request.deny # also marks mailboxer notification as read
respond_to do |format|
format.html { redirect_to map_path(@map), notice: 'Request was turned down' }
end
end
# POST maps/:id/approve_access/:request_id
def approve_access_post
request = AccessRequest.find(params[:request_id])
request.approve
respond_to do |format|
format.js
format.json do
head :ok
end
end
end
# POST maps/:id/deny_access/:request_id
def deny_access_post
request = AccessRequest.find(params[:request_id])
request.deny
respond_to do |format|
format.js
format.json do
head :ok
end
end
end
private
def set_map
@map = Map.find(params[:id])
authorize @map
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V1 module V1
class DeprecatedController < ApplicationController class DeprecatedController < ApplicationController

View file

@ -1,7 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class MappingsController < RestfulController class MappingsController < WithUpdatesController
def searchable_columns def searchable_columns
[] []
end end

View file

@ -1,9 +1,15 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class MapsController < RestfulController class MapsController < WithUpdatesController
def searchable_columns def searchable_columns
[:name, :desc] %i[name desc]
end
def apply_filters(collection)
collection = collection.where(user_id: params[:user_id]) if params[:user_id]
collection
end end
end end
end end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class MetacodesController < RestfulController class MetacodesController < RestfulController

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class RestfulController < ActionController::Base class RestfulController < ActionController::Base
@ -7,7 +8,7 @@ module Api
snorlax_used_rest! snorlax_used_rest!
before_action :load_resource, only: [:show, :update, :destroy] before_action :load_resource, only: %i[show update destroy]
after_action :verify_authorized after_action :verify_authorized
def index def index
@ -45,7 +46,7 @@ module Api
end end
def current_user def current_user
super || token_user || doorkeeper_user || nil token_user || doorkeeper_user
end end
def load_resource def load_resource
@ -86,12 +87,12 @@ module Api
def token_user def token_user
token = params[:access_token] token = params[:access_token]
access_token = Token.find_by_token(token) access_token = Token.find_by(token: token)
@token_user ||= access_token.user if access_token @token_user ||= access_token.user if access_token
end end
def doorkeeper_user def doorkeeper_user
return unless doorkeeper_token.present? return if doorkeeper_token.blank?
doorkeeper_render_error unless valid_doorkeeper_token? doorkeeper_render_error unless valid_doorkeeper_token?
@doorkeeper_user ||= User.find(doorkeeper_token.resource_owner_id) @doorkeeper_user ||= User.find(doorkeeper_token.resource_owner_id)
end end
@ -141,6 +142,7 @@ module Api
collection = accessible_records collection = accessible_records
collection = yield collection if block_given? collection = yield collection if block_given?
collection = search_by_q(collection) if params[:q] collection = search_by_q(collection) if params[:q]
collection = apply_filters(collection)
collection = order_by_sort(collection) if params[:sort] collection = order_by_sort(collection) if params[:sort]
collection = collection.page(params[:page]).per(params[:per]) collection = collection.page(params[:page]).per(params[:per])
self.collection = collection self.collection = collection
@ -148,10 +150,21 @@ module Api
# override this method to explicitly set searchable columns # override this method to explicitly set searchable columns
def searchable_columns def searchable_columns
return @searchable_columns unless @searchable_columns.nil?
columns = resource_class.columns.select do |column| columns = resource_class.columns.select do |column|
column.type == :text || column.type == :string column.type == :text || column.type == :string
end end
columns.map(&:name) @searchable_columns = columns.map(&:name)
end
# e.g. ?q=test&searchfields=name,desc
def searchfields
return searchable_columns if params[:searchfields].blank?
searchfields = params[:searchfields].split(',')
searchfields.select! { |f| searchable_columns.include?(f.to_sym) }
searchfields.empty? ? searchable_columns : searchfields
end end
# thanks to http://stackoverflow.com/questions/4430578 # thanks to http://stackoverflow.com/questions/4430578
@ -160,13 +173,18 @@ module Api
safe_query = "%#{params[:q].gsub(/[%_]/, '\\\\\0')}%" safe_query = "%#{params[:q].gsub(/[%_]/, '\\\\\0')}%"
search_column = ->(column) { table[column].matches(safe_query) } search_column = ->(column) { table[column].matches(safe_query) }
condition = searchable_columns.reduce(nil) do |prev, column| condition = searchfields.reduce(nil) do |prev, column|
next search_column.call(column) if prev.nil? next search_column.call(column) if prev.nil?
search_column.call(column).or(prev) search_column.call(column).or(prev)
end end
collection.where(condition) collection.where(condition)
end end
def apply_filters(collection)
# override this function for specific filters
collection
end
def order_by_sort(collection) def order_by_sort(collection)
builder = collection builder = collection
sorts = params[:sort].split(',') sorts = params[:sort].split(',')

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class SessionsController < ApplicationController class SessionsController < ApplicationController

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class StarsController < RestfulController class StarsController < RestfulController

View file

@ -1,7 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class SynapsesController < RestfulController class SynapsesController < WithUpdatesController
def searchable_columns def searchable_columns
[:desc] [:desc]
end end

View file

@ -1,7 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class TokensController < RestfulController class TokensController < RestfulController
protect_from_forgery
def searchable_columns def searchable_columns
[:description] [:description]
end end
@ -19,10 +22,10 @@ module Api
respond_with_resource respond_with_resource
end end
def my_tokens private
authorize resource_class
instantiate_collection def current_user
respond_with_collection token_user || doorkeeper_user || method(:current_user).super_method.super_method.call
end end
end end
end end

View file

@ -1,9 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class TopicsController < RestfulController class TopicsController < WithUpdatesController
def searchable_columns def searchable_columns
[:name, :desc, :link] %i[name desc link]
end end
end end
end end

View file

@ -1,8 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
module Api module Api
module V2 module V2
class UsersController < RestfulController class UsersController < RestfulController
def current def current
raise Pundit::NotAuthorizedError if current_user.nil?
@user = current_user @user = current_user
authorize @user authorize @user
show # delegate to the normal show function show # delegate to the normal show function
@ -17,7 +19,7 @@ module Api
# only ask serializer to return is_admin field if we're on the # only ask serializer to return is_admin field if we're on the
# current_user action # current_user action
def default_scope def default_scope
super.merge(show_is_admin: action_name == 'current') super.merge(show_full_user: action_name == 'current')
end end
end end
end end

View file

@ -0,0 +1,28 @@
# frozen_string_literal: true
module Api
module V2
class WithUpdatesController < RestfulController
def create
instantiate_resource
resource.user = current_user if current_user.present?
resource.updated_by = current_user if current_user.present?
authorize resource
create_action
respond_with_resource
end
def update
resource.updated_by = current_user if current_user.present?
update_action
respond_with_resource
end
def destroy
resource.updated_by = current_user if current_user.present?
destroy_action
head :no_content
end
end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
include ApplicationHelper include ApplicationHelper
include Pundit include Pundit
@ -21,23 +22,14 @@ class ApplicationController < ActionController::Base
helper_method :authenticated? helper_method :authenticated?
helper_method :admin? helper_method :admin?
def after_sign_in_path_for(resource)
sign_in_url = url_for(action: 'new', controller: 'sessions', only_path: false)
if request.referer == sign_in_url
super
elsif params[:uv_login] == '1'
'http://support.metamaps.cc/login_success?sso=' + current_sso_token
else
stored_location_for(resource) || request.referer || root_path
end
end
def handle_unauthorized def handle_unauthorized
if authenticated? if authenticated? && (params[:controller] == 'maps') && (params[:action] == 'show')
redirect_to request_access_map_path(params[:id])
elsif authenticated?
redirect_to root_path, notice: "You don't have permission to see that page." redirect_to root_path, notice: "You don't have permission to see that page."
else else
redirect_to new_user_session_path, notice: 'Try signing in to do that.' store_location_for(resource, request.fullpath)
redirect_to sign_in_path, notice: 'Try signing in to do that.'
end end
end end
@ -50,13 +42,13 @@ class ApplicationController < ActionController::Base
def require_no_user def require_no_user
return true unless authenticated? return true unless authenticated?
redirect_to edit_user_path(user), notice: 'You must be logged out.' redirect_to edit_user_path(user), notice: 'You must be logged out.'
return false false
end end
def require_user def require_user
return true if authenticated? return true if authenticated?
redirect_to new_user_session_path, notice: 'You must be logged in.' redirect_to sign_in_path, notice: 'You must be logged in.'
return false false
end end
def require_admin def require_admin

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class ExploreController < ApplicationController class ExploreController < ApplicationController
before_action :require_authentication, only: [:mine, :shared, :starred] before_action :require_authentication, only: %i[mine shared starred]
before_action :authorize_explore before_action :authorize_explore
after_action :verify_authorized after_action :verify_authorized
after_action :verify_policy_scoped after_action :verify_policy_scoped

View file

@ -1,17 +1,18 @@
# frozen_string_literal: true
# bad code that should be checked over before entering one of the # bad code that should be checked over before entering one of the
# nice files from the right side of this repo # nice files from the right side of this repo
class HacksController < ApplicationController class HacksController < ApplicationController
include ActionView::Helpers::TextHelper # string truncate method include ActionView::Helpers::TextHelper # string truncate method
# rate limited by rack-attack - currently 5r/s # rate limited by rack-attack - currently 5r/s
# TODO: what else can we do to make get_with_redirects safer?
def load_url_title def load_url_title
authorize :Hack authorize :Hack
url = params[:url] url = params[:url]
response, url = get_with_redirects(url) response, url = get_with_redirects(url)
title = get_encoded_title(response) title = get_encoded_title(response)
render json: { success: true, title: title, url: url } render json: { success: true, title: title, url: url }
rescue StandardError => e rescue StandardError
render json: { success: false } render json: { success: false }
end end
@ -28,7 +29,13 @@ class HacksController < ApplicationController
end end
def get_encoded_title(http_response) def get_encoded_title(http_response)
title = http_response.body.sub(/.*<title>(.*)<\/title>.*/m, '\1') # ensure there's actually an html title tag
title = http_response.body.sub(%r{.*(<title>.*</title>).*}m, '\1')
return '' unless title.starts_with?('<title>')
return '' unless title.ends_with?('</title>')
title = title.sub('<title>', '').sub(%r{</title>$}, '')
# encode and trim the title to 140 usable characters
charset = http_response['content-type'].sub(/.*charset=(.*);?.*/, '\1') charset = http_response['content-type'].sub(/.*charset=(.*);?.*/, '\1')
charset = nil if charset == 'text/html' charset = nil if charset == 'text/html'
title = title.force_encoding(charset) if charset title = title.force_encoding(charset) if charset

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
class MainController < ApplicationController class MainController < ApplicationController
before_action :authorize_main before_action :authorize_main
after_action :verify_authorized after_action :verify_authorized

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class MappingsController < ApplicationController class MappingsController < ApplicationController
before_action :require_user, only: [:create, :update, :destroy] before_action :require_user, only: %i[create update destroy]
after_action :verify_authorized, except: :index after_action :verify_authorized, except: :index
after_action :verify_policy_scoped, only: :index after_action :verify_policy_scoped, only: :index
@ -19,10 +20,10 @@ class MappingsController < ApplicationController
@mapping = Mapping.new(mapping_params) @mapping = Mapping.new(mapping_params)
authorize @mapping authorize @mapping
@mapping.user = current_user @mapping.user = current_user
@mapping.updated_by = current_user
if @mapping.save if @mapping.save
render json: @mapping, status: :created render json: @mapping, status: :created
Events::NewMapping.publish!(@mapping, current_user)
else else
render json: @mapping.errors, status: :unprocessable_entity render json: @mapping.errors, status: :unprocessable_entity
end end
@ -32,8 +33,11 @@ class MappingsController < ApplicationController
def update def update
@mapping = Mapping.find(params[:id]) @mapping = Mapping.find(params[:id])
authorize @mapping authorize @mapping
@mapping.updated_by = current_user
@mapping.map.updated_by = current_user
@mapping.assign_attributes(mapping_params)
if @mapping.update_attributes(mapping_params) if @mapping.save
head :no_content head :no_content
else else
render json: @mapping.errors, status: :unprocessable_entity render json: @mapping.errors, status: :unprocessable_entity
@ -44,14 +48,8 @@ class MappingsController < ApplicationController
def destroy def destroy
@mapping = Mapping.find(params[:id]) @mapping = Mapping.find(params[:id])
authorize @mapping authorize @mapping
@mapping.updated_by = current_user
mappable = @mapping.mappable @mapping.map.updated_by = current_user
if mappable.defer_to_map
mappable.permission = mappable.defer_to_map.permission
mappable.defer_to_map_id = nil
mappable.save
end
@mapping.destroy @mapping.destroy
head :no_content head :no_content

View file

@ -1,14 +1,17 @@
# frozen_string_literal: true # frozen_string_literal: true
class MapsController < ApplicationController class MapsController < ApplicationController
before_action :require_user, only: [:create, :update, :destroy, :access, :events] before_action :require_user, only: %i[create update destroy events follow unfollow]
before_action :set_map, only: [:show, :update, :destroy, :access, :contains, before_action :set_map, only: %i[show conversation update destroy
:events, :export] contains events export
follow unfollow unfollow_from_email]
after_action :verify_authorized after_action :verify_authorized
# GET maps/:id # GET maps/:id
def show def show
respond_to do |format| respond_to do |format|
format.html do format.html do
UserMap.where(map: @map, user: current_user).map(&:mark_invite_notifications_as_read)
@allmappers = @map.contributors @allmappers = @map.contributors
@allcollaborators = @map.editors @allcollaborators = @map.editors
@alltopics = policy_scope(@map.topics) @alltopics = policy_scope(@map.topics)
@ -16,9 +19,28 @@ class MapsController < ApplicationController
@allmappings = policy_scope(@map.mappings) @allmappings = policy_scope(@map.mappings)
@allmessages = @map.messages.sort_by(&:created_at) @allmessages = @map.messages.sort_by(&:created_at)
@allstars = @map.stars @allstars = @map.stars
@allrequests = @map.access_requests
end end
format.json { render json: @map } format.json { render json: @map }
format.csv { redirect_to action: :export, format: :csv } format.csv { redirect_to action: :export, format: :csv }
format.ttl { redirect_to action: :export, format: :ttl }
end
end
# GET maps/:id/conversation
def conversation
respond_to do |format|
format.html do
UserMap.where(map: @map, user: current_user).map(&:mark_invite_notifications_as_read)
@allmappers = @map.contributors
@allcollaborators = @map.editors
@alltopics = policy_scope(@map.topics)
@allsynapses = policy_scope(@map.synapses)
@allmappings = policy_scope(@map.mappings)
@allmessages = @map.messages.sort_by(&:created_at)
@allstars = @map.stars
@allrequests = @map.access_requests
end
end end
end end
@ -40,6 +62,7 @@ class MapsController < ApplicationController
def create def create
@map = Map.new(create_map_params) @map = Map.new(create_map_params)
@map.user = current_user @map.user = current_user
@map.updated_by = current_user
@map.arranged = false @map.arranged = false
authorize @map authorize @map
@ -60,8 +83,11 @@ class MapsController < ApplicationController
# PUT maps/:id # PUT maps/:id
def update def update
@map.updated_by = current_user
@map.assign_attributes(update_map_params)
respond_to do |format| respond_to do |format|
if @map.update_attributes(update_map_params) if @map.save
format.json { head :no_content } format.json { head :no_content }
else else
format.json { render json: @map.errors, status: :unprocessable_entity } format.json { render json: @map.errors, status: :unprocessable_entity }
@ -71,7 +97,8 @@ class MapsController < ApplicationController
# DELETE maps/:id # DELETE maps/:id
def destroy def destroy
@map.delete @map.updated_by = current_user
@map.destroy
respond_to do |format| respond_to do |format|
format.json do format.json do
@ -80,37 +107,21 @@ class MapsController < ApplicationController
end end
end end
# POST maps/:id/access
def access
user_ids = params[:access] || []
@map.add_new_collaborators(user_ids).each do |user_id|
# add_new_collaborators returns array of added users,
# who we then send an email to
MapMailer.invite_to_edit_email(@map, current_user, User.find(user_id)).deliver_later
end
@map.remove_old_collaborators(user_ids)
respond_to do |format|
format.json do
render json: { message: 'Successfully altered edit permissions' }
end
end
end
# GET maps/:id/contains # GET maps/:id/contains
def contains def contains
respond_to do |format| respond_to do |format|
format.json { render json: @map.contains(current_user) } format.json { render json: @map.contains(current_user).as_json(user: current_user) }
end end
end end
# GET maps/:id/export # GET maps/:id/export
def export def export
exporter = MapExportService.new(current_user, @map) exporter = MapExportService.new(current_user, @map, base_url: request.base_url)
respond_to do |format| respond_to do |format|
format.json { render json: exporter.json } format.json { render json: exporter.json }
format.csv { send_data exporter.csv } format.csv { send_data exporter.csv }
format.ttl { render text: exporter.rdf }
end end
end end
@ -120,9 +131,6 @@ class MapsController < ApplicationController
if params[:event] == 'conversation' if params[:event] == 'conversation'
Events::ConversationStartedOnMap.publish!(@map, current_user) Events::ConversationStartedOnMap.publish!(@map, current_user)
valid_event = true valid_event = true
elsif params[:event] == 'user_presence'
Events::UserPresentOnMap.publish!(@map, current_user)
valid_event = true
end end
respond_to do |format| respond_to do |format|
@ -133,6 +141,43 @@ class MapsController < ApplicationController
end end
end end
# POST maps/:id/follow
def follow
follow = FollowService.follow(@map, current_user, 'followed')
respond_to do |format|
format.json do
if follow
head :ok
else
head :bad_request
end
end
end
end
# POST maps/:id/unfollow
def unfollow
FollowService.unfollow(@map, current_user)
respond_to do |format|
format.json do
head :ok
end
end
end
# GET maps/:id/unfollow_from_email
def unfollow_from_email
FollowService.unfollow(@map, current_user)
respond_to do |format|
format.html do
redirect_to map_path(@map), notice: 'You are no longer following this map'
end
end
end
private private
def set_map def set_map
@ -141,7 +186,7 @@ class MapsController < ApplicationController
end end
def create_map_params def create_map_params
params.permit(:name, :desc, :permission) params.permit(:name, :desc, :permission, :source_id)
end end
def update_map_params def update_map_params

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
class MessagesController < ApplicationController class MessagesController < ApplicationController
before_action :require_user, except: [:show] before_action :require_user, except: [:show]
after_action :verify_authorized after_action :verify_authorized

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
class MetacodeSetsController < ApplicationController class MetacodeSetsController < ApplicationController
before_action :require_admin before_action :require_admin
@ -55,8 +56,13 @@ class MetacodeSetsController < ApplicationController
@metacodes.each do |m| @metacodes.each do |m|
InMetacodeSet.create(metacode_id: m, metacode_set_id: @metacode_set.id) InMetacodeSet.create(metacode_id: m, metacode_set_id: @metacode_set.id)
end end
format.html { redirect_to metacode_sets_url, notice: 'Metacode set was successfully created.' } format.html do
format.json { render json: @metacode_set, status: :created, location: metacode_sets_url } redirect_to metacode_sets_url,
notice: 'Metacode set was successfully created.'
end
format.json do
render json: @metacode_set, status: :created, location: metacode_sets_url
end
else else
format.html { render action: 'new' } format.html { render action: 'new' }
format.json { render json: @metacode_set.errors, status: :unprocessable_entity } format.json { render json: @metacode_set.errors, status: :unprocessable_entity }
@ -73,20 +79,20 @@ class MetacodeSetsController < ApplicationController
if @metacode_set.update_attributes(metacode_set_params) if @metacode_set.update_attributes(metacode_set_params)
# build an array of the IDs of the metacodes currently in the set # build an array of the IDs of the metacodes currently in the set
@currentMetacodes = @metacode_set.metacodes.map { |m| m.id.to_s } current_metacodes = @metacode_set.metacodes.map { |m| m.id.to_s }
# get the list of desired metacodes for the set from the user input and build an array out of it # get the list of desired metacodes for the set from the user input and build an array out of it
@newMetacodes = params[:metacodes][:value].split(',') new_metacodes = params[:metacodes][:value].split(',')
# remove the metacodes that were in it, but now aren't # remove the metacodes that were in it, but now aren't
@removedMetacodes = @currentMetacodes - @newMetacodes removed_metacodes = current_metacodes - new_metacodes
@removedMetacodes.each do |m| removed_metacodes.each do |m|
@inmetacodeset = InMetacodeSet.find_by_metacode_id_and_metacode_set_id(m, @metacode_set.id) inmetacodeset = InMetacodeSet.find_by(metacode_id: m, metacode_set_id: @metacode_set.id)
@inmetacodeset.destroy inmetacodeset.destroy
end end
# add the new metacodes # add the new metacodes
@addedMetacodes = @newMetacodes - @currentMetacodes added_metacodes = new_metacodes - current_metacodes
@addedMetacodes.each do |m| added_metacodes.each do |m|
InMetacodeSet.create(metacode_id: m, metacode_set_id: @metacode_set.id) InMetacodeSet.create(metacode_id: m, metacode_set_id: @metacode_set.id)
end end

View file

@ -1,7 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
class MetacodesController < ApplicationController class MetacodesController < ApplicationController
before_action :require_admin, except: [:index, :show] before_action :require_admin, except: %i[index show]
before_action :set_metacode, only: [:edit, :update] before_action :set_metacode, only: %i[edit update]
# GET /metacodes # GET /metacodes
# GET /metacodes.json # GET /metacodes.json

View file

@ -0,0 +1,107 @@
# frozen_string_literal: true
class NotificationsController < ApplicationController
before_action :set_receipts, only: %i[index show mark_read mark_unread]
before_action :set_notification, only: %i[show mark_read mark_unread]
before_action :set_receipt, only: %i[show mark_read mark_unread]
def index
@notifications = current_user.mailbox.notifications.page(params[:page]).per(25)
respond_to do |format|
format.html
format.json do
notifications = @notifications.map do |notification|
receipt = @receipts.find_by(notification_id: notification.id)
NotificationDecorator.decorate(notification, receipt)
end
if !notifications.empty?
render json: notifications
else
render json: [].to_json
end
end
end
end
def show
@receipt.update(is_read: true)
respond_to do |format|
format.html do
case @notification.notification_code
when MAP_ACCESS_APPROVED, MAP_INVITE_TO_EDIT
redirect_to map_path(@notification.notified_object.map)
when TOPIC_ADDED_TO_MAP
redirect_to map_path(@notification.notified_object.map)
when TOPIC_CONNECTED_1
redirect_to topic_path(@notification.notified_object.topic1)
when TOPIC_CONNECTED_2
redirect_to topic_path(@notification.notified_object.topic2)
end
end
format.json do
render json: NotificationDecorator.decorate(@notification, @receipt)
end
end
end
def mark_read
@receipt.update(is_read: true)
respond_to do |format|
format.js
format.json do
render json: NotificationDecorator.decorate(@notification, @receipt)
end
end
end
def mark_unread
@receipt.update(is_read: false)
respond_to do |format|
format.js
format.json do
render json: NotificationDecorator.decorate(@notification, @receipt)
end
end
end
def unsubscribe
unsubscribe_redirect_if_logged_out!
check_if_already_unsubscribed!
return if performed? # if one of these checks already redirected, we're done
if current_user.update(emails_allowed: false)
redirect_to edit_user_path(current_user),
notice: 'You will no longer receive emails from Metamaps.'
else
flash[:alert] = 'Sorry, something went wrong. You have not been unsubscribed from emails.'
redirect_to edit_user_path(current_user)
end
end
private
def unsubscribe_redirect_if_logged_out!
return if current_user.present?
flash[:notice] = 'Continue to unsubscribe from emails by logging in.'
redirect_to "#{sign_in_path}?redirect_to=#{unsubscribe_notifications_path}"
end
def check_if_already_unsubscribed!
return if current_user.emails_allowed
redirect_to edit_user_path(current_user), notice: 'You were already unsubscribed from emails.'
end
def set_receipts
@receipts = current_user.mailboxer_notification_receipts
end
def set_notification
@notification = current_user.mailbox.notifications.find_by(id: params[:id])
end
def set_receipt
@receipt = @receipts.find_by(notification_id: params[:id])
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
class SearchController < ApplicationController class SearchController < ApplicationController
include TopicsHelper include TopicsHelper
include MapsHelper include MapsHelper
@ -7,14 +8,15 @@ class SearchController < ApplicationController
before_action :authorize_search before_action :authorize_search
after_action :verify_authorized after_action :verify_authorized
after_action :verify_policy_scoped, only: [:maps, :mappers, :synapses, :topics] after_action :verify_policy_scoped, only: %i[maps mappers synapses topics]
# get /search/topics?term=SOMETERM # get /search/topics?term=SOMETERM
def topics def topics
term = params[:term] term = params[:term]
user = params[:user] ? params[:user] : false user = params[:user] ? params[:user] : false
if term && !term.empty? && term.downcase[0..3] != 'map:' && term.downcase[0..6] != 'mapper:' && !term.casecmp('topic:').zero? if term.present? && term.downcase[0..3] != 'map:' &&
term.downcase[0..6] != 'mapper:' && !term.casecmp('topic:').zero?
# remove "topic:" if appended at beginning # remove "topic:" if appended at beginning
term = term[6..-1] if term.downcase[0..5] == 'topic:' term = term[6..-1] if term.downcase[0..5] == 'topic:'
@ -34,28 +36,28 @@ class SearchController < ApplicationController
end end
# check whether there's a filter by metacode as part of the query # check whether there's a filter by metacode as part of the query
filterByMetacode = false filter_by_metacode = false
Metacode.all.each do |m| Metacode.all.each do |m|
lOne = m.name.length + 1 length_one = m.name.length + 1
lTwo = m.name.length length_two = m.name.length
if term.downcase[0..lTwo] == m.name.downcase + ':' if term.downcase[0..length_two] == m.name.downcase + ':'
term = term[lOne..-1] term = term[length_one..-1]
filterByMetacode = m filter_by_metacode = m
end end
end end
search = '%' + term.downcase + '%' search = '%' + term.downcase.strip + '%'
builder = policy_scope(Topic) builder = policy_scope(Topic)
if filterByMetacode if filter_by_metacode
if term == '' if term == ''
builder = builder.none builder = builder.none
else else
builder = builder.where('LOWER("name") like ? OR builder = builder.where('LOWER("name") like ? OR
LOWER("desc") like ? OR LOWER("desc") like ? OR
LOWER("link") like ?', search, search, search) LOWER("link") like ?', search, search, search)
builder = builder.where(metacode_id: filterByMetacode.id) builder = builder.where(metacode_id: filter_by_metacode.id)
end end
elsif desc elsif desc
builder = builder.where('LOWER("desc") like ?', search) builder = builder.where('LOWER("desc") like ?', search)
@ -70,6 +72,7 @@ class SearchController < ApplicationController
builder = builder.where(user: user) if user builder = builder.where(user: user) if user
@topics = builder.order(:name) @topics = builder.order(:name)
else else
skip_policy_scope
@topics = [] @topics = []
end end
@ -81,7 +84,8 @@ class SearchController < ApplicationController
term = params[:term] term = params[:term]
user = params[:user] ? params[:user] : nil user = params[:user] ? params[:user] : nil
if term && !term.empty? && term.downcase[0..5] != 'topic:' && term.downcase[0..6] != 'mapper:' && !term.casecmp('map:').zero? if term.present? && term.downcase[0..5] != 'topic:' &&
term.downcase[0..6] != 'mapper:' && !term.casecmp('map:').zero?
# remove "map:" if appended at beginning # remove "map:" if appended at beginning
term = term[4..-1] if term.downcase[0..3] == 'map:' term = term[4..-1] if term.downcase[0..3] == 'map:'
@ -93,7 +97,7 @@ class SearchController < ApplicationController
desc = true desc = true
end end
search = '%' + term.downcase + '%' search = '%' + term.downcase.strip + '%'
builder = policy_scope(Map) builder = policy_scope(Map)
builder = if desc builder = if desc
@ -104,6 +108,7 @@ class SearchController < ApplicationController
builder = builder.where(user: user) if user builder = builder.where(user: user) if user
@maps = builder.order(:name) @maps = builder.order(:name)
else else
skip_policy_scope
@maps = [] @maps = []
end end
@ -113,16 +118,17 @@ class SearchController < ApplicationController
# get /search/mappers?term=SOMETERM # get /search/mappers?term=SOMETERM
def mappers def mappers
term = params[:term] term = params[:term]
if term && !term.empty? && term.downcase[0..3] != 'map:' && term.downcase[0..5] != 'topic:' && !term.casecmp('mapper:').zero? if term.present? && term.downcase[0..3] != 'map:' &&
term.downcase[0..5] != 'topic:' && !term.casecmp('mapper:').zero?
# remove "mapper:" if appended at beginning # remove "mapper:" if appended at beginning
term = term[7..-1] if term.downcase[0..6] == 'mapper:' term = term[7..-1] if term.downcase[0..6] == 'mapper:'
search = term.downcase + '%' search = term.downcase.strip + '%'
skip_policy_scope # TODO: builder = policy_scope(User) builder = policy_scope(User).where('LOWER("name") like ?', search)
builder = User.where('LOWER("name") like ?', search)
@mappers = builder.order(:name) @mappers = builder.order(:name)
else else
skip_policy_scope
@mappers = [] @mappers = []
end end
render json: autocomplete_user_array_json(@mappers).to_json render json: autocomplete_user_array_json(@mappers).to_json
@ -135,16 +141,19 @@ class SearchController < ApplicationController
topic1id = params[:topic1id] topic1id = params[:topic1id]
topic2id = params[:topic2id] topic2id = params[:topic2id]
if term && !term.empty? if term.present?
@synapses = policy_scope(Synapse).where('LOWER("desc") like ?', '%' + term.downcase + '%').order('"desc"') @synapses = policy_scope(Synapse)
.where('LOWER("desc") like ?', '%' + term.downcase.strip + '%')
.order('"desc"')
@synapses = @synapses.uniq(&:desc) @synapses = @synapses.uniq(&:desc)
elsif topic1id && !topic1id.empty? elsif topic1id.present?
@one = policy_scope(Synapse).where(topic1_id: topic1id, topic2_id: topic2id) one = policy_scope(Synapse).where(topic1_id: topic1id, topic2_id: topic2id)
@two = policy_scope(Synapse).where(topic2_id: topic1id, topic1_id: topic2id) two = policy_scope(Synapse).where(topic2_id: topic1id, topic1_id: topic2id)
@synapses = @one + @two @synapses = one + two
@synapses.sort! { |s1, s2| s1.desc <=> s2.desc }.to_a @synapses.sort! { |s1, s2| s1.desc <=> s2.desc }.to_a
else else
skip_policy_scope
@synapses = [] @synapses = []
end end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
class StarsController < ApplicationController class StarsController < ApplicationController
before_action :require_user before_action :require_user
before_action :set_map before_action :set_map

View file

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
class SynapsesController < ApplicationController class SynapsesController < ApplicationController
include TopicsHelper include TopicsHelper
before_action :require_user, only: [:create, :update, :destroy] before_action :require_user, only: %i[create update destroy]
after_action :verify_authorized, except: :index after_action :verify_authorized, except: :index
after_action :verify_policy_scoped, only: :index after_action :verify_policy_scoped, only: :index
@ -22,10 +23,20 @@ class SynapsesController < ApplicationController
@synapse = Synapse.new(synapse_params) @synapse = Synapse.new(synapse_params)
@synapse.desc = '' if @synapse.desc.nil? @synapse.desc = '' if @synapse.desc.nil?
@synapse.desc.strip! # no trailing/leading whitespace @synapse.desc.strip! # no trailing/leading whitespace
authorize @synapse @synapse.user = current_user
@synapse.updated_by = current_user
# we want invalid params to return :unprocessable_entity
# so we have to authorize AFTER saving. But if authorize
# fails, we need to rollback the SQL transaction
success = nil
ActiveRecord::Base.transaction do
success = @synapse.save
success ? authorize(@synapse) : skip_authorization
end
respond_to do |format| respond_to do |format|
if @synapse.save if success
format.json { render json: @synapse, status: :created } format.json { render json: @synapse, status: :created }
else else
format.json { render json: @synapse.errors, status: :unprocessable_entity } format.json { render json: @synapse.errors, status: :unprocessable_entity }
@ -39,9 +50,11 @@ class SynapsesController < ApplicationController
@synapse = Synapse.find(params[:id]) @synapse = Synapse.find(params[:id])
@synapse.desc = '' if @synapse.desc.nil? @synapse.desc = '' if @synapse.desc.nil?
authorize @synapse authorize @synapse
@synapse.updated_by = current_user
@synapse.assign_attributes(synapse_params)
respond_to do |format| respond_to do |format|
if @synapse.update_attributes(synapse_params) if @synapse.save
format.json { head :no_content } format.json { head :no_content }
else else
format.json { render json: @synapse.errors, status: :unprocessable_entity } format.json { render json: @synapse.errors, status: :unprocessable_entity }
@ -53,6 +66,7 @@ class SynapsesController < ApplicationController
def destroy def destroy
@synapse = Synapse.find(params[:id]) @synapse = Synapse.find(params[:id])
authorize @synapse authorize @synapse
@synapse.updated_by = current_user
@synapse.destroy @synapse.destroy
respond_to do |format| respond_to do |format|
@ -63,6 +77,8 @@ class SynapsesController < ApplicationController
private private
def synapse_params def synapse_params
params.require(:synapse).permit(:id, :desc, :category, :weight, :permission, :topic1_id, :topic2_id, :user_id) params.require(:synapse).permit(
:id, :desc, :category, :weight, :permission, :topic1_id, :topic2_id
)
end end
end end

View file

@ -0,0 +1,10 @@
# frozen_string_literal: true
class TokensController < ApplicationController
before_action :require_user, only: [:new]
def new
@token = Token.new(user: current_user)
render :new, layout: false
end
end

View file

@ -1,8 +1,12 @@
# frozen_string_literal: true # frozen_string_literal: true
class TopicsController < ApplicationController class TopicsController < ApplicationController
include TopicsHelper include TopicsHelper
before_action :require_user, only: [:create, :update, :destroy] before_action :require_user, only: %i[create update destroy follow unfollow]
before_action :set_topic, only: %i[show update relative_numbers
relatives network destroy
follow unfollow unfollow_from_email]
after_action :verify_authorized, except: :autocomplete_topic after_action :verify_authorized, except: :autocomplete_topic
respond_to :html, :js, :json respond_to :html, :js, :json
@ -10,26 +14,27 @@ class TopicsController < ApplicationController
# GET /topics/autocomplete_topic # GET /topics/autocomplete_topic
def autocomplete_topic def autocomplete_topic
term = params[:term] term = params[:term]
if term && !term.empty? if term.present?
@topics = policy_scope(Topic.where('LOWER("name") like ?', term.downcase + '%')).order('"name"') topics = policy_scope(Topic)
@mapTopics = @topics.select { |t| t.metacode.name == 'Metamap' } .where('LOWER("name") like ?', term.downcase + '%')
.order('"name"')
map_topics = topics.select { |t| t&.metacode&.name == 'Metamap' }
# prioritize topics which point to maps, over maps # prioritize topics which point to maps, over maps
@exclude = @mapTopics.length > 0 ? @mapTopics.map(&:name) : [''] exclude = map_topics.length.positive? ? map_topics.map(&:name) : ['']
@maps = policy_scope(Map.where('LOWER("name") like ? AND name NOT IN (?)', term.downcase + '%', @exclude)).order('"name"') maps = policy_scope(Map)
.where('LOWER("name") like ? AND name NOT IN (?)', term.downcase + '%', exclude)
.order('"name"')
else else
@topics = [] topics = []
@maps = [] maps = []
end end
@all= @topics.to_a.concat(@maps.to_a).sort { |a, b| a.name <=> b.name } @all = topics.to_a.concat(maps.to_a).sort_by(&:name)
render json: autocomplete_array_json(@all) render json: autocomplete_array_json(@all).to_json
end end
# GET topics/:id # GET topics/:id
def show def show
@topic = Topic.find(params[:id])
authorize @topic
respond_to do |format| respond_to do |format|
format.html do format.html do
@alltopics = [@topic].concat(policy_scope(Topic.relatives(@topic.id, current_user)).to_a) @alltopics = [@topic].concat(policy_scope(Topic.relatives(@topic.id, current_user)).to_a)
@ -39,15 +44,12 @@ class TopicsController < ApplicationController
respond_with(@allsynapses, @alltopics, @allcreators, @topic) respond_with(@allsynapses, @alltopics, @allcreators, @topic)
end end
format.json { render json: @topic } format.json { render json: @topic.as_json(user: current_user).to_json }
end end
end end
# GET topics/:id/network # GET topics/:id/network
def network def network
@topic = Topic.find(params[:id])
authorize @topic
@alltopics = [@topic].concat(policy_scope(Topic.relatives(@topic.id, current_user)).to_a) @alltopics = [@topic].concat(policy_scope(Topic.relatives(@topic.id, current_user)).to_a)
@allsynapses = policy_scope(Synapse.for_topic(@topic.id)) @allsynapses = policy_scope(Synapse.for_topic(@topic.id))
@ -55,9 +57,9 @@ class TopicsController < ApplicationController
@allcreators += @allsynapses.map(&:user).uniq @allcreators += @allsynapses.map(&:user).uniq
@json = {} @json = {}
@json['topic'] = @topic @json['topic'] = @topic.as_json(user: current_user)
@json['creators'] = @allcreators @json['creators'] = @allcreators
@json['relatives'] = @alltopics @json['relatives'] = @alltopics.as_json(user: current_user)
@json['synapses'] = @allsynapses @json['synapses'] = @allsynapses
respond_to do |format| respond_to do |format|
@ -67,16 +69,13 @@ class TopicsController < ApplicationController
# GET topics/:id/relative_numbers # GET topics/:id/relative_numbers
def relative_numbers def relative_numbers
@topic = Topic.find(params[:id]) topics_already_has = params[:network] ? params[:network].split(',').map(&:to_i) : []
authorize @topic
topicsAlreadyHas = params[:network] ? params[:network].split(',').map(&:to_i) : []
alltopics = policy_scope(Topic.relatives(@topic.id, current_user)).to_a alltopics = policy_scope(Topic.relatives(@topic.id, current_user)).to_a
alltopics.delete_if { |topic| topic.metacode_id != params[:metacode].to_i } if params[:metacode].present? if params[:metacode].present?
alltopics.delete_if do |topic| alltopics.delete_if { |topic| topic.metacode_id != params[:metacode].to_i }
!topicsAlreadyHas.index(topic.id).nil?
end end
alltopics.delete_if { |topic| !topics_already_has.index(topic.id).nil? }
@json = Hash.new(0) @json = Hash.new(0)
alltopics.each do |t| alltopics.each do |t|
@ -90,15 +89,14 @@ class TopicsController < ApplicationController
# GET topics/:id/relatives # GET topics/:id/relatives
def relatives def relatives
@topic = Topic.find(params[:id]) topics_already_has = params[:network] ? params[:network].split(',').map(&:to_i) : []
authorize @topic
topicsAlreadyHas = params[:network] ? params[:network].split(',').map(&:to_i) : []
alltopics = policy_scope(Topic.relatives(@topic.id, current_user)).to_a alltopics = policy_scope(Topic.relatives(@topic.id, current_user)).to_a
alltopics.delete_if { |topic| topic.metacode_id != params[:metacode].to_i } if params[:metacode].present? if params[:metacode].present?
alltopics.delete_if { |topic| topic.metacode_id != params[:metacode].to_i }
end
alltopics.delete_if do |topic| alltopics.delete_if do |topic|
!topicsAlreadyHas.index(topic.id.to_s).nil? !topics_already_has.index(topic.id.to_s).nil?
end end
# find synapses between topics in alltopics array # find synapses between topics in alltopics array
@ -108,13 +106,13 @@ class TopicsController < ApplicationController
!synapse_ids.index(synapse.id).nil? !synapse_ids.index(synapse.id).nil?
end end
creatorsAlreadyHas = params[:creators] ? params[:creators].split(',').map(&:to_i) : [] creators_already_has = params[:creators] ? params[:creators].split(',').map(&:to_i) : []
allcreators = (alltopics.map(&:user) + allsynapses.map(&:user)).uniq.delete_if do |user| allcreators = (alltopics.map(&:user) + allsynapses.map(&:user)).uniq.delete_if do |user|
!creatorsAlreadyHas.index(user.id).nil? !creators_already_has.index(user.id).nil?
end end
@json = {} @json = {}
@json['topics'] = alltopics @json['topics'] = alltopics.as_json(user: current_user)
@json['synapses'] = allsynapses @json['synapses'] = allsynapses
@json['creators'] = allcreators @json['creators'] = allcreators
@ -128,10 +126,12 @@ class TopicsController < ApplicationController
def create def create
@topic = Topic.new(topic_params) @topic = Topic.new(topic_params)
authorize @topic authorize @topic
@topic.user = current_user
@topic.updated_by = current_user
respond_to do |format| respond_to do |format|
if @topic.save if @topic.save
format.json { render json: @topic, status: :created } format.json { render json: @topic.as_json(user: current_user), status: :created }
else else
format.json { render json: @topic.errors, status: :unprocessable_entity } format.json { render json: @topic.errors, status: :unprocessable_entity }
end end
@ -141,11 +141,11 @@ class TopicsController < ApplicationController
# PUT /topics/1 # PUT /topics/1
# PUT /topics/1.json # PUT /topics/1.json
def update def update
@topic = Topic.find(params[:id]) @topic.updated_by = current_user
authorize @topic @topic.assign_attributes(topic_params)
respond_to do |format| respond_to do |format|
if @topic.update_attributes(topic_params) if @topic.save
format.json { head :no_content } format.json { head :no_content }
else else
format.json { render json: @topic.errors, status: :unprocessable_entity } format.json { render json: @topic.errors, status: :unprocessable_entity }
@ -155,18 +155,58 @@ class TopicsController < ApplicationController
# DELETE topics/:id # DELETE topics/:id
def destroy def destroy
@topic = Topic.find(params[:id]) @topic.updated_by = current_user
authorize @topic
@topic.destroy @topic.destroy
respond_to do |format| respond_to do |format|
format.json { head :no_content } format.json { head :no_content }
end end
end end
# POST topics/:id/follow
def follow
follow = FollowService.follow(@topic, current_user, 'followed')
respond_to do |format|
format.json do
if follow
head :ok
else
head :bad_request
end
end
end
end
# POST topics/:id/unfollow
def unfollow
FollowService.unfollow(@topic, current_user)
respond_to do |format|
format.json do
head :ok
end
end
end
# GET topics/:id/unfollow_from_email
def unfollow_from_email
FollowService.unfollow(@topic, current_user)
respond_to do |format|
format.html do
redirect_to topic_path(@topic), notice: 'You are no longer following this topic'
end
end
end
private private
def set_topic
@topic = Topic.find(params[:id])
authorize @topic
end
def topic_params def topic_params
params.require(:topic).permit(:id, :name, :desc, :link, :permission, :user_id, :metacode_id, :defer_to_map_id) params.require(:topic).permit(:id, :name, :desc, :link, :permission, :metacode_id, :defer_to_map_id)
end end
end end

View file

@ -1,5 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class Users::PasswordsController < Devise::PasswordsController
module Users
class PasswordsController < Devise::PasswordsController
protected protected
def after_resetting_password_path_for(resource) def after_resetting_password_path_for(resource)
@ -7,6 +9,7 @@ class Users::PasswordsController < Devise::PasswordsController
end end
def after_sending_reset_password_instructions_path_for(_resource_name) def after_sending_reset_password_instructions_path_for(_resource_name)
new_user_session_path if is_navigational_format? sign_in_path if is_navigational_format?
end
end end
end end

View file

@ -1,25 +1,40 @@
# frozen_string_literal: true # frozen_string_literal: true
class Users::RegistrationsController < Devise::RegistrationsController
module Users
class RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create] before_action :configure_sign_up_params, only: [:create]
before_action :configure_account_update_params, only: [:update] before_action :configure_account_update_params, only: [:update]
after_action :store_location, only: [:new]
protected protected
def after_sign_up_path_for(resource)
signed_in_root_path(resource)
end
def after_update_path_for(resource) def after_update_path_for(resource)
signed_in_root_path(resource) signed_in_root_path(resource)
end end
def after_sign_in_path_for(resource)
stored = stored_location_for(User)
return stored if stored
if request.referer&.match(sign_in_url) || request.referer&.match(sign_up_url)
super
else
request.referer || root_path
end
end
private private
def store_location
store_location_for(User, params[:redirect_to]) if params[:redirect_to]
end
def configure_sign_up_params def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :joinedwithcode]) devise_parameter_sanitizer.permit(:sign_up, keys: %i[name joinedwithcode])
end end
def configure_account_update_params def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:image]) devise_parameter_sanitizer.permit(:account_update, keys: [:image])
end end
end end
end

View file

@ -0,0 +1,26 @@
# frozen_string_literal: true
module Users
class SessionsController < Devise::SessionsController
after_action :store_location, only: [:new]
protected
def after_sign_in_path_for(resource)
stored = stored_location_for(User)
return stored if stored
if request.referer&.match(sign_in_url) || request.referer&.match(sign_up_url)
super
else
request.referer || root_path
end
end
private
def store_location
store_location_for(User, params[:redirect_to]) if params[:redirect_to]
end
end
end

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class UsersController < ApplicationController class UsersController < ApplicationController
before_action :require_user, only: [:edit, :update, :updatemetacodes] before_action :require_user, only: %i[edit update updatemetacodes update_metacode_focus]
respond_to :html, :json respond_to :html, :json
@ -13,25 +14,25 @@ class UsersController < ApplicationController
# GET /users/:id/edit # GET /users/:id/edit
def edit def edit
@user = current_user @user = User.find(current_user.id)
respond_with(@user)
end end
# PUT /users/:id # PUT /users/:id
def update def update
@user = current_user @user = User.find(current_user.id)
if user_params[:password] == '' && user_params[:password_confirmation] == '' if user_params[:password] == '' && user_params[:password_confirmation] == ''
# not trying to change the password # not trying to change the password
if @user.update_attributes(user_params.except(:password, :password_confirmation)) if @user.update_attributes(user_params.except(:password, :password_confirmation))
update_follow_settings(@user, params[:settings])
@user.image = nil if params[:remove_image] == '1' @user.image = nil if params[:remove_image] == '1'
@user.save @user.save
sign_in(@user, bypass: true) bypass_sign_in(@user)
respond_to do |format| respond_to do |format|
format.html { redirect_to root_url, notice: 'Account updated!' } format.html { redirect_to root_url, notice: 'Settings updated' }
end end
else else
sign_in(@user, bypass: true) bypass_sign_in(@user)
respond_to do |format| respond_to do |format|
format.html { redirect_to edit_user_path(@user), notice: @user.errors.to_a[0] } format.html { redirect_to edit_user_path(@user), notice: @user.errors.to_a[0] }
end end
@ -41,11 +42,12 @@ class UsersController < ApplicationController
correct_pass = @user.valid_password?(params[:current_password]) correct_pass = @user.valid_password?(params[:current_password])
if correct_pass && @user.update_attributes(user_params) if correct_pass && @user.update_attributes(user_params)
update_follow_settings(@user, params[:settings])
@user.image = nil if params[:remove_image] == '1' @user.image = nil if params[:remove_image] == '1'
@user.save @user.save
sign_in(@user, bypass: true) sign_in(@user, bypass: true)
respond_to do |format| respond_to do |format|
format.html { redirect_to root_url, notice: 'Account updated!' } format.html { redirect_to root_url, notice: 'Settings updated' }
end end
else else
respond_to do |format| respond_to do |format|
@ -93,9 +95,28 @@ class UsersController < ApplicationController
end end
end end
# PUT /user/update_metacode_focus
def update_metacode_focus
@user = current_user
@user.settings.metacode_focus = params[:value]
@user.save
respond_to do |format|
format.json { render json: { success: 'success' } }
end
end
private private
def update_follow_settings(user, settings)
user.settings.follow_topic_on_created = settings[:follow_topic_on_created]
user.settings.follow_topic_on_contributed = settings[:follow_topic_on_contributed]
user.settings.follow_map_on_created = settings[:follow_map_on_created]
user.settings.follow_map_on_contributed = settings[:follow_map_on_contributed]
end
def user_params def user_params
params.require(:user).permit(:name, :email, :image, :password, :password_confirmation) params.require(:user).permit(
:name, :email, :image, :password, :password_confirmation, :emails_allowed, :settings
)
end end
end end

View file

@ -0,0 +1,51 @@
# frozen_string_literal: true
class NotificationDecorator
class << self
def decorate(notification, receipt)
result = {
id: notification.id,
type: notification.notification_code,
subject: notification.subject,
is_read: receipt.is_read,
created_at: notification.created_at,
actor: notification.sender,
data: {
object: notification.notified_object
}
}
case notification.notification_code
when MAP_ACCESS_APPROVED, MAP_ACCESS_REQUEST, MAP_INVITE_TO_EDIT
map = notification.notified_object&.map
result[:data][:map] = {
id: map&.id,
name: map&.name
}
when TOPIC_ADDED_TO_MAP
topic = notification.notified_object&.eventable
map = notification.notified_object&.map
result[:data][:topic] = {
id: topic&.id,
name: topic&.name
}
result[:data][:map] = {
id: map&.id,
name: map&.name
}
when TOPIC_CONNECTED_1, TOPIC_CONNECTED_2
topic1 = notification.notified_object&.topic1
topic2 = notification.notified_object&.topic2
result[:data][:topic1] = {
id: topic1&.id,
name: topic1&.name
}
result[:data][:topic2] = {
id: topic2&.id,
name: topic2&.name
}
end
result
end
end
end

View file

@ -1,40 +1,14 @@
# frozen_string_literal: true # frozen_string_literal: true
module ApplicationHelper module ApplicationHelper
def metacodeset
metacodes = current_user.settings.metacodes
return false unless metacodes[0].include?('metacodeset')
if metacodes[0].sub('metacodeset-', '') == 'Most'
return 'Most'
elsif metacodes[0].sub('metacodeset-', '') == 'Recent'
return 'Recent'
end
MetacodeSet.find(metacodes[0].sub('metacodeset-', '').to_i)
end
def user_metacodes
@m = current_user.settings.metacodes
set = metacodeset
@metacodes = if set && set == 'Most'
Metacode.where(id: current_user.mostUsedMetacodes).to_a
elsif set && set == 'Recent'
Metacode.where(id: current_user.recentMetacodes).to_a
elsif set
set.metacodes.to_a
else
Metacode.where(id: @m).to_a
end
@metacodes.sort! { |m1, m2| m2.name.downcase <=> m1.name.downcase }.rotate!(-1)
end
def user_most_used_metacodes
@metacodes = current_user.mostUsedMetacodes.map { |id| Metacode.find(id) }
end
def user_recent_metacodes
@metacodes = current_user.recentMetacodes.map { |id| Metacode.find(id) }
end
def invite_link def invite_link
"#{request.base_url}/join" + (current_user ? "?code=#{current_user.code}" : '') "#{request.base_url}/join" + (current_user ? "?code=#{current_user.code}" : '')
end end
def user_unread_notification_count
return 0 if current_user.nil?
@uunc ||= current_user.mailboxer_notification_receipts.reduce(0) do |total, receipt|
receipt.is_read ? total : total + 1
end
end
end end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
module ContentHelper module ContentHelper
def resource_name def resource_name
:user :user

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
module DeviseHelper module DeviseHelper
def devise_error_messages! def devise_error_messages!
resource.errors.to_a[0] resource.errors.to_a[0]

View file

@ -1,3 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
module InMetacodeSetsHelper module InMetacodeSetsHelper
end end

View file

@ -1,3 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
module MainHelper module MainHelper
end end

Some files were not shown because too many files have changed in this diff Show more