', {
174 | class: 'alert alert-danger alert-dismissible',
175 | text: 'Repository could not be found. The repository must be public.',
176 | }).append('
')
178 | .appendTo('#user-hacker-alertbox');
179 | } else {
180 | ownerHandle = URLArray[i + 1];
181 | repo = URLArray[i + 2];
182 | repoObj = {
183 | handle,
184 | name: repo,
185 | owner: ownerHandle,
186 | full_name: `${ownerHandle}/${repo}`,
187 | url: repoURL,
188 | };
189 | updateRepository(repoObj);
190 | repoObj = {};
191 | }
192 | });
193 | } catch (errorString) {
194 | $('
', {
195 | class: 'alert alert-danger alert-dismissible',
196 | text: errorString,
197 | }).append('
× ')
199 | .appendTo('#user-hacker-alertbox');
200 | }
201 | },
202 | 'click #user-hacker-leave-repo': function() {
203 | if (!confirm("Are you sure want to leave this project?"))
204 | return false;
205 | Meteor.subscribe("userData");
206 | Meteor.subscribe("RepositoryList");
207 | var repo_id = Meteor.user().profile.repositoryId;
208 | var handle = Meteor.user().profile.github_handle;
209 | // delete their information in the repository entry
210 | RepositoryList.update({ "_id":repo_id }, {
211 | $pull: {
212 | contributors: {
213 | id: Meteor.userId(),
214 | handle: handle
215 | }
216 | }
217 | }, function(error, nUpdated) {
218 | if (!error) {
219 | // delete the information from the user's profile
220 | Meteor.users.update({ "_id":Meteor.userId() }, {
221 | $set: {
222 | "profile.github_handle": "",
223 | "profile.repository": "",
224 | "profile.repositoryId": ""
225 | }
226 | });
227 | var repo_doc = RepositoryList.findOne({ '_id': repo_id });
228 | if (Meteor.userId() === repo_doc.webhook.createdBy)
229 | Meteor.call('deleteRepositoryWebhook', Meteor.userId(), repo_doc);
230 | // delete the repository if they were the last person on the project
231 | RepositoryList.remove({ '_id': repo_id });
232 | }
233 | }
234 | );
235 | },
236 | 'click #user-devPost-save': function() {
237 | new_devpost_link = $("#devPost-input").val();
238 | devPost_dep.changed();
239 | },
240 |
241 | 'click #github-signin': function() {
242 | Meteor.call('getGitHubRedirect', Meteor.userId(), function(error, result) {
243 | if (error) {
244 | Session.set('displayMessage', {
245 | title: error.error,
246 | body: error.reason
247 | });
248 | }
249 | else {
250 | window.location = result;
251 | }
252 | });
253 | },
254 |
255 | });
256 |
--------------------------------------------------------------------------------
/client/script/user/mentor.js:
--------------------------------------------------------------------------------
1 | var edit_skills_flag = false,
2 | edit_skills_dep = new Tracker.Dependency;
3 |
4 | Template.user_mentor.rendered = function() {
5 | Meteor.subscribe("MentorQueue");
6 | Meteor.subscribe('UserData', Meteor.userId());
7 | }
8 |
9 | Template.user_mentor.helpers({
10 | checked_in: function() {
11 | try {
12 | return Meteor.user().settings.checked_in;
13 | }
14 | catch (e) {
15 | return false;
16 | }
17 | },
18 | active: function() {
19 | // return the status of the mentor
20 | return Meteor.user().profile.active;
21 | },
22 | assignment: function() {
23 | // returns the details of the mentor's current assignment
24 | if (Meteor.user().profile.mentee_id)
25 | return MentorQueue.findOne({
26 | '_id': Meteor.user().profile.mentee_id
27 | });
28 | else return false;
29 | },
30 | skills: function() {
31 | // returns the mentor's list of skills
32 | var arr = [];
33 | Meteor.user().profile.tags.forEach(function(val) {
34 | arr.push(val);
35 | });
36 | return arr;
37 | },
38 | history: function() {
39 | // returns a list of the mentor's past assignments
40 | return Meteor.user().profile.history;
41 | },
42 | editSkills: function() {
43 | // toggle editting the mentor's skills
44 | edit_skills_dep.depend();
45 | return edit_skills_flag;
46 | },
47 | modifyLangs: function() {
48 | // return a list of the mentor's languages with the selected ones marked
49 | var all = [];
50 | Meteor.settings.public.languages.forEach(function(lang) {
51 | all.push({
52 | name: lang,
53 | checked: $.inArray(lang, Meteor.user().profile.languages) != -1 });
54 | });
55 | return all;
56 | },
57 | modifyFrames: function() {
58 | // return a list of the mentor's frameworks with the selected ones marked
59 | var all = [];
60 | Meteor.settings.public.frameworks.forEach(function(frame) {
61 | all.push({
62 | name: frame,
63 | checked: $.inArray(frame, Meteor.user().profile.frameworks) != -1 });
64 | });
65 | return all;
66 | },
67 | modifyApis: function() {
68 | // return a list of the mentor's APIs with the selected ones marked
69 | var all = [];
70 | Meteor.settings.public.apis.forEach(function(api) {
71 | all.push({
72 | name: api,
73 | checked: $.inArray(api, Meteor.user().profile.apis) != -1 });
74 | });
75 | return all;
76 | }
77 | });
78 |
79 | Template.user_mentor.events({
80 | 'click .user-mentor-btn': function(e) {
81 | var target = $(e.target).attr('value');
82 | switch (target) {
83 | case 'activate':
84 | // toggle the mentor as active
85 | Meteor.users.update({ '_id': Meteor.userId() }, {
86 | $set: { 'profile.active': true }
87 | });
88 | break;
89 | case 'suspend':
90 | // toggle the mentor as unactive
91 | Meteor.users.update({ '_id':Meteor.userId() }, {
92 | $set: { 'profile.active': false }
93 | });
94 | break;
95 | case 'edit-skills':
96 | // toggle editting the mentor's skills
97 | edit_skills_flag = !edit_skills_flag;
98 | edit_skills_dep.changed();
99 | break;
100 | case 'save-skills':
101 | // save all changes made the selected skills
102 | Meteor.subscribe("userData");
103 | var languages = [],
104 | frameworks = [],
105 | apis = [],
106 | all = [];
107 | $("#user-mentor-checkbox-langs input:checked").each(function() {
108 | languages.push(this.name); all.push(this.name);
109 | });
110 | $("#user-mentor-checkbox-frames input:checked").each(function() {
111 | frameworks.push(this.name); all.push(this.name);
112 | });
113 | $("#user-mentor-checkbox-apis input:checked").each(function() {
114 | apis.push(this.name); all.push(this.name);
115 | });
116 | if (Meteor.users.update({ '_id': Meteor.userId() }, {
117 | $set: {
118 | 'profile.languages': languages,
119 | 'profile.frameworks': frameworks,
120 | 'profile.apis': apis,
121 | 'profile.tags': all
122 | }
123 | })) {
124 | Session.set("displayMessage", {
125 | title: 'Success',
126 | body: 'Data saved successfully'
127 | });
128 | edit_skills_flag = false;
129 | edit_skills_dep.changed();
130 | }
131 | else {
132 | Session.set("displayMessage", {
133 | title: "Error",
134 | body: "Something went wrong trying to save your changes." +
135 | " Please try again later!"
136 | });
137 | }
138 | break;
139 | case 'complete-task':
140 | // complete the mentor's current assignment
141 | var mentee_id = Meteor.user().profile.mentee_id,
142 | mentee = MentorQueue.findOne({ "_id": mentee_id });
143 | Meteor.users.update({ "_id": Meteor.userId() }, {
144 | $set: {
145 | "profile.available": true,
146 | "profile.mentee_id": null
147 | },
148 | $push: {
149 | "profile.history": {
150 | "name": mentee.name,
151 | "_id": mentee_id,
152 | "tag": mentee.tag,
153 | "loc": mentee.loc,
154 | "time": (new Date()).toLocaleString()
155 | }
156 | }
157 | });
158 | break;
159 | case 'waive-btn':
160 | // return the current task back to the queue to be assigned to someone
161 | // else (nothing preventing self re-assignment!)
162 | var mentee_doc = MentorQueue.findOne({
163 | '_id': Meteor.user().profile.mentee_id
164 | });
165 | MentorQueue.update({ '_id': mentee_doc._id }, {
166 | $set: { 'completed': false }
167 | }, function(error, result) {
168 | if (mentee_doc.phone) {
169 | Meteor.call('sendText', mentee_doc.phone,
170 | Meteor.user().profile.name +
171 | ' was called away. You have been added back into the queue.');
172 | }
173 | });
174 | Meteor.users.update({ '_id': Meteor.userId() }, {
175 | $set: {
176 | 'profile.available': true,
177 | 'profile.active': false,
178 | 'profile.mentee_id': null,
179 | }
180 | });
181 | break;
182 | default:
183 | break;
184 | }
185 | },
186 | });
187 |
--------------------------------------------------------------------------------
/client/script/user/profile.js:
--------------------------------------------------------------------------------
1 | Template.user_profile.rendered = function() {
2 | Meteor.subscribe("UserData", Meteor.userId());
3 | }
4 |
5 | Template.user_profile.helpers({
6 | accepted: function() {
7 | try {
8 | return Meteor.user().settings.accepted.flag;
9 | }
10 | catch (e) {
11 | return false;
12 | }
13 | },
14 | not_confirmed: function() {
15 | try {
16 | return ! Meteor.user().settings.confirmed.flag;
17 | }
18 | catch (e) {
19 | return false;
20 | }
21 | },
22 | email: function() {
23 | try {
24 | return Meteor.user().emails[0].address;
25 | }
26 | catch (e) {
27 | return '';
28 | }
29 | },
30 | name: function() {
31 | try {
32 | return Meteor.user().profile.name;
33 | }
34 | catch (e) {
35 | return '';
36 | }
37 | },
38 | affiliation: function() {
39 | try {
40 | return Meteor.user().profile.affiliation;
41 | }
42 | catch (e) {
43 | return '';
44 | }
45 | },
46 | phone: function() {
47 | try {
48 | return Meteor.user().profile.phone;
49 | }
50 | catch (e) {
51 | return '';
52 | }
53 | },
54 | location: function() {
55 | try {
56 | return Meteor.user().profile.location;
57 | }
58 | catch (e) {
59 | return '';
60 | }
61 | },
62 | school: function() {
63 | try {
64 | return Meteor.user().profile.school.name;
65 | }
66 | catch (e) {
67 | return '';
68 | }
69 | },
70 | travel_method: function() {
71 | try {
72 | return Meteor.user().settings.accepted.travel.method;
73 | }
74 | catch (e) {
75 | return '';
76 | }
77 | },
78 | diet: function() {
79 | try {
80 | return Meteor.user().profile.diet.list;
81 | }
82 | catch (e) {
83 | return [];
84 | }
85 | },
86 | resume: function() {
87 | try {
88 | return Meteor.user().profile.resume;
89 | }
90 | catch (e) {
91 | return '';
92 | }
93 | },
94 | international: function() {
95 | try {
96 | return Meteor.user().profile.travel.international;
97 | }
98 | catch (e) {
99 | return false;
100 | }
101 | },
102 | city_country: function() {
103 | try {
104 | return Meteor.user().profile.travel.location;
105 | }
106 | catch (e) {
107 | return '';
108 | }
109 | },
110 | zipcode: function() {
111 | try {
112 | return Meteor.user().profile.travel.zipcode;
113 | }
114 | catch (e) {
115 | return '';
116 | }
117 | },
118 | github: function() {
119 | try {
120 | return Meteor.user().profile.websites.github;
121 | }
122 | catch (e) {
123 | return '';
124 | }
125 | },
126 | linkedIn: function() {
127 | try {
128 | return Meteor.user().profile.websites.linkedIn;
129 | }
130 | catch (e) {
131 | return '';
132 | }
133 | },
134 | website: function() {
135 | try {
136 | return Meteor.user().profile.websites.personal;
137 | }
138 | catch (e) {
139 | return '';
140 | }
141 | },
142 | editActive: function() {
143 | user_profile_edit_dep.depend();
144 | return user_profile_edit;
145 | },
146 | allTravel: function() {
147 | try {
148 | return _.map(Meteor.settings.public.buses, function(route) {
149 | return {
150 | route: route,
151 | selected: Meteor.user().profile.travel.method === route
152 | }
153 | });
154 | }
155 | catch (e) {
156 | Meteor.settings.public.buses;
157 | }
158 | },
159 | allDiets: function() {
160 | try {
161 | return _.map(Meteor.settings.public.diet, function(name) {
162 | return {
163 | name: name,
164 | selected: _.contains(Meteor.user().profile.diet.list, name)
165 | }
166 | });
167 | }
168 | catch (e) {
169 | return Meteor.settings.public.diet;
170 | }
171 | },
172 | special_diet: function() {
173 | try {
174 | return Meteor.user().profile.diet.special;
175 | }
176 | catch (e) {
177 | return '';
178 | }
179 | }
180 | });
181 |
182 | var user_profile_edit = false;
183 | var user_profile_edit_dep = new Tracker.Dependency;
184 |
185 | Template.user_profile.events({
186 | 'click #user-profile-edit-btn': function(e) {
187 | e.preventDefault();
188 | user_profile_edit = true;
189 | user_profile_edit_dep.changed();
190 | },
191 | 'change #user-profile input[name="resume"]': function() {
192 | var resume_file = $('#user-profile input[name="resume"]')[0].files[0];
193 | if (! resume_file)
194 | return;
195 | else if (resume_file.type !== 'application/pdf') {
196 | Session.set('displayMessage', {
197 | title: 'Resume Error',
198 | body: 'Resume upload must be a PDF.'
199 | });
200 | return;
201 | }
202 | else if (resume_file.size / 1024 > 10240) {
203 | Session.set('displayMessage', {
204 | title: 'Resume Error',
205 | body: 'Maximum resume file size is 10MB.'
206 | });
207 | return;
208 | }
209 | var reader = new FileReader();
210 | reader.onload = function(event) {
211 | var binary_data = new Uint8Array(reader.result);
212 | Meteor.users.update({ _id: Meteor.userId() }, {
213 | $set: {
214 | 'profile.resume': binary_data
215 | }
216 | });
217 | }
218 | reader.readAsArrayBuffer(resume_file);
219 | },
220 | 'click #user-profile-save-btn': function(e, t) {
221 | // check edits and save to db
222 | e.preventDefault();
223 | var old_profile = Meteor.user().profile;
224 |
225 | var new_name = t.find("#UPedit-name").value,
226 | new_affiliation = t.find("#UPedit-affiliation").value,
227 | new_phone = t.find("#UPedit-phone").value,
228 | new_location = t.find("#UPedit-location").value,
229 | new_school = t.find('#UPedit-school').value,
230 | new_travel = $('.travel-selection input:checked').attr('value') || '',
231 | new_diet = [],
232 | new_special_diet = t.find('#UPedit-diet-special').value,
233 | new_zipcode = null,
234 | new_city_country = null;
235 |
236 | if (old_profile.travel.international) {
237 | new_city_country = t.find('#UPedit-city-country').value;
238 | }
239 | else {
240 | new_zipcode = t.find('#UPedit-zipcode').value;
241 | }
242 |
243 | $('.diet-selection input:checked').each(function() {
244 | new_diet.push(this.value);
245 | });
246 |
247 | Meteor.users.update({ "_id": Meteor.userId() }, {
248 | $set: {
249 | "profile.name": new_name,
250 | "profile.affiliation": new_affiliation,
251 | "profile.phone": new_phone,
252 | 'profile.location': new_location,
253 | "profile.school": new_school,
254 | 'profile.travel.method': new_travel,
255 | 'profile.travel.zipcode': new_zipcode,
256 | 'profile.travel.location': new_city_country,
257 | 'profile.diet.list': new_diet,
258 | 'profile.diet.special': new_special_diet
259 | }
260 | }, {}, function(error, data) {
261 | if (error) {
262 | Session.set("displayMessage", {
263 | title: "Error",
264 | body: 'Something went wrong saving the data! You may not have ' +
265 | 'permission to perform this action.'
266 | });
267 | } else {
268 | // data save successfully
269 | Session.set("displayMessage", {
270 | title: "Success",
271 | body: "Data saved successfully!"
272 | });
273 | }
274 | });
275 |
276 | user_profile_edit = false;
277 | user_profile_edit_dep.changed();
278 | },
279 | 'click #user-profile-cancel-btn': function(e) {
280 | e.preventDefault();
281 | user_profile_edit = false;
282 | user_profile_edit_dep.changed();
283 | },
284 | });
285 |
--------------------------------------------------------------------------------
/client/script/user/server_settings.js:
--------------------------------------------------------------------------------
1 | Template.user_server_settings.helpers({
2 | allowAccountCreation: function() {
3 | Meteor.subscribe('UserData', Meteor.userId());
4 | return Meteor.user().profile.settings.allow_account_creation;
5 | },
6 | mentoringSystemStatus: function() {
7 | Meteor.subscribe('UserData', Meteor.userId());
8 | return Meteor.user().profile.settings.mentoring_system;
9 | },
10 | alertNumbers: function() {
11 | Meteor.subscribe('UserData', Meteor.userId());
12 | if (Meteor.user().settings)
13 | return Meteor.user().settings.alert_numbers;
14 | else return [];
15 | },
16 | stage: function() {
17 | if (Meteor.user().settings) {
18 | var stage = Meteor.user().settings.event_stage;
19 | return [
20 | {
21 | name: 'Registration',
22 | value: 'registration',
23 | checked: stage === 'registration'
24 | },
25 | {
26 | name: 'Check-In',
27 | value: 'check-in',
28 | checked: stage === 'check-in'
29 | },
30 | {
31 | name: 'Main Event',
32 | value: 'main-event',
33 | checked: stage === 'main-event'
34 | }
35 | ];
36 | }
37 | else return [];
38 | }
39 | });
40 |
41 | Template.user_server_settings.events({
42 | // Account Creating Settings
43 | 'click #admin-allow-account-creation-off-btn': function() {
44 | Meteor.subscribe("UserData", Meteor.userId());
45 | Meteor.users.update( {"_id":Meteor.userId()}, {
46 | $set: {
47 | "profile.settings.allow_account_creation": false
48 | }
49 | });
50 | },
51 | 'click #admin-allow-account-creation-on-btn': function() {
52 | Meteor.subscribe("UserData", Meteor.userId());
53 | Meteor.users.update( {"_id":Meteor.userId()}, {
54 | $set: {
55 | "profile.settings.allow_account_creation": true
56 | }
57 | });
58 | },
59 | // Mentoring Settings
60 | 'click #admin-mentoring-off-btn': function() {
61 | Meteor.subscribe("UserData", Meteor.userId());
62 | Meteor.users.update( {"_id":Meteor.userId()}, {
63 | $set: {
64 | "profile.settings.mentoring_system": false
65 | }
66 | });
67 | },
68 | 'click #admin-mentoring-on-btn': function() {
69 | Meteor.subscribe("UserData", Meteor.userId());
70 | Meteor.users.update( {"_id":Meteor.userId()}, {
71 | $set: {
72 | "profile.settings.mentoring_system": true
73 | }
74 | });
75 | },
76 | // alert numbers
77 | 'click #add-alert-number-btn': function() {
78 | var phone = $('#alertNum-input').val();
79 | $('#alertNum-input').val('');
80 | if (! phone) return;
81 | phone = Forms.stripPhone(phone);
82 | Meteor.users.update({ '_id': Meteor.userId() }, {
83 | $push: {
84 | 'settings.alert_numbers': phone
85 | }
86 | });
87 | },
88 | 'click .alert-num-remove': function() {
89 | Meteor.users.update({ '_id': Meteor.userId() }, {
90 | $pull: {
91 | 'settings.alert_numbers': this + ''
92 | }
93 | });
94 | },
95 | // event stage
96 | 'change .event-stage': function(e) {
97 | var stage = $(e.target).attr('value');
98 | Meteor.users.update({ '_id': Meteor.userId() }, {
99 | $set: {
100 | 'settings.event_stage': stage
101 | }
102 | });
103 | }
104 | });
105 |
--------------------------------------------------------------------------------
/client/script/user/user.js:
--------------------------------------------------------------------------------
1 | Template.user.rendered = function() {
2 | // get to see if we have an incoming code from GitHub
3 | if (window.location.search) {
4 | params = window.location.search.split('&').map(function(d) { return d.split('='); });
5 | if (params.length > 1 && params[0][0] === '?code' && params[1][0] === 'state') {
6 | // grab access token
7 | Meteor.call('getGitHubAccessToken', params[0][1], params[1][1], Meteor.userId(),
8 | function(error, result) {
9 | if (! error) {
10 | // if we got an access token then create a webhook
11 | Meteor.call('createRepositoryWebhook', Meteor.userId(),
12 | function(error, result) {
13 | if (! error) {
14 | Session.set('displayMessage', {
15 | title: 'Success',
16 | body: 'Github was connected successfully and a webhook was '
17 | + 'created. Happy hacking!'
18 | });
19 | }
20 | else {
21 | Session.set('displayMessage', {
22 | title: error.error,
23 | body: error.reason
24 | });
25 | }
26 | });
27 | // then grab any (at most 30) commits that we may have missed
28 | Meteor.call('addCommits', Meteor.userId(),
29 | function(error, result) {
30 | if (error) {
31 | Session.set('displayMessage', {
32 | title: error.error,
33 | body: error.reason
34 | });
35 | }
36 | }
37 | );
38 | }
39 | else {
40 | Session.set('displayMessage', {
41 | title: error.error,
42 | body: error.reason
43 | });
44 | }
45 | });
46 | }
47 | }
48 | };
49 |
50 | Template.user.helpers({
51 | user_page: function() {
52 | var page = Session.get('user-page');
53 | if (page === 'hacker')
54 | return 'userHacker';
55 | else if (page === 'mentor')
56 | return 'user_mentor';
57 | else if (page === 'volunteer')
58 | return 'user_volunteer';
59 | else if (page === 'announcements')
60 | return 'user_announcements';
61 | else if (page === 'database')
62 | return 'user_database';
63 | else if (page === 'server-settings')
64 | return 'user_server_settings';
65 | else
66 | return 'user_profile';
67 | },
68 | hasAnnouncerAccess: function() {
69 | return Roles.userIsInRole(Meteor.userId(), ['admin', 'announcer']);
70 | }
71 | });
72 |
73 | Template.user.events({
74 | 'click .user-sidebar-btn': function(e) {
75 | Session.set('user-page', $(e.target).attr('value'));
76 | }
77 | });
78 |
--------------------------------------------------------------------------------
/client/style/check_in.less:
--------------------------------------------------------------------------------
1 | @import "global";
2 |
3 | .checkin-panel {
4 | height: 100%;
5 | margin: 0 auto;
6 | text-align: center;
7 | }
8 |
9 | .checkin-container, checkin-success-container {
10 | display: none;
11 | }
12 |
13 | .checkin-container .validate, .checkin-container .confirm-checkin {
14 | text-align: center;
15 | margin: 0 auto;
16 | }
17 |
18 | .checkin-container input {
19 | height: 100px;
20 | width: 200px;
21 | font-size: 48px;
22 | text-align: center;
23 | margin: 5% auto;
24 | display: block;
25 | }
26 |
27 | .checkin-container .confirm-checkin input {
28 | width: 550px;
29 | }
30 |
31 | .checkin-btn {
32 | background-color: @accent;
33 | color: #FFFFFF;
34 | padding: 10px;
35 | font-size: 18px;
36 | }
37 |
38 | .checkin-container .checkin-btn:hover {
39 | background-color: @dark-accent;
40 | }
41 |
42 | .checkin-panel .checkin-return-btn {
43 | margin-top: 100px;
44 | }
45 |
46 | .checkin-container .checkin-btn[data-action="register"] {
47 | margin-top: 100px;
48 | }
49 |
50 | .checkin-container .confirm-checkin .form-error {
51 | width: 600px;
52 | margin: 0 auto;
53 | display: none;
54 | }
55 |
56 | .checkin-success-container {
57 | text-align: center;
58 | margin: 10% auto;
59 | }
60 |
61 | .checkin-success-container p {
62 | margin-bottom: 50px;
63 | }
--------------------------------------------------------------------------------
/client/style/commits.css:
--------------------------------------------------------------------------------
1 | .commit-box {
2 | background: #FFFFFF;
3 | border-radius: 10px;
4 | padding: 20px;
5 | margin-bottom: 20px;
6 | color: #000000;
7 | float: left;
8 | width: 98%;
9 | }
10 |
11 | .commit-repo {
12 | font-size: 32px;
13 | }
14 |
15 | .commit-text {
16 | font-size: 18px;
17 | }
18 |
19 | .commit-flag-count {
20 | float:right;
21 | font-size: 14px;
22 | }
23 |
24 | .commit-flag-count i {
25 | padding-left: 2px;
26 | padding-right: 2px;
27 | }
28 |
29 | .commit-flag-count i.fa-thumbs-up {
30 | cursor: pointer;
31 | }
32 |
33 | .commit-date {
34 | color: #cdcdcd;
35 | float: right;
36 | }
37 |
38 | .commit-bookmark {
39 | margin-top: -2px;
40 | margin-left: -20px;
41 | color: #FFD700;
42 | }
43 |
--------------------------------------------------------------------------------
/client/style/confirm.less:
--------------------------------------------------------------------------------
1 | @import "global";
2 |
3 | #confirm-container.reactive-container {
4 | text-align: center;
5 | margin: auto;
6 |
7 | @media only screen and (max-width: @small) {
8 | padding: 5px;
9 | width: 100%;
10 | }
11 | @media only screen and (min-width: @small) and (max-width: @large) {
12 | padding: 50px 50px;
13 | font-size: 22px;
14 | }
15 | @media only screen and (min-width: @large) {
16 | padding-top: 100px;
17 | font-size: 18px;
18 | width: 600px;
19 | }
20 |
21 |
22 | h2 {
23 | margin-bottom: 30px;
24 | }
25 |
26 | .btn {
27 | display: inline-block;
28 | width: auto;
29 | background-color: @accent;
30 | margin: 20px;
31 | &:hover {
32 | color: #FFF;
33 | border: 1px solid #000;
34 | }
35 | &:active {
36 | background-color: @dark-accent-2;
37 | color: #FFF;
38 | }
39 | }
40 |
41 | .btn[data-action="confirm"] {
42 | font-size: 36px;
43 | }
44 |
45 | .nav {
46 | margin-top: 100px;
47 | }
48 |
49 | #accept-travel {
50 | margin-top: 15px;
51 | }
52 |
53 | #travel-explaination {
54 | display: none;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/client/style/footer.less:
--------------------------------------------------------------------------------
1 | @import "global";
2 |
3 | @background: #424242;
4 | @background-dark: #232323;
5 |
6 | .footer {
7 | width: 100%;
8 | min-height: 60px;
9 | background-color: @background-dark;
10 | padding-top: 10px;
11 | display: -webkit-flex;
12 | display: -ms-flex;
13 | display: flex;
14 | flex-wrap: wrap;
15 | justify-content: center;
16 | text-align: center;
17 |
18 | div {
19 | width: 300px;
20 | }
21 |
22 | a {
23 | text-decoration: none;
24 | color: #FFF;
25 | }
26 |
27 | p {
28 | padding: 10px;
29 | }
30 |
31 | .social-media i {
32 | margin: 5px;
33 | }
34 |
35 | @media only screen and (max-width: @small) {
36 | font-size: @small_font;
37 | }
38 |
39 | @media only screen and (min-width: @small) and (max-width: @large) {
40 |
41 | }
42 |
43 | @media only screen and (min-width: @large) {
44 |
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/client/style/forgot.less:
--------------------------------------------------------------------------------
1 | @import "global";
2 |
3 | .forgot-container {
4 | text-align: center;
5 |
6 | .btn {
7 | background-color: @accent;
8 | border: 1px solid #000;
9 | margin-top: 50px;
10 | }
11 |
12 | .loading {
13 | display: none;
14 | margin-top: 50px;
15 | }
16 |
17 | }
--------------------------------------------------------------------------------
/client/style/forms.less:
--------------------------------------------------------------------------------
1 | @import "global";
2 |
3 | ._form-group {
4 | margin: 10px 0;
5 | width: 100%;
6 | }
7 |
8 | ._form-group label {
9 | font-size: 12px;
10 | font-weight: normal;
11 | font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
12 | opacity: 0;
13 | margin-bottom: 0;
14 | border-top-left-radius: 10px;
15 | border-top-right-radius: 10px;
16 | background-color: rgba(75 , 75, 75, 0.5);
17 | padding: 2px 10px;
18 | }
19 |
20 | ._form-group input[type="text"],
21 | ._form-group input[type="number"],
22 | ._form-group input[type="password"] {
23 | font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
24 | background-color: rgba(75 , 75, 75, 0.5);
25 | color: #FFFFFF;
26 | padding: 10px;
27 | border: none;
28 | border-bottom: solid 2px #c9c9c9;
29 | transition: border 0.3s;
30 | width: 100%;
31 | }
32 |
33 | ._form-group input[type="text"]:focus,
34 | ._form-group input[type="text"].focus,
35 | ._form-group input[type="number"]:focus,
36 | ._form-group input[type="number"].focus,
37 | ._form-group input[type="password"]:focus,
38 | ._form-group input[type="password"].focus {
39 | border-bottom: 2px solid @dark-accent-2;
40 | outline: none;
41 | }
42 |
43 | .has-form-error {
44 | -webkit-box-shadow: 0px 0px 50px 10px darken(@dark-accent-2, 10%);
45 | -moz-box-shadow: 0px 0px 50px 10px darken(@dark-accent-2, 10%);
46 | box-shadow: 0px 0px 50px 10px darken(@dark-accent-2, 10%);
47 | }
48 |
49 | ._checkbox {
50 | cursor: pointer;
51 | }
52 |
53 | ._checkbox input {
54 | margin-right: 5px;
55 | cursor: pointer;
56 | }
57 |
58 | ._form-group select {
59 | font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
60 | background-color: rgba(75 , 75, 75, 0.5);
61 | color: #FFFFFF;
62 | padding: 10px;
63 | border: none;
64 | width: 200px;
65 | }
66 |
67 |
68 | ._radio-group,
69 | ._checkbox-group {
70 | display: -webkit-flex;
71 | display: -ms-flex;
72 | display: flex;
73 | flex-wrap: wrap;
74 | justify-content: center;
75 |
76 | label {
77 | flex-basis: 50%;
78 | background-color: #FFF;
79 | color: #000;
80 | padding: 2px;
81 | font-weight: normal;
82 | cursor: pointer;
83 | text-align: center;
84 | vertical-align: middle;
85 | }
86 |
87 | label.active {
88 | background-color: @dark-accent;
89 | color: #FFF;
90 | }
91 |
92 | input[type="radio"],
93 | input[type="checkbox"] {
94 | display: none;
95 | }
96 |
97 | }
98 |
99 | ._button-group {
100 | width: 100%;
101 | text-align: center;
102 | }
103 |
--------------------------------------------------------------------------------
/client/style/global.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | height: 100%;
3 | width: 100%;
4 | background: #424242;
5 | color: #FFFFFF;
6 | /*padding-bottom: 100px;*/
7 | font-family: 'Open Sans', sans-serif;
8 | }
9 |
10 | .accent, a, a:hover, .btn-link, .btn-link:hover {
11 | color: #C03328;
12 | /*color: #e60000;*/
13 | }
14 |
15 | .list-plain {
16 | list-style-type: none;
17 | margin-left: -40px;
18 | }
19 |
20 | .faded-text {
21 | color: #343434;
22 | }
23 |
24 | .modal, input {
25 | color: #000000;
26 | }
27 |
28 | .fa-toggle-on {
29 | color: #11aa11;
30 | cursor: pointer;
31 | }
32 |
33 | .fa-toggle-off {
34 | color: #aa1111;
35 | cursor: pointer;
36 | }
37 |
38 | .datetimepicker {
39 | color: #343434;
40 | }
41 |
42 | .FourOhFour-box {
43 | text-align: center;
44 | font-size: 26px;
45 | }
46 |
--------------------------------------------------------------------------------
/client/style/global.less:
--------------------------------------------------------------------------------
1 | @accent: #C03328;
2 | @dark-accent: #C1261A;
3 | @dark-accent-2: #8c0000;
4 |
5 | @small: 480px;
6 | @small_font: 24px;
7 | @large: 960px;
8 |
--------------------------------------------------------------------------------
/client/style/jumbotron.less:
--------------------------------------------------------------------------------
1 | @import "global";
2 |
3 | .jumbotron-container {
4 | background: #FFFFFF;
5 | }
6 |
7 | .jumbotron {
8 | background: #FFFFFF;
9 | height: 200px;
10 | }
11 |
12 | .banner-logo {
13 | width: 200px;
14 | margin-top: 20px;
15 | }
16 |
17 | .announcements-panel {
18 | text-align: center;
19 | }
20 |
21 | .announcement {
22 | display: none;
23 | }
24 |
25 | .announcement.active {
26 | display: block;
27 | }
28 |
29 | .announce-box {
30 | h1 {
31 | color: #333;
32 | }
33 |
34 | p {
35 | color: #999;
36 | }
37 | }
38 |
39 | .next-announcement,
40 | .prev-announcement {
41 | &:hover {
42 | cursor: pointer;
43 | }
44 | color: #ddd;
45 | -webkit-user-select: none;
46 | -moz-user-select: none;
47 | -ms-user-select: none;
48 | }
49 |
--------------------------------------------------------------------------------
/client/style/login.css:
--------------------------------------------------------------------------------
1 | .login-panel {
2 | padding: 50px 20px;
3 | width: 600px;
4 | margin: 0px auto;
5 | }
6 |
7 | .login-panel-2 {
8 | width: 600px;
9 | margin: 0px auto;
10 | text-align: center;
11 | }
12 |
13 | .register-panel {
14 | padding: 30px 20px;
15 | width: 700px;
16 | margin: 0px auto;
17 | text-align: center;
18 | }
19 |
20 | .register-btn-start {
21 | width: 200px;
22 | padding: 10px;
23 | margin: 10px;
24 | }
25 |
26 | .register-panel-title {
27 | /*margin-bottom: -50px;*/
28 | text-align: center;
29 | }
30 |
31 | .checkbox-list {
32 | text-align: left;
33 | }
34 |
35 | .reg-page-hidden {
36 | display: none;
37 | }
38 |
39 | #reg-mentor-submit, #reg-volunteer-submit {
40 | margin-top: 50px;
41 | }
42 |
43 | .time-grid-box {
44 | height: 25px;
45 | width: 50px;
46 | border: 1px solid black;
47 | padding: 5px;
48 | margin: 5px;
49 | margin-right: 2px;
50 | float: left;
51 | text-align: center;
52 | cursor: pointer;
53 | -webkit-touch-callout: none;
54 | -webkit-user-select: none;
55 | -khtml-user-select: none;
56 | -moz-user-select: none;
57 | -ms-user-select: none;
58 | user-select: none;
59 | }
60 |
61 | .time-grid-box-selected {
62 | background: #00CC00;
63 | }
64 |
65 | .time-grid-date {
66 | clear: left;
67 | }
68 |
--------------------------------------------------------------------------------
/client/style/mentor.less:
--------------------------------------------------------------------------------
1 | @import "global";
2 |
3 | .mentor-request-form {
4 | width: 400px;
5 | text-align: center;
6 | margin: auto;
7 | }
8 |
9 | .mentor-request-form .form-error {
10 | display: none;
11 | }
12 |
13 | .no-mentors {
14 | margin: auto;
15 | text-align: center;
16 | margin-top: 30px;
17 | font-size: 18px;
18 | }
--------------------------------------------------------------------------------
/client/style/navbar.css:
--------------------------------------------------------------------------------
1 | .header {
2 | color: #FFFFFF;
3 | padding: 5px;
4 | margin-bottom: 15px;
5 | }
6 |
7 | .header-logo {
8 | width: 20%;
9 | }
10 |
11 | .nav-list {
12 | margin: 0 auto;
13 | text-align: center;
14 | padding: 1em 0;
15 | }
16 |
17 | .nav-button {
18 | display: inline;
19 | padding: 10px;
20 | font-size: 20px;
21 | width: 100px;
22 | cursor: pointer;
23 | }
24 |
25 | .nav-header {
26 | width: 50%;
27 | margin: auto;
28 | }
29 |
30 | .nav-header a {
31 | text-decoration: none;
32 | color: #FFFFFF;
33 | }
34 |
35 | .nav-header a:hover {
36 | color: #efefef;
37 | }
38 |
39 | .user-popup {
40 | display: none;
41 | position: absolute;
42 | padding: 10px;
43 | background: #dfdfdf;
44 | border-radius: 5px;
45 | width: 150px;
46 | }
47 |
48 | .user-popup-btn {
49 | width: 130px;
50 | margin-top: 5px;
51 | }
52 |
--------------------------------------------------------------------------------
/client/style/pre_event.less:
--------------------------------------------------------------------------------
1 | @import "global";
2 |
3 | .sign-up-container {
4 |
5 | .splash {
6 | background-image: url("./img/downtown.jpg");
7 | background-position: center;
8 | background-repeat: no-repeat;
9 | background-size: cover;
10 | padding: 100px;
11 | }
12 |
13 | .splash-text {
14 | padding: 30px;
15 | max-width: @large;
16 | margin: auto;
17 | background: rgb(0, 0, 0); /* fallback color */
18 | background: rgba(0, 0, 0, 0.7);
19 | border-radius: 10px;
20 | -webkit-box-shadow: 1px 2px 3px rgba(0,0,0,.5);
21 | -moz-box-shadow: 1px 2px 3px rgba(0,0,0,.5);
22 | box-shadow: 1px 2px 3px rgba(0,0,0,.5);
23 | }
24 |
25 | .splash-header {
26 | font-family: Tahoma, Geneva, sans-serif;
27 | font-size: 32px;
28 | text-align: center;
29 | color: @accent;
30 | }
31 |
32 | .splash-subheader {
33 | text-align: center;
34 | color: #acacac;
35 | }
36 |
37 | .splash-content {
38 | text-align: center;
39 | }
40 |
41 | .splash-nav {
42 | display: -webkit-flex;
43 | display: -ms-flex;
44 | display: flex;
45 | flex-wrap: wrap;
46 | align-items: center;
47 | div {
48 | cursor: pointer;
49 | &:hover {
50 | color: @dark-accent;
51 | }
52 | }
53 | }
54 |
55 | @media only screen and (max-width: @small) {
56 | .splash {
57 | padding: 100px 0;
58 | }
59 | .splash-text {
60 | margin: 0;
61 | text-align: center;
62 | font-size: @small_font;
63 | }
64 | .splash-nav {
65 | width: 100%;
66 | margin: 20px auto;
67 | div {
68 | flex-basis: 100%;
69 | }
70 | }
71 | }
72 |
73 | @media only screen and (min-width: @small) and (max-width: @large) {
74 | .splash-text {
75 | width: 100%;
76 | margin: auto;
77 | text-align: center;
78 | font-size: @small_font;
79 | background: rgb(0, 0, 0); /* fallback color */
80 | background: rgba(0, 0, 0, 0.7);
81 | border-radius: 10px;
82 | -webkit-box-shadow: 1px 2px 3px rgba(0,0,0,.5);
83 | -moz-box-shadow: 1px 2px 3px rgba(0,0,0,.5);
84 | box-shadow: 1px 2px 3px rgba(0,0,0,.5);
85 | }
86 | .splash-nav {
87 | width: 500px;
88 | margin: 20px auto;
89 | div {
90 | flex-basis: 33%;
91 | }
92 | }
93 | }
94 |
95 | @media only screen and (min-width: @large) {
96 | .splash-nav {
97 | width: 300px;
98 | margin: 20px auto;
99 | div {
100 | flex-basis: 33%;
101 | }
102 | }
103 | }
104 |
105 | }
106 |
107 |
108 | .goto-register-btn, .register-btn {
109 | color: #FFF;
110 | margin-top: 10px;
111 | background-color: @accent;
112 | }
113 |
114 | .register-btn {
115 | width: 120px;
116 | margin: 10px;
117 | }
118 |
119 | .register-btn:hover {
120 | background-color: @dark-accent-2;
121 | color: #FFF;
122 | }
123 |
124 | .register-btn[data-action="back"]:hover {
125 | background-color: @accent;
126 | }
127 |
128 | .splash-content .btn:hover, .login-btn:hover {
129 | background-color: @dark-accent;
130 | }
131 |
132 | .splash-login {
133 | display: none;
134 | margin: auto;
135 | max-width: 400px;
136 |
137 | #login-btn-group {
138 | text-align: center;
139 | }
140 | }
141 |
142 | /* -------------------------------------------------------------------------- */
143 |
144 | .status-what-container {
145 | width: 100%;
146 |
147 | .status-what {
148 | padding-top: 50px;
149 |
150 | .more-questions {
151 | text-align: center;
152 | font-size: 18px;
153 | }
154 |
155 | .blurb {
156 | div {
157 | display: -webkit-flex;
158 | display: -ms-flex;
159 | display: flex;
160 | flex-wrap: wrap;
161 | align-items: center;
162 | }
163 |
164 | .elem-1 i {
165 | margin: auto;
166 | }
167 | }
168 |
169 | }
170 |
171 |
172 | @media only screen and (max-width: @small) {
173 | .blurb {
174 | width: 100%;
175 | padding: 10px;
176 | margin-bottom: 50px;
177 |
178 | .elem-1, .elem-2, { flex-basis: 100%; }
179 | }
180 | }
181 |
182 | @media only screen and (min-width: @small) and (max-width: @large) {
183 | .blurb {
184 | width: @small;
185 | margin: auto;
186 | margin-bottom: 50px;
187 |
188 | .elem-1 { flex-basis: 22%; }
189 | .elem-2 { flex-basis: 78%; }
190 | }
191 | }
192 |
193 | @media only screen and (min-width: @large) {
194 | .blurb {
195 | width: 700px;
196 | margin: auto;
197 | margin-bottom: 50px;
198 |
199 | .elem-1 { flex-basis: 15%; }
200 | .elem-2 { flex-basis: 85%; }
201 | }
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/client/style/preregister.less:
--------------------------------------------------------------------------------
1 | @import "global";
2 |
3 | .content#preregister {
4 |
5 | h2 {
6 | color: @accent;
7 | text-align: center;
8 | margin-bottom: 50px;
9 | }
10 |
11 | form {
12 | text-align: center;
13 | input {
14 | width: 325px;
15 | }
16 | button {
17 | margin-top: 50px;
18 | font-family: 'Lucida Console', Monaco, monospace;
19 | }
20 | }
21 |
22 | @media only screen and (max-width: @small) {
23 | font-size: 32px;
24 | padding: 5px;
25 | }
26 | @media only screen and (min-width: @small) and (max-width: @large) {
27 | font-size: 26px;
28 | padding: 10px;
29 | }
30 | @media only screen and (min-width: @large) {
31 | width: 70%;
32 | margin: auto;
33 | p {
34 | width: 600px;
35 | margin: auto;
36 | }
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/client/style/register.less:
--------------------------------------------------------------------------------
1 | @import "global";
2 |
3 | .register {
4 |
5 | .register-landing {
6 | text-align: center;
7 | margin-top: 100px;
8 | }
9 |
10 | margin: auto;
11 | width: 95%;
12 |
13 | .group {
14 | margin: 30px 0;
15 | }
16 |
17 | .twitter-typeahead {
18 | width: 100%;
19 | }
20 |
21 | .school-selection, .zip-code, .international-loc {
22 | display: none;
23 | }
24 |
25 | div#tshirt-size label {
26 | flex-basis: 20%;
27 | }
28 |
29 | div#diet-selection label,
30 | div#gender-selection label,
31 | div#language-selection label,
32 | div#framework-selection label,
33 | div#api-selection label {
34 | flex-basis: 25%;
35 | }
36 |
37 | div#interest-areas label,
38 | div#race-selection label {
39 | flex-basis: 33%;
40 | }
41 |
42 | @media only screen and (max-width: @small) {
43 | font-size: @small_font;
44 | div#travel-origin-type label,
45 | div#tshirt-size label,
46 | div#diet-selection label,
47 | div#interest-areas label,
48 | div#why-selection label,
49 | div#gender-selection label,
50 | div#race-selection label,
51 | div#language-selection label,
52 | div#framework-selection label,
53 | div#api-selection label {
54 | flex-basis: 100%;
55 | font-size: @small_font;
56 | }
57 | .register-landing {
58 | margin-top: 30px;
59 | }
60 | .register-btn,
61 | #register-btn {
62 | font-size: @small_font;
63 | width: 200px;
64 | }
65 | }
66 | @media only screen and (min-width: @small) and (max-width: @large) {
67 | width: @small;
68 | }
69 | @media only screen and (min-width: @large) {
70 | width: 600px;
71 | }
72 |
73 | .btn-register {
74 | color: #FFF;
75 | background-color: @accent;
76 | width: 120px;
77 | margin: 20px 0 40px 0;
78 |
79 | &:hover {
80 | background-color: @dark-accent-2;
81 | }
82 | }
83 |
84 | }
85 |
86 | .register .form-error {
87 | margin-top: 10px;
88 | display: none;
89 | }
90 |
91 | .register-landing, .register-complete {
92 | display: none;
93 | }
94 |
95 | .register-landing .music {
96 | display: none;
97 | }
98 |
99 | .language-selection, .framework-selection, .api-selection {
100 | text-align: left;
101 | padding-top: 15px;
102 | margin-left: 15%;
103 |
104 | label {
105 | width: 200px;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/client/style/set-password.less:
--------------------------------------------------------------------------------
1 | @import "global";
2 |
3 | .set-password-container {
4 | text-align: center;
5 |
6 | .btn {
7 | background-color: @accent;
8 | border: 1px solid #000;
9 | margin-top: 50px;
10 | }
11 |
12 | }
--------------------------------------------------------------------------------
/client/style/typeahead.less:
--------------------------------------------------------------------------------
1 | @import "global";
2 |
3 | /* basic typeahead styles */
4 |
5 | .typeahead,
6 | .tt-query,
7 | .tt-hint {
8 | width: 325px;
9 | padding: 8px 12px;
10 | line-height: 30px;
11 | border: 2px solid #ccc;
12 | -webkit-border-radius: 8px;
13 | -moz-border-radius: 8px;
14 | border-radius: 8px;
15 | outline: none;
16 | }
17 |
18 | .typeahead {
19 | background-color: #fff;
20 | }
21 |
22 | .typeahead:focus {
23 | border: 2px solid #0097cf;
24 | }
25 |
26 | .tt-query {
27 | -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
28 | -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
29 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
30 | }
31 |
32 | .tt-hint {
33 | color: #999
34 | }
35 |
36 | .tt-menu {
37 | width: 325px;
38 | margin: 4px 0;
39 | padding: 8px 0;
40 | background-color: #fff;
41 | border: 1px solid #ccc;
42 | border: 1px solid rgba(0, 0, 0, 0.2);
43 | -webkit-border-radius: 8px;
44 | -moz-border-radius: 8px;
45 | border-radius: 8px;
46 | -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
47 | -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
48 | box-shadow: 0 5px 10px rgba(0,0,0,.2);
49 | }
50 |
51 | .tt-suggestion {
52 | color: @accent;
53 | padding: 3px 20px;
54 | font-size: 18px;
55 | line-height: 24px;
56 | }
57 |
58 | .tt-suggestion:hover {
59 | cursor: pointer;
60 | color: #fff;
61 | background-color: #0097cf;
62 | }
63 |
64 | .tt-suggestion.tt-cursor {
65 | color: #fff;
66 | background-color: #0097cf;
67 |
68 | }
69 |
70 | .tt-suggestion p {
71 | margin: 0;
72 | }
--------------------------------------------------------------------------------
/client/style/user.css:
--------------------------------------------------------------------------------
1 | /* Sidebar ------------------------------------------------------------------ */
2 | .user-sidebar {
3 |
4 | }
5 |
6 | .user-nav-list {
7 | list-style-type: none;
8 | }
9 |
10 | .user-sidebar-btn {
11 | cursor: pointer;
12 | font-size: 16px;
13 | padding-top: 5px;
14 | padding-bottom: 5px;
15 | margin-left: -20px;
16 | margin-top: 5px;
17 | margin-bottom: 5px;
18 | }
19 |
20 | .user-sidebar-btn:hover {
21 | color: #d3d3d3;
22 | }
23 |
24 |
25 | /* Content ------------------------------------------------------------------ */
26 | .user-content {
27 |
28 | }
29 |
30 | .user-section-title {
31 | border-bottom: 3px solid #FFFFFF;
32 | margin-bottom: 30px;
33 | margin-top: -20px;
34 | }
35 |
36 | .user-table {
37 | margin-bottom: 20px;
38 | }
39 |
40 | .user-table-row {
41 | margin-top: 10px;
42 | }
43 |
44 | .user-table-label {
45 | font-weight: bold;
46 | }
47 |
48 | /* Hacker Dashboard --------------------------------------------------------- */
49 |
50 | #user-hacker-leave-repo {
51 | margin-top: 10px;
52 | margin-bottom: 10px;
53 | }
54 |
55 | #user-hacker .pre-event-warning {
56 | font-size: 18px;
57 | width: 100%;
58 | text-align: center;
59 | margin-top: 20px;
60 | }
61 |
62 | .repo-details-header {
63 | font-size: 24px;
64 | margin-left: 5px;
65 | }
66 |
67 | .repo-details-header-row {
68 | margin-bottom: 10px;
69 | margin-top: 20px;
70 | }
71 |
72 | .repo-details-box {
73 | text-align: center;
74 | margin-bottom: 20px;
75 | }
76 |
77 | .repo-details-box .btn {
78 | width: 80%;
79 | }
80 |
81 | .repo-details {
82 | font-size: 24px;
83 | }
84 |
85 | .repo-details-subtext {
86 | margin-top: 10px;
87 | }
88 |
89 | .contributor {
90 | margin-left: 10px;
91 | font-size: 18px;
92 | }
93 |
94 | #user-hacker-leave-repo, #user-hacker-leave-repo {
95 | width: 100%;
96 | }
97 |
98 | /* Mentor ------------------------------------------------------------------- */
99 |
100 | .skill-tag {
101 | margin-top: 10px;
102 | }
103 |
104 | .mentor-tag-list {
105 | margin-bottom: 20px;
106 | }
107 |
108 | /* -------------------------------------------------------------------------- */
109 |
110 | #selectDatabase {
111 | width: 300px;
112 | }
113 |
114 | #user-profile-edit-btn {
115 | margin-bottom: -20px;
116 | float: right;
117 | }
118 |
119 | .user-settings-table {
120 | margin-top: 20px;
121 | margin-bottom: 20px;
122 | font-size: 18px;
123 | }
124 |
125 | #user-devPost-edit {
126 | font-size: 14px;
127 | float: right;
128 | }
129 |
130 | .alert-num-remove {
131 | cursor: pointer;
132 | }
133 |
134 | .db_page {
135 | margin-top: 20px;
136 | }
137 |
138 | .next-btn, .prev-btn {
139 | width: 100px;
140 | }
141 |
142 | .table-sort {
143 | cursor: pointer;
144 | }
145 |
--------------------------------------------------------------------------------
/client/templates/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | This is not the screw you are looking for.
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/client/templates/anonReportForm.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/client/templates/check-in/check_in.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{> Template.dynamic template = checkin_page }}
5 |
6 | Return to Check In
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{#if validated}}
15 |
16 |
Welcome to HackRPI 2016
17 |
18 |
19 |
20 |
21 | Check In
22 |
23 |
24 | Register
25 |
26 |
27 | {{ else }}
28 |
29 |
Enter Event Code
30 |
31 |
32 | Submit
33 |
34 |
35 | {{/if}}
36 |
37 |
38 |
39 |
40 |
41 |
42 |
Glad you could make it!
43 |
You're all set.
44 |
45 | Check In Another
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/client/templates/commits.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{#each messages}}
9 |
44 | {{/each}}
45 |
46 |
47 |
48 |
49 |
50 |
51 | {{test}}
52 |
53 |
54 |
--------------------------------------------------------------------------------
/client/templates/confirm.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{#if currentUser}}
4 | {{#if accepted}}
5 | {{#if confirmed}}
6 |
7 | You're all set to come to HackRPI! Check out the event schedule and other goodies
8 | on our main website, hackrpi.com .
9 |
10 | {{#if is_on_bus}}
11 |
12 | To find out the departure time and location along with the bus captain information,
13 | please see this document.
14 |
15 | {{/if}}
16 |
17 | {{else}}
18 |
Hooray! You're officially invited to HackRPI!
19 |
20 | {{#if travel}}
21 |
22 | We have arranged for you to travel on the {{ travel }} .
23 | It will be of no cost to you. We'll be in touch with the details shortly.
24 |
25 |
26 |
27 | Accept Travel
28 |
29 | Reject Travel
30 |
31 |
32 | Please Explain Your Travel
33 |
34 |
36 |
37 | {{/if}}
38 |
42 |
43 | Confirm My Spot
44 |
45 |
46 |
47 | I actually don't like fun.
48 |
49 | {{/if}}
50 |
51 | {{else}}
52 |
You're still on the waiting list.
53 |
54 | The waiting list for HackRPI is FIFO. We will
55 | let you know as soon as possible when a spot opens
56 | up for you. Hang in there!
57 |
58 | {{/if}}
59 |
60 | {{else}}
61 |
Please login to confirm your spot.
62 | {{/if}}
63 |
64 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/client/templates/footer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/client/templates/forgot.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Email
7 |
8 |
9 |
10 | Send Password Reset Email
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/client/templates/info.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
Important Event Information
8 |
9 |
12 |
13 |
18 |
19 |
20 | Welcome to the Status Board! This is where you will receive event updates, find mentors,
21 | and watch commits from all of the projects being developed at HackRPI. More information
22 | about HackRPI can be found on the HackRPI homepage .
23 |
24 |
25 |
Important Links
26 |
27 |
32 |
33 |
Anonymous Reporting
34 |
If you encounter any problems during the event that you would like to
35 | bring to our attention anonymously, please don't hesitate to do so.
36 |
37 | File Anonymous Report
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
About Status Board
46 |
Status Board is developed with Meteor by HackRPI Organizers:
47 |
51 |
52 |
53 |
Status Board is proudly open source and hosted on Github .
54 | If you have comments, suggestions, or bug reports let us know!
55 | (Specifically, Matt Poegel , if you can find him.)
56 |
57 |
58 |
59 |
60 |
61 |
62 | {{> anonReportForm }}
63 |
64 |
65 |
--------------------------------------------------------------------------------
/client/templates/jumbotron.html:
--------------------------------------------------------------------------------
1 |
2 | {{#if showJumbo}}
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
18 |
19 |
20 |
21 |
22 | {{#each announcements}}
23 |
25 |
{{header}}
26 |
{{text}}
27 |
28 | {{/each}}
29 |
30 |
31 |
32 |
33 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | {{/if}}
47 |
48 |
--------------------------------------------------------------------------------
/client/templates/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 |
18 |
23 |
24 |
25 |
26 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/client/templates/mentor.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
Request a Mentor
7 |
Do you need help with your project? Just fill out this form and the
8 | next available mentor will be with you as soon as possible!
9 |
The issue tags are a compiled list of all the skills of all the
10 | currently active mentors. If what you are looking for is not on the
11 | list, try something similiar, or wait for a mentor to become active.
12 | Otherwise, wonder by our sponsor tables and ask for help.
13 |
14 |
15 |
16 | {{#if mentorsAvailable}}
17 |
47 | {{else}}
48 |
49 |
Unfortunately, there are no active mentors right now.
50 |
51 | {{/if}}
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/client/templates/navbar.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
17 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/client/templates/popup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
{{ body }}
12 | {{#if pre}}
13 |
{{ pre }}
14 | {{/if}}
15 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/client/templates/pre-event/preregister.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
HackRPI 2016
6 |
7 |
8 | Are you excited for HackRPI 2016 too? Join the club! And by "club", we
9 | mean mailing list. Let us know your name, email, and school, and you will
10 | be among the first notified for when registration opens for real. And by
11 | letting us know your school, you can help us plan buses! Note: Please
12 | do not abbreviate the name of your school.
13 |
14 |
15 |
16 |
17 |
18 |
19 | Name
20 |
21 |
22 |
23 | Email
24 |
25 |
26 |
27 | School
28 |
30 |
31 |
32 |
33 | hype_train.board(self);
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/client/templates/pre-event/sign_up.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
12 |
13 |
14 | Register
15 |
16 |
17 |
18 | {{ #if currentUser }}
19 |
20 | Profile
21 |
22 | {{ else }}
23 |
24 | Login
25 |
26 | {{ /if }}
27 |
28 | HackRPI
29 |
30 |
31 | Status What?
32 |
33 |
34 |
35 |
36 |
37 |
38 | Email
39 |
40 |
41 |
42 | Password
43 |
44 |
45 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
View Commits from Everyone at HackRPI
62 |
63 |
64 |
65 |
66 |
67 |
68 | By allowing participants to add their Github projects to the
69 | Status Board, everyone at the event can watch all the other
70 | projects as they are developed, creating a stronger hackathon
71 | community through data and statistics.
72 |
73 |
74 |
75 |
76 |
77 |
78 |
Match with Mentors
79 |
80 |
81 |
82 |
83 |
84 |
85 | For when you inevitably get stuck on your project, we have mentors
86 | ready to assist you! The Status Board makes it really simple to
87 | request a mentor to your location. Mentors are alerted via text
88 | message of their assignment and can communicate with the
89 | Status Board using just text messages.
90 |
91 |
92 |
93 |
94 |
95 |
96 |
Get Event Updates and Announcements
97 |
98 |
99 |
100 |
101 |
102 |
103 | Stay updated with event announcements! The Status Board will
104 | be the primary method of broadcasting updates to everyone
105 | at the event.
106 |
107 |
108 |
109 |
110 |
111 |
112 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | {{ > footer }}
126 |
127 |
128 |
--------------------------------------------------------------------------------
/client/templates/registration/hacker.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Hacker Registration
5 |
6 |
46 |
47 |
67 |
68 |
83 |
84 |
101 |
102 |
119 |
120 |
133 |
134 |
144 |
145 |
163 |
164 |
184 |
185 |
186 |
187 |
188 | We participate in Major League Hacking (MLH) as a MLH Member Event. You authorize us to share
189 | certain application/registration information for event administration, ranking, MLH
190 | administration, pre and post-event informational e-mails, and occasional messages about
191 | hackathons in line with the MLH Privacy Policy .
192 |
193 |
194 |
199 |
200 |
201 |
202 |
--------------------------------------------------------------------------------
/client/templates/registration/mentor.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Mentor Registration
5 |
6 |
37 |
38 |
39 |
Select your languages.
40 |
41 | {{#each languages}}
42 |
43 | {{ this }}
44 | {{/each}}
45 |
46 |
47 |
48 |
49 |
Select your frameworks.
50 |
51 | {{#each frameworks}}
52 |
53 | {{ this }}
54 | {{/each}}
55 |
56 |
57 |
58 |
59 |
Select your APIs
60 |
61 | {{#each apis}}
62 |
63 | {{ this }}
64 | {{/each}}
65 |
66 |
67 |
68 |
69 |
70 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/client/templates/registration/register.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{> Template.dynamic template=register_page }}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | I want to be...
17 |
18 |
20 | a hacker.
21 |
22 |
24 | a mentor.
25 |
26 |
27 | a volunteer.
28 |
29 |
31 | the very best.
32 |
33 |
38 |
39 |
40 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
Volunteer
53 |
54 |
55 |
56 |
57 |
58 |
68 |
74 |
80 |
86 |
92 |
1 of 2
93 |
Next
94 |
95 |
96 |
97 | Select your availability
98 |
99 |
105 |
2 of 2
106 |
Prev
107 |
108 | Submit
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
Registration Successful!
120 |
121 | You have successfully registered for HackRPI 2016.
122 | You should be receiving a confirmation email shortly.
123 | See you soon!
124 |
125 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/client/templates/registration/volunteer.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hack-rpi/Status-Board/5e75d79da61c3ea2064a626cfb7c733a5981a276/client/templates/registration/volunteer.html
--------------------------------------------------------------------------------
/client/templates/set-password.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | New Password
7 |
8 |
9 |
10 | Confirm New Password
11 |
12 |
13 |
14 | Set New Password
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/client/templates/user/announce.html:
--------------------------------------------------------------------------------
1 |
2 | {{#if hasAccess}}
3 |
4 |
5 |
Announcements Controls
6 |
7 |
8 |
9 |
10 |
11 |
12 |
19 |
27 |
38 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | {{else}}
50 | Unauthorized Access
51 | {{/if}}
52 |
53 |
--------------------------------------------------------------------------------
/client/templates/user/mentor.html:
--------------------------------------------------------------------------------
1 |
2 | {{#if isInRole 'mentor'}}
3 |
4 |
5 |
6 |
7 |
8 |
9 |
Mentoring Status
10 | {{#if checked_in}}
11 | {{#if active}}
12 |
13 | Suspend
14 |
15 | {{else}}
16 |
17 | Activate
18 |
19 | {{/if}}
20 | {{else}}
21 |
22 | You have not checked in yet. You cannot be added to the active
23 | mentor queue until you check in.
24 |
25 | {{/if}}
26 |
27 |
28 |
29 |
30 |
31 |
Current Assignment
32 | {{#if assignment}}
33 |
34 | {{#with assignment}}
35 | Mentee {{ name }}
36 | Tag {{ tag }}
37 | Location {{ loc }}
38 | {{/with}}
39 |
40 |
42 | Complete
43 |
44 |
46 | Waive
47 |
48 | {{else}}
49 |
50 | You do not currently have an assignment.
51 |
52 | {{/if}}
53 |
54 |
55 |
56 |
57 |
58 |
Skills
59 | {{#if editSkills}}
60 |
101 |
102 |
103 |
105 | Save Changes
106 |
107 |
108 |
109 | {{else}}
110 |
111 |
112 | {{#each skills}}
113 |
114 | {{ this }}
115 | {{/each}}
116 |
117 |
118 | {{/if}}
119 |
121 | Edit Skills
122 |
123 |
124 |
125 |
126 |
127 |
128 |
History
129 |
130 |
131 | Name
132 | Tag
133 | Location
134 | Time Completed
135 |
136 |
137 | {{#each history}}
138 |
139 | {{name}}
140 | {{tag}}
141 | {{loc}}
142 | {{time}}
143 |
144 | {{/each}}
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | {{else}}
154 | Unauthorized Access
155 | {{/if}}
156 |
157 |
--------------------------------------------------------------------------------
/client/templates/user/profile.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ name }} ({{ email }})
5 |
6 |
7 |
8 |
9 | {{#if editActive}}
10 |
11 |
17 |
23 |
29 |
35 |
41 |
47 | {{#if international}}
48 |
54 | {{else}}
55 |
61 | {{/if}}
62 |
76 |
82 |
88 |
89 |
97 |
98 |
99 | {{else}}
100 |
101 | {{#if isInRole 'hacker'}}
102 | {{#if accepted}}
103 | {{#if not_confirmed}}
104 | You have been accepted to HackRPI 2016!
105 | Confirm your spot!
106 | {{/if}}
107 | {{else}}
108 | You are still on the waiting list. The waiting list for HackRPI 2016 is FIFO.
109 | We will let you know as soon as possible when a spot opens up for you.
110 | Hang in there!
111 | {{/if}}
112 | {{/if}}
113 |
114 |
115 |
116 |
Name
117 |
{{ name }}
118 |
119 |
120 |
Affiliation
121 |
{{ affiliation }}
122 |
123 |
124 |
Phone Number
125 |
{{ phone }}
126 |
127 |
128 |
Room/Location
129 |
{{ location }}
130 |
131 |
132 |
School
133 |
{{ school }}
134 |
135 |
136 |
Travel Method
137 |
{{ travel_method }}
138 |
139 | {{#if international}}
140 |
141 |
City, Country
142 |
{{ city_country }}
143 |
144 | {{else}}
145 |
146 |
Traveling From Zipcode
147 |
{{ zipcode }}
148 |
149 | {{/if}}
150 |
151 |
Dietary Restrictions
152 |
{{ diet }}
153 |
154 |
155 |
Other Dietary Restrictions
156 |
{{ special_diet }}
157 |
158 |
159 |
Resume
160 |
161 | {{#if resume}}
162 | Resume Uploaded
163 | {{else}}
164 | No Resume Uploaded
165 | {{/if}}
166 |
167 |
168 |
169 | {{/if}}
170 |
171 |
172 |
--------------------------------------------------------------------------------
/client/templates/user/server_settings.html:
--------------------------------------------------------------------------------
1 |
2 | {{#if isInRole 'admin'}}
3 |
4 |
5 |
Server Settings
6 |
7 |
8 |
9 |
10 |
Allow Account Creation
11 |
12 | {{#if allowAccountCreation}}
13 |
14 | {{else}}
15 |
16 | {{/if}}
17 |
18 |
19 |
20 |
21 |
Activate Mentoring System
22 |
23 | {{#if mentoringSystemStatus}}
24 |
25 | {{else}}
26 |
27 | {{/if}}
28 |
29 |
30 |
31 |
32 |
Alert Numbers
33 |
34 |
35 | {{#each alertNumbers}}
36 | {{this}}
37 | ×
38 | {{/each}}
39 |
40 |
41 |
Add
42 |
43 |
44 |
45 |
46 |
47 | Event Stage
48 |
49 |
65 |
66 |
67 |
68 |
69 | {{else}}
70 | Unauthorized Access
71 | {{/if}}
72 |
73 |
--------------------------------------------------------------------------------
/client/templates/user/user.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{#if currentUser}}
8 |
9 |
57 |
58 |
59 |
60 |
61 | {{> Template.dynamic template=user_page}}
62 |
63 |
64 | {{else}}
65 |
66 |
Please login to view your profile.
67 |
68 | {{/if}}
69 |
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/client/templates/user/volunteer.html:
--------------------------------------------------------------------------------
1 |
2 | {{#if isInRole 'volunteer'}}
3 |
4 |
Volunteer Controls
5 |
6 |
7 | {{else}}
8 | Unauthorized Access
9 | {{/if}}
10 |
11 |
--------------------------------------------------------------------------------
/client/templates/welcome.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/config/env.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | export MONGO_URL=""
4 | export ROOT_URL="localhost:3000"
5 | export METEOR_SETTINGS="$(cat config/settings.json)"
6 |
--------------------------------------------------------------------------------
/config/meteor.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | sudo apt-get update
3 | sudo apt-get install -y curl
4 | sudo apt-get install -y git
5 | curl https://install.meteor.com | sudo sh
6 |
--------------------------------------------------------------------------------
/config/settings.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "public": {
4 | "event_state": "",
5 | "event_start": "",
6 | "event_end": "",
7 |
8 | "languages": [],
9 | "frameworks": [],
10 | "apis": [],
11 | "buses": [],
12 | "diet": []
13 | },
14 |
15 | "root_url": "",
16 |
17 | "mail_url": "",
18 |
19 | "default_admin_username": "",
20 | "default_admin_password": "",
21 |
22 | "github_clientId": "",
23 | "github_secret": "",
24 |
25 | "twilio_SID": "",
26 | "twilio_token": "",
27 | "twilio_from_num": "",
28 |
29 | "kadira": {
30 | "appId": "",
31 | "appSecret": ""
32 | },
33 |
34 | "secret_key": "",
35 |
36 | "checkin_code": ""
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/lib/collections.js:
--------------------------------------------------------------------------------
1 | Announcements = new Mongo.Collection("Announcements");
2 | AnonReports = new Mongo.Collection('AnonReports');
3 | AnonUserData = new Mongo.Collection('AnonUserData');
4 | CommitMessages = new Mongo.Collection("CommitMessages");
5 | MentorQueue = new Mongo.Collection("MentorQueue");
6 | PreRegistration = new Mongo.Collection('PreRegistration');
7 | RepositoryList = new Mongo.Collection("RepositoryList");
8 | USColleges = new Mongo.Collection('USColleges');
9 |
--------------------------------------------------------------------------------
/lib/languages.js:
--------------------------------------------------------------------------------
1 | languageColors = {
2 | "Prolog": "#74283c",
3 | "J": "#9EEDFF",
4 | "Erlang": "#B83998",
5 | "edn": "#db5855",
6 | "Turing": "#45f715",
7 | "LookML": "#652B81",
8 | "E": "#ccce35",
9 | "AMPL": "#E6EFBB",
10 | "Component Pascal": "#b0ce4e",
11 | "Groovy": "#e69f56",
12 | "NetLogo": "#ff6375",
13 | "Brainfuck": "#2F2530",
14 | "LSL": "#3d9970",
15 | "xBase": "#403a40",
16 | "ColdFusion": "#ed2cd6",
17 | "Elm": "#60B5CC",
18 | "OCaml": "#3be133",
19 | "KRL": "#28431f",
20 | "D": "#fcd46d",
21 | "Papyrus": "#6600cc",
22 | "Shen": "#120F14",
23 | "Gosu": "#82937f",
24 | "Objective-C++": "#6866fb",
25 | "AutoIt": "#1C3552",
26 | "Objective-J": "#ff0c5a",
27 | "wisp": "#7582D1",
28 | "eC": "#913960",
29 | "Java": "#b07219",
30 | "ANTLR": "#9DC3FF",
31 | "Smalltalk": "#596706",
32 | "Kotlin": "#EA4DFA",
33 | "IDL": "#a3522f",
34 | "C": "#555555",
35 | "Pike": "#005390",
36 | "RAML": "#77d9fb",
37 | "Dylan": "#6c616e",
38 | "Red": "#ee0000",
39 | "PHP": "#4F5D95",
40 | "PAWN": "#dbb284",
41 | "Rebol": "#358a5b",
42 | "Ioke": "#078193",
43 | "Slash": "#007eff",
44 | "Agda": "#315665",
45 | "AutoHotkey": "#6594b9",
46 | "Harbour": "#0e60e3",
47 | "Squirrel": "#800000",
48 | "Cirru": "#ccccff",
49 | "Fantom": "#dbded5",
50 | "Eagle": "#814C05",
51 | "HTML": "#e44b23",
52 | "Nu": "#c9df40",
53 | "PureScript": "#1D222D",
54 | "ABAP": "#E8274B",
55 | "Dogescript": "#cca760",
56 | "Mirah": "#c7a938",
57 | "Pan": "#cc0000",
58 | "Nit": "#009917",
59 | "JavaScript": "#f1e05a",
60 | "JFlex": "#DBCA00",
61 | "NewLisp": "#87AED7",
62 | "Factor": "#636746",
63 | "Alloy": "#cc5c24",
64 | "SQF": "#3F3F3F",
65 | "Assembly": "#6E4C13",
66 | "SourcePawn": "#5c7611",
67 | "Handlebars": "#01a9d6",
68 | "Puppet": "#332A77",
69 | "FLUX": "#88ccff",
70 | "Mercury": "#ff2b2b",
71 | "Isabelle": "#FEFE00",
72 | "VimL": "#199f4b",
73 | "QML": "#44a51c",
74 | "Lua": "#000080",
75 | "DM": "#447265",
76 | "PigLatin": "#fcd7de",
77 | "C++": "#f34b7d",
78 | "ECL": "#8a1267",
79 | "Lasso": "#999999",
80 | "CoffeeScript": "#244776",
81 | "PogoScript": "#d80074",
82 | "APL": "#5A8164",
83 | "Self": "#0579aa",
84 | "SystemVerilog": "#DAE1C2",
85 | "Slim": "#ff8f77",
86 | "Perl": "#0298c3",
87 | "Clojure": "#db5855",
88 | "Forth": "#341708",
89 | "TeX": "#3D6117",
90 | "UnrealScript": "#a54c4d",
91 | "Clarion": "#db901e",
92 | "VHDL": "#adb2cb",
93 | "Swift": "#ffac45",
94 | "Scheme": "#1e4aec",
95 | "SAS": "#B34936",
96 | "Nimrod": "#37775b",
97 | "Io": "#a9188d",
98 | "LOLCODE": "#cc9900",
99 | "Arduino": "#bd79d1",
100 | "F#": "#b845fc",
101 | "nesC": "#94B0C7",
102 | "Max": "#c4a79c",
103 | "Parrot": "#f3ca0a",
104 | "R": "#198ce7",
105 | "Grammatical Framework": "#79aa7a",
106 | "CSS": "#563d7c",
107 | "Haskell": "#29b544",
108 | "Ruby": "#701516",
109 | "Rust": "#dea584",
110 | "Boo": "#d4bec1",
111 | "Pure Data": "#91de79",
112 | "Rouge": "#cc0088",
113 | "Opal": "#f7ede0",
114 | "Volt": "#1F1F1F",
115 | "TypeScript": "#2b7489",
116 | "ActionScript": "#882B0F",
117 | "NetLinx+ERB": "#747faa",
118 | "AGS Script": "#B9D9FF",
119 | "ATS": "#1ac620",
120 | "Go": "#375eab",
121 | "Game Maker Language": "#8fb200",
122 | "Dart": "#00B4AB",
123 | "Shell": "#89e051",
124 | "Nix": "#7e7eff",
125 | "Vala": "#fbe5cd",
126 | "Diff": "#88dddd",
127 | "Golo": "#88562A",
128 | "Scala": "#7dd3b0",
129 | "LiveScript": "#499886",
130 | "Ada": "#02f88c",
131 | "Latte": "#A8FF97",
132 | "SuperCollider": "#46390b",
133 | "Fancy": "#7b9db4",
134 | "Common Lisp": "#3fb68b",
135 | "Mask": "#f97732",
136 | "Propeller Spin": "#7fa2a7",
137 | "MTML": "#b7e1f4",
138 | "ooc": "#b0b77e",
139 | "Tcl": "#e4cc98",
140 | "Haxe": "#f7941e",
141 | "NetLinx": "#0aa0ff",
142 | "LFE": "#004200",
143 | "Oz": "#fab738",
144 | "Gnuplot": "#f0a9f0",
145 | "Julia": "#a270ba",
146 | "Chapel": "#8dc63f",
147 | "Clean": "#3F85AF",
148 | "Frege": "#00cafe",
149 | "Omgrofl": "#cabbff",
150 | "Processing": "#0096D8",
151 | "Oxygene": "#cdd0e3",
152 | "Python": "#3572A5",
153 | "Glyph": "#e4cc98",
154 | "Perl6": "#0000fb",
155 | "Racket": "#22228f",
156 | "Eiffel": "#946d57",
157 | "Web Ontology Language": "#9cc9dd",
158 | "Pascal": "#b0ce4e",
159 | "Emacs Lisp": "#c065db",
160 | "Zephir": "#118f9e",
161 | "EmberScript": "#FFF4F3",
162 | "C#": "#178600",
163 | "XC": "#99DA07",
164 | "Standard ML": "#dc566d",
165 | "Verilog": "#b2b7f8",
166 | "SaltStack": "#646464",
167 | "ASP": "#6a40fd",
168 | "Elixir": "#6e4a7e",
169 | "Unified Parallel C": "#4e3617",
170 | "XQuery": "#5232e7",
171 | "Makefile": "#427819",
172 | "Arc": "#aa2afe",
173 | "Crystal": "#776791",
174 | "Matlab": "#bb92ac",
175 | "PureBasic": "#5a6986",
176 | "ColdFusion CFC": "#ed2cd6",
177 | "FORTRAN": "#4d41b1",
178 | "Hy": "#7790B2",
179 | "AspectJ": "#a957b0",
180 | "BlitzMax": "#cd6400",
181 | "Objective-C": "#438eff",
182 | "Nemerle": "#3d3c6e",
183 | "Ragel in Ruby Host": "#e17600",
184 | "Visual Basic": "#945db7"
185 | }
186 |
--------------------------------------------------------------------------------
/lib/methods.js:
--------------------------------------------------------------------------------
1 | Meteor.methods({
2 | validateDate: function(dt) {
3 | // if a commit has a date in the future compared to the server time, then
4 | // assign it the server time
5 | var now = new Date();
6 | now.setHours( now.getHours() + 5 ); // UTC
7 | if (dt > now) {
8 | dt = now;
9 | }
10 | return dt;
11 | },
12 |
13 | formatDateTime: function(dt) {
14 | var year = parseInt(dt.substr(0,4),10);
15 | var month = parseInt(dt.substr(5,2),10);
16 | var day = parseInt(dt.substr(8,2),10);
17 | var hour = parseInt(dt.substr(11,2),10);
18 | var min = parseInt(dt.substr(14,2),10);
19 | var sec = parseInt(dt.substr(17,2),10);
20 | month--; // JS months start at 0
21 |
22 | var d = new Date(year,month,day,hour,min,sec);
23 | d = d.toLocaleString(0,24);
24 |
25 | return d.substr(0,24);
26 | }
27 | });
28 |
--------------------------------------------------------------------------------
/lib/router.js:
--------------------------------------------------------------------------------
1 | /**
2 | * lib/router.js
3 | *
4 | * This file contains the calls to the iron router plugin to control routes to
5 | * templates and files.
6 | */
7 |
8 | Router.route('/', function () {
9 | var self = this;
10 | switch (Meteor.settings.public.event_state) {
11 | case 'preregistration':
12 | self.layout('pre-eventLayout');
13 | self.render('preregister');
14 | break;
15 | case 'registration':
16 | self.layout('pre-eventLayout');
17 | self.render('sign_up');
18 | break;
19 | case 'check-in':
20 | self.layout('pre-eventLayout');
21 | self.render('check_in');
22 | break;
23 | default:
24 | self.layout('defaultLayout');
25 | self.render('commits');
26 | }
27 | });
28 |
29 | Router.route('checkin', function() {
30 | var self = this;
31 | self.layout('pre-eventLayout');
32 | self.render('check_in');
33 | });
34 |
35 | Router.route('confirm', function() {
36 | var self = this;
37 | self.layout('pre-eventLayout');
38 | self.render('confirm');
39 | });
40 |
41 | Router.route('mentor');
42 | Router.route('info');
43 | Router.route('login');
44 | Router.route('register', function() {
45 | var self = this;
46 | self.layout('pre-eventLayout');
47 | self.render('register');
48 | });
49 | Router.route('user');
50 | Router.route('forgot');
51 | Router.route('set-password');
52 |
53 | Router.configure({
54 | layoutTemplate: 'defaultLayout',
55 | notFoundTemplate: '404'
56 | });
57 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "status-board",
3 | "version": "2.2.1",
4 | "description": "Hackathon commit messages, announcements, mentor requests, and more, all in one place",
5 | "main": "index.js",
6 | "dependencies": {
7 | "bcrypt": "^0.8.7"
8 | },
9 | "devDependencies": {
10 | "babel-eslint": "^6.1.2",
11 | "eslint": "^3.6.0",
12 | "eslint-config-airbnb": "^11.2.0",
13 | "eslint-import-resolver-meteor": "^0.3.3",
14 | "eslint-plugin-import": "^1.16.0",
15 | "eslint-plugin-jsx-a11y": "^2.2.2",
16 | "eslint-plugin-meteor": "^4.0.0",
17 | "eslint-plugin-react": "^6.3.0"
18 | },
19 | "scripts": {
20 | "lint": "eslint .",
21 | "pretest": "npm run lint",
22 | "test": "echo \"Error: no test specified\" && exit 1"
23 | },
24 | "repository": {
25 | "type": "git",
26 | "url": "git+https://github.com/hack-rpi/Status-Board.git"
27 | },
28 | "keywords": [
29 | "hackathon",
30 | "management"
31 | ],
32 | "author": "Matt Poegel",
33 | "license": "MIT",
34 | "bugs": {
35 | "url": "https://github.com/hack-rpi/Status-Board/issues"
36 | },
37 | "homepage": "https://github.com/hack-rpi/Status-Board#readme"
38 | }
39 |
--------------------------------------------------------------------------------
/private/emailTemplates/mentor_confirm.txt:
--------------------------------------------------------------------------------
1 | Hi,
2 |
3 | You did it! You registered for the HackRPI 2016. It's going to be the best one yet! Thank you for volunteering to be a mentor! As a mentor you are automatically accepted to HackRPI. If you are not one of our sponsors, you should reach out to us and introduce yourself! Remember, you are on your own for transporting yourself to HackRPI.
4 |
5 | When you arrive at HackRPI, see one of our volunteers to check-in in order to activate your mentor status. Here's how our mentor system works:
6 |
7 | 1. Edit your mentor skill tags to reflect your expertise. You can do this at any time via your profile page on Status Board.
8 | 2. Students will submit mentor requests using Status Board. They will be able to select from a list of skill tags from all of the currently active mentors.
9 | 3. When you get matched with a mentor, you will receive a text message that will tell you where to go and who to help.
10 | 4. There are four commands that you can text back to interact with Status Board: (1) "DONE" will mark your current task as completed add you back into the active mentor queue, (2) "WAIVE" will forfeit the current task to be given to someone else and automatically suspend you, (3) "SUSPEND" will suspend your mentor status so you won't receive any new tasks and (4) "ACTIVATE" will return you to the active mentor queue if you are suspended.
11 | 5. All of these interactions are also available on Status Board itself in your profile. There, you can also view your mentoring history.
12 |
13 | If you run into any problems, just let one of the organizers know. (You can also directly open an issue on the Status Board repository on Github to buzz the Dev Team!)
14 | [https://github.com/hack-rpi/Status-Board]
15 |
16 | In the meantime,
17 | - Follow us on Twitter @gohackrpi where will post event updates [https://twitter.com/gohackrpi].
18 | - Like our Facebook page to talk with others going to HackRPI 2016 [https://facebook.com/hackrpi].
19 | - Admire our last-minute technological preparations on Github [https://github.com/hack-rpi].
20 | - Stay awesome.
21 |
22 | See you November 12!
23 |
24 |
25 | — The HackRPI Dev Team
26 |
27 |
28 | Facebook [https://www.facebook.com/hackrpi]
29 | Twitter [https://twitter.com/gohackrpi]
30 | Instagram [https://www.instagram.com/gohackrpi]
31 |
--------------------------------------------------------------------------------
/private/emailTemplates/passwordReset.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
41 |
42 |
43 |
44 |
49 |
50 |
Hello {{ name }},
51 |
52 | Click on the link below to reset your Status Board
53 | password. If you did not request this email, no
54 | action need be taken.
55 |
56 |
61 |
62 | - The Status Board Team
63 |
64 |
65 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/private/emailTemplates/prereg_confirm.txt:
--------------------------------------------------------------------------------
1 | Hello,
2 |
3 | Hooray! You have successfully preregistered for HackRPI 2016! What does this mean?
4 |
5 | - You have made it onto the HackRPI 2016 Mailing List!
6 | - You will be one first notified when registration opens for real, which is important because acceptance is on a rolling, first-come, first-served basis.
7 | - You're awesome.
8 |
9 | Remember, this does not mean that you are registered for HackRPI 2016. Look for registration to open early September!
10 |
11 |
12 | — The HackRPI Dev Team
--------------------------------------------------------------------------------
/private/emailTemplates/register_confirm.txt:
--------------------------------------------------------------------------------
1 | Hi,
2 |
3 | You did it! You registered for the HackRPI 2016. It's going to be the best one yet! The first round of acceptances will be sent out around September 23 and will continue thereafter on a rolling basis every other week until the event.
4 |
5 | When you receive your acceptance email, you will have 10 days to confirm your spot. This email will contain information about transportation, including buses and reimbursements. If you fail to confirm your spot, your name will be thrown onto the bottom of the stack.
6 |
7 | In the meantime,
8 | - Follow us on Twitter @gohackrpi [https://twitter.com/gohackrpi].
9 | - Like our Facebook page to talk with other students going to HackRPI 2016 [https://facebook.com/hackrpi].
10 | - Admire our last-minute technological preparations on Github [https://github.com/hack-rpi].
11 | - Stay awesome.
12 |
13 | See you November 12!
14 |
15 |
16 | — The HackRPI Dev Team
17 |
18 |
19 | Facebook [https://www.facebook.com/hackrpi]
20 | Twitter [https://twitter.com/gohackrpi]
21 | Instagram [https://www.instagram.com/gohackrpi]
22 |
--------------------------------------------------------------------------------
/private/emailTemplates/standard.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
HackRPI {{ subject }}
6 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 | Hi {{ name }},
205 | {{ content }}
206 |
207 | — The HackRPI Dev Team
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
253 |
254 |
255 |
256 |
--------------------------------------------------------------------------------
/public/assets/colleges-ca.txt:
--------------------------------------------------------------------------------
1 | Algonquin College
2 | Assiniboine Community College
3 | Aurora College
4 | Bow Valley College
5 | British Columbia Institute of Technology (BCIT)
6 | Cambrian College of Applied Arts and Technology
7 | Camosun College
8 | Canadore College of Applied Arts and Technology
9 | Capilano University
10 | Carlton Trail College
11 | Cegep Andre-Laurendeau
12 | Cegep Beauce-Appalaches
13 | Cegep Garneau
14 | Cegep John Abbott College
15 | Cegep Limoilou
16 | Cegep Marie-Victorin
17 | Cegep Saint-Jean-sur-Richelieu
18 | Cegep de Baie-Comeau
19 | Cegep de Chicoutimi
20 | Cegep de Jonquiere
21 | Cegep de La Pocatiere
22 | Cegep de Matane
23 | Cegep de Riviere-du-Loup
24 | Cegep de Saint-Felicien
25 | Cegep de Saint-Hyacinthe
26 | Cegep de Saint-Jerome
27 | Cegep de Saint-Laurent
28 | Cegep de Sainte-Foy
29 | Cegep de Sept-Iles
30 | Cegep de Sherbrooke
31 | Cegep de Thetford
32 | Cegep de Trois-Rivieres
33 | Cegep de Victoriaville
34 | Cegep de lAbitibi-Temiscamingue
35 | Cegep de lOutaouais
36 | Cegep de la Gaspesie et des Iles
37 | Cegep du Vieux Montreal
38 | Cegep edouard-Montpetit
39 | Cegep regional de Lanaudiere
40 | Centennial College of Applied Arts and Technology
41 | Centre for Nursing Studies
42 | Champlain Regional College
43 | College Acadie I.-P.-e.
44 | College Ahuntsic
45 | College Andre Grasset
46 | College Boreal
47 | College Educacentre
48 | College Gerald-Godin
49 | College LaSalle
50 | College Lionel-Groulx
51 | College Merici
52 | College Montmorency
53 | College Nordique Francophone
54 | College Shawinigan
55 | College communautaire du Nouveau-Brunswick (CCNB)
56 | College de Maisonneuve
57 | College de Rosemont
58 | College of New Caledonia
59 | College of the North Atlantic (CNA)
60 | College of the Rockies
61 | Conestoga College Institute of Technology and Advanced Learning
62 | Confederation College of Applied Arts and Technology
63 | Cumberland College
64 | Dalhousie Agricultural Campus of Dalhousie University
65 | Dawson College
66 | Douglas College
67 | Durham College
68 | Fanshawe College of Applied Arts and Technology
69 | Fleming College
70 | Gabriel Dumont Institute of Native Studies and Applied Research
71 | George Brown College
72 | Georgian College of Applied Arts and Technology
73 | Grande Prairie Regional College
74 | Great Plains College
75 | Heritage College
76 | Holland College
77 | Humber College Institute of Technology & Advanced Learning
78 | Institut de technologie agroalimentaire - Quebec
79 | Institut de tourisme et dhotellerie du Quebec
80 | Justice Institute of British Columbia
81 | Kemptville Campus University of Guelph
82 | Keyano College
83 | Kwantlen Polytechnic University
84 | La Cite
85 | Lakeland College
86 | Lambton College of Applied Arts and Technology
87 | Langara College
88 | Lethbridge College
89 | Loyalist College of Applied Arts and Technology
90 | Manitoba Institute of Trades and Technology
91 | Marine Institute
92 | Medicine Hat College
93 | Mohawk College of Applied Arts and Technology
94 | Native Education College
95 | New Brunswick College of Craft and Design
96 | New Brunswick Community College (NBCC)
97 | Niagara College
98 | Nicola Valley Institute of Technology
99 | NorQuest College
100 | North Island College
101 | North West College
102 | Northern Alberta Institute of Technology (NAIT)
103 | Northern College of Applied Arts and Technology
104 | Northern Lakes College
105 | Northern Lights College
106 | Northlands College
107 | Northwest Community College
108 | Nova Scotia Community College (NSCC)
109 | Nunavut Arctic College
110 | Okanagan College
111 | Olds College
112 | Parkland College
113 | Portage College
114 | Red Deer College
115 | Red River College of Applied Arts Science and Technology
116 | SAIT Polytechnic
117 | Saskatchewan Indian Institute of Technologies (SIIT)
118 | Saskatchewan Polytechnic
119 | Sault College of Applied Arts and Technology
120 | Selkirk College
121 | Seneca College of Applied Arts and Technology
122 | Southeast College
123 | St. Clair College of Applied Arts and Technology
124 | St. Lawrence College
125 | The Michener Institute for Applied Health Sciences
126 | Universite Sainte-Anne -College de lAcadie
127 | University College of the North
128 | University of the Fraser Valley
129 | Vancouver Community College (VCC)
130 | Vancouver Island University
131 | Vanier College
132 | Yukon College
133 | ecole technique et professionnelle Universite de Saint-Boniface
--------------------------------------------------------------------------------
/public/img/downtown.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hack-rpi/Status-Board/5e75d79da61c3ea2064a626cfb7c733a5981a276/public/img/downtown.jpg
--------------------------------------------------------------------------------
/public/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hack-rpi/Status-Board/5e75d79da61c3ea2064a626cfb7c733a5981a276/public/img/favicon.ico
--------------------------------------------------------------------------------
/public/img/hackrpi_logo_cropped.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hack-rpi/Status-Board/5e75d79da61c3ea2064a626cfb7c733a5981a276/public/img/hackrpi_logo_cropped.png
--------------------------------------------------------------------------------
/public/img/hackrpi_logo_full.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hack-rpi/Status-Board/5e75d79da61c3ea2064a626cfb7c733a5981a276/public/img/hackrpi_logo_full.png
--------------------------------------------------------------------------------
/public/img/hackrpi_logo_red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hack-rpi/Status-Board/5e75d79da61c3ea2064a626cfb7c733a5981a276/public/img/hackrpi_logo_red.png
--------------------------------------------------------------------------------
/public/img/hackrpi_screw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hack-rpi/Status-Board/5e75d79da61c3ea2064a626cfb7c733a5981a276/public/img/hackrpi_screw.png
--------------------------------------------------------------------------------
/public/img/red_screw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hack-rpi/Status-Board/5e75d79da61c3ea2064a626cfb7c733a5981a276/public/img/red_screw.png
--------------------------------------------------------------------------------
/server/accounts.js:
--------------------------------------------------------------------------------
1 | Accounts.config({
2 | loginExpirationInDays: 1,
3 | });
4 |
5 | // Construct new users, add to roles, and validate new user data
6 | Accounts.onCreateUser(function(options, user) {
7 | user.profile = options.profile;
8 | user.settings = user.settings || {};
9 | user.settings.accepted = {
10 | flag: false,
11 | expires: null,
12 | travel: {
13 | method: null,
14 | reimbursement: 0,
15 | }
16 | };
17 | user.settings.bus_captain = false;
18 | user.settings.checked_in = false;
19 | user.settings.wifi_username = null;
20 | user.settings.confirmed = {
21 | flag: null,
22 | travel: {
23 | accepted: false,
24 | explaination: null,
25 | }
26 | };
27 | if (options.profile.role == "hacker")
28 | user.roles = ["hacker"];
29 | else if (options.profile.role == "mentor")
30 | user.roles = ["mentor"];
31 | else if (options.profile.role == "volunteer")
32 | user.roles = ["volunteer"];
33 | return user;
34 | });
35 |
36 | Accounts.validateNewUser(function(user) {
37 | if (_.contains(user.roles, 'admin') || _.contains(user.roles, 'announcer'))
38 | return false;
39 | else
40 | return true;
41 | });
42 |
43 | Meteor.methods({
44 | 'sendPasswordResetEmail': function(email) {
45 | var doc = Accounts.findUserByEmail(email)
46 | if (! doc) {
47 | throw new Meteor.Error('Email Not Found',
48 | 'No user found with email address: ' + email);
49 | }
50 | Accounts.sendResetPasswordEmail(doc._id);
51 | return true;
52 | }
53 | });
54 |
55 |
56 | /**
57 | * Email Template Defaults
58 | */
59 | Accounts.emailTemplates.from = 'gohackrpi.status@gmail.com';
60 | Accounts.emailTemplates.siteName = 'status.hackrpi.com';
61 |
62 | Accounts.emailTemplates.resetPassword.subject = function(user) {
63 | return 'HackRPI Status Board - Reset Password';
64 | }
65 | Accounts.emailTemplates.resetPassword.text = function(user, url) {
66 | return 'Hello ' + user.profile.name + ', \n\n' +
67 | 'Use the link below to reset your password. If you did not' +
68 | ' not request this email, no action need be taken. \n\n' +
69 | url + '\n\n' +
70 | '- The HackRPI Team';
71 | }
72 | Accounts.emailTemplates.resetPassword.html = function(user, url) {
73 | SSR.compileTemplate('resetPasswordText',
74 | Assets.getText('emailTemplates/passwordReset.html'));
75 | return SSR.render('resetPasswordText', {
76 | logo_url: Meteor.absoluteUrl('img/hackrpi_logo_cropped.png'),
77 | name: user.profile.name,
78 | url: url
79 | });
80 | }
--------------------------------------------------------------------------------
/server/collections/hooks.js:
--------------------------------------------------------------------------------
1 | AnonReports.after.insert(function(userId, doc) {
2 | Meteor.call('sendAlerts', 'ALERT! An anonymous report has been filed.');
3 | });
4 |
--------------------------------------------------------------------------------
/server/collections/permissions.js:
--------------------------------------------------------------------------------
1 | // COLLECTION PRIVELEDGES
2 | Meteor.users.allow({
3 | insert: function(userId, doc) {
4 | // users should only be added on the server via the Accounts package
5 | return false;
6 | },
7 | remove: function(userId, doc) {
8 | if (doc._id === admin_id)
9 | return false;
10 | else if (Roles.userIsInRole(userId, 'admin'))
11 | return true;
12 | else
13 | return false;
14 | },
15 | update: function(userId, doc, fieldNames, modifier) {
16 | if (doc._id === admin_id && _.contains(fieldNames, 'roles'))
17 | return false;
18 | // users can only edit their own data
19 | else if (doc._id === userId && fieldNames.length === 0 && fieldNames[0] === 'profile')
20 | return true;
21 | else if (Roles.userIsInRole(userId, 'admin'))
22 | return true;
23 | else
24 | return false;
25 | }
26 | });
27 |
28 | CommitMessages.allow({
29 | insert:function(userId, doc) {
30 | // done server side
31 | return false;
32 | },
33 | remove: function(userId, doc) {
34 | if (Roles.userIsInRole(userId, 'admin'))
35 | return true;
36 | else
37 | return false;
38 | },
39 | update: function(userId, doc, fieldNames, modifier) {
40 | var upVoteMod = {
41 | $inc: {
42 | total_flags: 1
43 | },
44 | $addToSet: {
45 | flags: {
46 | id: userId
47 | }
48 | }
49 | },
50 | downVoteMod = {
51 | $inc: {
52 | total_flags: -1
53 | },
54 | $pull: {
55 | flags: {
56 | id: userId
57 | }
58 | }
59 | };
60 | if (Roles.userIsInRole(userId, 'admin'))
61 | return true;
62 | // verify that voting is completed legitimently
63 | // user can only modify the flag and total_flag fields,
64 | // modifier must either be upVoteMod or downVoteMod defined above
65 | // check that user can only inc up/down once
66 | else if (_.every(fieldNames, function(f) {
67 | return f === 'flags' || f === 'total_flags'})
68 | && ((_.isEqual(modifier, upVoteMod) && ! _.contains(doc.flags, { id: userId }))
69 | || (_.isEqual(modifier, downVoteMod) && _.contains(doc.flags, { id: userId }))))
70 | return true;
71 | else
72 | return false;
73 | }
74 | });
75 |
76 | RepositoryList.allow({
77 | insert: function(userId, doc) {
78 | var user_doc = Meteor.users.findOne({ '_id': userId });
79 | // any logged in user can insert a repo as long as they are not yet
80 | // attached to one
81 | if (user_doc && ! user_doc.profile.repositoryId
82 | && ! RepositoryList.findOne({ 'contributors': {
83 | $elemMatch: { 'id': 5, 'handle': user_doc.profile.github_handle }
84 | }
85 | }))
86 | return true;
87 | else
88 | return false
89 | },
90 | remove: function(userId, doc) {
91 | var user_doc = Meteor.users.findOne({ '_id': userId });
92 | // a user can only remove a repo that no one is attached to
93 | if (doc.contributors.length === 0)
94 | return true;
95 | else
96 | return false;
97 | },
98 | update: function(userId, doc, fieldNames, modifier) {
99 | var user_doc = Meteor.users.findOne({ '_id': userId }),
100 | userSet = {
101 | id: userId,
102 | handle: user_doc.profile.github_handle
103 | },
104 | removeUser = {
105 | $pull: {
106 | contributors: userSet
107 | }
108 | },
109 | addUser = {
110 | $addToSet: {
111 | contributors: userSet
112 | }
113 | };
114 | // a user can only modify the repo doc that they are attached to
115 | if (user_doc.profile.repositoryId === doc._id) {
116 | // if the user if modifying the userIds/collab field, they may only edit
117 | // their own entry
118 | if (_.contains(fieldNames, 'contributors')) {
119 | if (_.isEqual(modifier, removeUser) || _.isEqual(modifier, addUser))
120 | return true;
121 | else
122 | return false;
123 | }
124 | // user can edit the other fields freely
125 | else if (_.some(doc.contributors, function(x) { return _.isEqual(x, userSet); })
126 | && _.intersection(fieldNames, ['webhook', 'name', 'full_name', 'url', 'DevPost'])
127 | .length !== 0)
128 | return true;
129 | }
130 | else
131 | return false;
132 | }
133 | });
134 |
135 | Announcements.allow({
136 | insert: function(userId, doc) {
137 | if (Roles.userIsInRole(userId, ['announcer', 'admin']))
138 | return true;
139 | else
140 | return false;
141 | },
142 | remove: function(userId, doc) {
143 | if (Roles.userIsInRole(userId, ['announcer', 'admin']))
144 | return true;
145 | else
146 | return false;
147 | },
148 | update: function(userId, doc, fieldNames, modifier) {
149 | if (Roles.userIsInRole(userId, ['announcer', 'admin']))
150 | return true;
151 | else
152 | return false;
153 | }
154 | });
155 |
156 | MentorQueue.allow({
157 | insert: function(userId, doc) {
158 | return Meteor.users.findOne({ "_id":admin_id }).profile.settings.mentoring_system;
159 | },
160 | remove: function(userId, doc) {
161 | if (Roles.userIsInRole(userId, 'mentor', 'admin'))
162 | return true;
163 | else
164 | return false;
165 | },
166 | update: function(userId, doc) {
167 | if (Roles.userIsInRole(userId, ['mentor', 'admin']))
168 | return true;
169 | else
170 | return false;
171 | }
172 | });
173 |
174 | AnonReports.allow({
175 | insert: function(userId, doc) {
176 | return true;
177 | },
178 | remove: function(userId, doc) {
179 | return Roles.userIsInRole(userId, 'admin');
180 | },
181 | update: function(userId, doc) {
182 | return Roles.userIsInRole(userId, 'admin');
183 | }
184 | });
185 |
186 | AnonUserData.allow({
187 | insert: function(userId, doc) {
188 | return true;
189 | },
190 | remove: function(userId, doc) {
191 | return Roles.userIsInRole(userId, 'admin');
192 | },
193 | update: function(userId, doc, fieldNames, modifier) {
194 | return Roles.userIsInRole(userId, 'admin');
195 | }
196 | });
197 |
198 | PreRegistration.allow({
199 | insert: function(userId, doc) {
200 | var doc_keys = _.keys(doc);
201 | if (!_.isEqual(_.keys(doc), ['name', 'email', 'school'])) {
202 | return false;
203 | }
204 | if (doc.name == '' || doc.email == '' || doc.school == '') {
205 | return false;
206 | }
207 | if (PreRegistration.find({ email: doc.email }).count() > 0) {
208 | throw new Meteor.Error('Email Exists',
209 | 'This email address has already been preregistered');
210 | return false;
211 | }
212 | return true;
213 | },
214 | remove: function(userId, doc) {
215 | return false;
216 | },
217 | update: function(userId, doc, fieldNames, modifier) {
218 | return false;
219 | },
220 | fetch: ['email']
221 | });
222 |
--------------------------------------------------------------------------------
/server/collections/publications.js:
--------------------------------------------------------------------------------
1 | // publish the databases to all clients
2 | Meteor.publish("CommitMessages", function() { return CommitMessages.find(); });
3 | Meteor.publish("RepositoryList", function() { return RepositoryList.find(); });
4 | Meteor.publish("Announcements", function() { return Announcements.find(); });
5 | Meteor.publish("MentorQueue", function() { return MentorQueue.find(); });
6 | // users can view all of their own data but only the profiles and usernames
7 | // of other users
8 | Meteor.publish("UserData", function(userId) {
9 | if (Roles.userIsInRole(userId, 'admin')){
10 | return Meteor.users.find();
11 | }
12 | else if (userId) {
13 | return Meteor.users.find({ "_id": userId });
14 | }
15 | else {
16 | this.ready();
17 | }
18 | });
19 |
20 | Meteor.publish('MentorData', function() {
21 | return Meteor.users.find({
22 | roles: 'mentor'
23 | }, {
24 | fields: {
25 | 'profile.tags': 1,
26 | 'profile.active': 1,
27 | 'profile.available': 1,
28 | 'roles': 1
29 | }
30 | });
31 | })
32 |
33 | Meteor.publish('AnonReports', function() {
34 | if (Roles.userIsInRole(this.userId, 'admin')) {
35 | return AnonReports.find();
36 | }
37 | });
38 |
39 | Meteor.publish('AnonUserData', function() {
40 | if (Roles.userIsInRole(this.userId, 'admin')) {
41 | return AnonUserData.find();
42 | }
43 | });
44 |
45 | Meteor.publish('USColleges', function() {
46 | return USColleges.find();
47 | });
48 |
49 | // Meteor.publish('PreRegistration', function() {
50 | // return this.ready();
51 | // });
52 |
--------------------------------------------------------------------------------
/server/email.js:
--------------------------------------------------------------------------------
1 | /**
2 | * server/email.js
3 | */
4 | Meteor.methods({
5 |
6 | /**
7 | *
8 | */
9 | 'sendEmail': function(to, subject, data, template) {
10 | // add asset locations
11 | data.logo_url = Meteor.absoluteUrl('img/hackrpi_logo_red.png');
12 | // compile the email template
13 | SSR.compileTemplate('email',
14 | Assets.getText('emailTemplates/' + template + '.html'));
15 | var html = SSR.render('email', data);
16 | // let the client continue with other calls
17 | this.unblock();
18 | // send the email
19 | Email.send({
20 | to: to,
21 | from: 'team@hackrpi.com',
22 | subject: subject,
23 | html: html,
24 | text: Assets.getText('emailTemplates/' + template + '.txt'),
25 | });
26 | }
27 |
28 | });
--------------------------------------------------------------------------------
/server/github.js:
--------------------------------------------------------------------------------
1 | /*
2 | Server methods for making calls to the GitHub API
3 | */
4 |
5 | // keeps track of the state variables sent with OAuth requests
6 | // user_states[USER_ID] = STATE
7 | var user_states = {};
8 |
9 | Meteor.methods({
10 | // returns a URL to direct the user to GitHub to yeild an access token
11 | getGitHubRedirect: function(userId) {
12 | var state = Random.secret();
13 | if (! Meteor.users.find({ '_id': userId }))
14 | throw new Meteor.Error('GitHub Error', 'Invalid userId.');
15 | user_states[userId] = state;
16 | return 'https://github.com/login/oauth/authorize?'
17 | + 'client_id=' + Meteor.settings.github_clientId
18 | + '&redirect_uri=' + Meteor.settings.root_url + '/user'
19 | + '&scope=admin:repo_hook,admin:org_hook'
20 | + '&state=' + state;
21 | },
22 |
23 | // takes the CODE and STATE returned from GitHub and retrieves an access
24 | // token. stores the token, scope, and token type in the services.Gitub
25 | // field in the user's document
26 | getGitHubAccessToken: function(code, state, userId) {
27 | var url = 'https://github.com/login/oauth/access_token?'
28 | + 'client_id=' + Meteor.settings.github_clientId
29 | + '&client_secret=' + Meteor.settings.github_secret
30 | + '&code=' + code
31 | try {
32 | if (user_states[userId] != state) {
33 | throw new Meteor.Error('State-Error',
34 | 'bad state! request created by third party!');
35 | }
36 | delete user_states[userId];
37 | Meteor.http.post(url, {
38 | headers: {
39 | 'User-Agent': 'Meteor/1.1'
40 | }
41 | }, function(error, result) {
42 | var content = decodeURIComponent(result.content).split('&')
43 | .map(function(d) { return d.split('='); });
44 | Meteor.users.update({ '_id': userId }, {
45 | $set: {
46 | 'services.Github.access_token': content[0][1],
47 | 'services.Github.scope': content[1][1].split(','),
48 | 'services.Github.token_type': content[2][1]
49 | }
50 | });
51 | });
52 | }
53 | catch (e) {
54 | throw new Meteor.Error('GitHub Error', 'Unable to obtain access token.')
55 | }
56 | },
57 |
58 | // creates a webhook on the repository that the given user is attached to
59 | // and updates that repository's document after the webhook has been created
60 | createRepositoryWebhook: function(userId) {
61 | var user_doc = Meteor.users.findOne({ '_id': userId }),
62 | repo_doc = RepositoryList.findOne({ '_id': user_doc.profile.repositoryId });
63 | try {
64 | return Meteor.http.post(
65 | 'https://api.github.com/repos/' + repo_doc.full_name + '/hooks'
66 | + '?access_token=' + user_doc.services.Github.access_token,
67 | {
68 | headers: {
69 | 'User-Agent': 'Meteor/1.1'
70 | },
71 | data: {
72 | 'name': 'web',
73 | 'active': true,
74 | 'events': ['push'],
75 | 'config': {
76 | 'url': Meteor.settings.root_url + '/api/CommitMessages',
77 | 'content_type': 'json',
78 | 'secret': Meteor.settings.secret_key
79 | }
80 | }
81 | }, function(error, result) {
82 | RepositoryList.update({ '_id': repo_doc._id }, {
83 | $set: {
84 | 'webhook.created': true,
85 | 'webhook.createdBy': userId,
86 | 'webhook.id': result.data.id,
87 | 'webhook.events': result.data.events
88 | }
89 | });
90 | });
91 | }
92 | catch (e) {
93 | throw new Meteor.Error('GitHub Error', 'Unable to create webhook.');
94 | }
95 | },
96 |
97 | // deletes the webhook given full repo's name and hookId
98 | deleteRepositoryWebhook: function(userId, repoDoc) {
99 | var user_doc = Meteor.users.findOne({ '_id': userId });
100 | try {
101 | return Meteor.http.del(
102 | 'https://api.github.com/repos/' + repoDoc.full_name + '/hooks/'
103 | + repoDoc.webhook.id
104 | + '?access_token=' + user_doc.services.Github.access_token,
105 | {
106 | headers: {
107 | 'User-Agent': 'Meteor/1.1'
108 | }
109 | }, function(error, result) {
110 | if (error)
111 | throw error;
112 | else {
113 | RepositoryList.update({ '_id': repoDoc._id }, {
114 | $set: {
115 | 'webhook.created': false,
116 | 'webhook.createdBy': '',
117 | 'webhook.id': '',
118 | 'webhook.events': []
119 | }
120 | });
121 | }
122 | });
123 | }
124 | catch (e) {
125 | console.log(e);
126 | throw new Meteor.Error('GitHub Error', 'Unable to delete webhook.');
127 | }
128 | },
129 |
130 | // retreives the commit messages in the master branch for a given
131 | // repository using a user's access token
132 | getRepoCommitData: function(token, full_repo_name) {
133 | try {
134 | return Meteor.http.get(
135 | 'https://api.github.com/repos/' + full_repo_name + '/commits',
136 | {
137 | headers: {
138 | 'User-Agent': 'Meteor/1.1'
139 | },
140 | params: {
141 | access_token: token
142 | }
143 | }
144 | );
145 | }
146 | catch (e) {
147 | throw new Meteor.Error('GitHub Error',
148 | 'Unable to retrieve commit messages.');
149 | }
150 | },
151 |
152 | // retrieves the information about a given repository (full name) using
153 | // a user's access token
154 | getRepositoryData: function(token, full_repo_name) {
155 | try {
156 | return Meteor.http.get(
157 | 'https://api.github.com/repos/' + full_repo_name,
158 | {
159 | headers: {
160 | 'User-Agent': 'Meteor/1.1'
161 | },
162 | params: {
163 | access_token: token
164 | }
165 | }
166 | );
167 | }
168 | catch (e) {
169 | throw new Meteor.Error('GitHub Error',
170 | 'Unable to retrieve repository data.');
171 | }
172 | },
173 |
174 | // grabs the 30 most recent commits from a given repository using a user's
175 | // access token and adds all of the new commits to the collection
176 | addCommits: function(userId) {
177 | var user_doc = Meteor.users.findOne({ '_id': userId }),
178 | token = user_doc.services.Github.access_token,
179 | full_repo_name = RepositoryList.findOne({
180 | '_id': user_doc.profile.repositoryId
181 | }).full_name;
182 | try {
183 | // make synchronous calls (blocking)
184 | var commits_result = Meteor.call('getRepoCommitData', token, full_repo_name),
185 | repo_result = Meteor.call('getRepositoryData', token, full_repo_name);
186 | }
187 | catch (e) {
188 | throw e;
189 | }
190 | try {
191 | var commits = JSON.parse(commits_result.content),
192 | raw_repo_data = JSON.parse(repo_result.content),
193 | // create repo object to attach to every commit
194 | repo_data = {
195 | id: raw_repo_data.id,
196 | name: raw_repo_data.name,
197 | full_name: raw_repo_data.full_name,
198 | owner: {
199 | name: raw_repo_data.owner.login,
200 | email: raw_repo_data.owner.email,
201 | },
202 | description: raw_repo_data.description,
203 | url: raw_repo_data.html_url,
204 | homepage: raw_repo_data.homepage,
205 | language: {
206 | name: raw_repo_data.language,
207 | color: languageColors[raw_repo_data.language]
208 | }
209 | };
210 | // loop over all the commits that were found
211 | // stop if we get to something we've already added
212 | for (var i=0; i
> admin account created");
64 | // admin_id = Accounts.createUser({
65 | // "username": Meteor.settings.default_admin_username,
66 | // "password": Meteor.settings.default_admin_password,
67 | // "profile": {
68 | // "name": "Administrator",
69 | // "settings": {
70 | // "allow_account_creation": false,
71 | // "mentoring_system": false
72 | // }
73 | // },
74 | // 'settings': {
75 | // 'alert_numbers': [],
76 | // 'event_stage': 'registration'
77 | // }
78 | // });
79 | // // give the admin admin rights
80 | // var adminUser = Meteor.users.findOne({ "_id":admin_id });
81 | // Roles.addUsersToRoles(adminUser, 'admin');
82 | // }
83 |
84 | // Prevent non-authorized users from creating new users:
85 | // Accounts.validateNewUser(function (user) {
86 | // if (Meteor.users.findOne({ "_id":admin_id }).profile.settings.allow_account_creation) {
87 | // return true;
88 | // }
89 | // throw new Meteor.Error(403, "Not authorized to create new users");
90 | // });
91 |
92 |
93 | /**
94 | * Set the environment variable to send mail
95 | */
96 | process.env.MAIL_URL = Meteor.settings.mail_url;
97 |
98 | if (Meteor.settings.mongo_url) {
99 | process.env.MONGO_URL = Meteor.settings.mongo_url;
100 | }
101 |
102 | /* Turn these off for now
103 |
104 | // Repeating Server Actions ==================================================
105 |
106 | // show check for new announcements to show every 30 seconds
107 | Meteor.setInterval(function() {
108 | Meteor.call("showAnnouncements");
109 | }, 10*1000);
110 |
111 | // assign free mentors to hackers in the queue every 60 seconds
112 | Meteor.setInterval(function() {
113 | Meteor.call("assignMentors");
114 | }, 10*1000);
115 |
116 | // ===========================================================================
117 |
118 | */
119 |
120 | });
121 |
--------------------------------------------------------------------------------