├── .arcconfig ├── .arclint ├── .editorconfig ├── .env.dusk.testing.example ├── .env.example ├── .env.testing.example ├── .gitattributes ├── .gitignore ├── Homestead.yaml ├── LICENSE ├── Makefile ├── README.md ├── Vagrantfile ├── after.sh ├── app ├── Config │ ├── Bootstrap │ │ └── LoadConfiguration.php │ ├── Facades │ │ └── SiteConfigSaver.php │ ├── Models │ │ └── Config.php │ ├── Repository │ │ ├── ConfigLoaderRepository.php │ │ └── ConfigSaverRepository.php │ └── SiteConfigServiceProvider.php ├── Console │ ├── Commands │ │ ├── ActivityExport.php │ │ ├── CreateRole.php │ │ ├── CreateUser.php │ │ ├── DatabaseBackup.php │ │ ├── DatabaseClear.php │ │ ├── DatabaseRebuild.php │ │ ├── DatabaseRestore.php │ │ ├── Inspire.php │ │ ├── SendDailyNotifications.php │ │ ├── SponsorCommand.php │ │ ├── UserRole.php │ │ └── dbUpdateSponsors.php │ └── Kernel.php ├── Contracts │ └── Notification.php ├── Events │ ├── CommentCreated.php │ ├── CommentFlagged.php │ ├── CommentLiked.php │ ├── DocumentPublished.php │ ├── SponsorCreated.php │ ├── SponsorMemberAdded.php │ ├── SponsorMemberRemoved.php │ ├── SponsorMemberRoleChanged.php │ ├── SponsorStatusChanged.php │ ├── SupportVoteChanged.php │ ├── UserVerificationRequest.php │ └── UserVerificationStatusChange.php ├── Exceptions │ └── Handler.php ├── Http │ ├── Controllers │ │ ├── AdminController.php │ │ ├── Auth │ │ │ ├── ForgotPasswordController.php │ │ │ ├── LoginController.php │ │ │ ├── RegisterController.php │ │ │ └── ResetPasswordController.php │ │ ├── CommentController.php │ │ ├── Controller.php │ │ ├── DocumentController.php │ │ ├── HomeController.php │ │ ├── PageController.php │ │ ├── SponsorController.php │ │ ├── SponsorMemberController.php │ │ ├── TranslationController.php │ │ └── UserController.php │ ├── Kernel.php │ ├── Middleware │ │ ├── CheckForLoginToken.php │ │ ├── DiscussionState.php │ │ ├── EncryptCookies.php │ │ ├── LoadPages.php │ │ ├── RedirectIfAuthenticated.php │ │ ├── UnapprovedSponsorRedirect.php │ │ └── VerifyCsrfToken.php │ └── Requests │ │ ├── Admin │ │ ├── FeaturedDocuments │ │ │ ├── Index.php │ │ │ └── Update.php │ │ ├── SiteSettings │ │ │ ├── Index.php │ │ │ └── Update.php │ │ ├── Sponsors │ │ │ ├── Index.php │ │ │ └── PutStatus.php │ │ └── Users │ │ │ ├── Index.php │ │ │ └── PostAdmin.php │ │ ├── AdminRequest.php │ │ ├── Document │ │ ├── Edit.php │ │ ├── Index.php │ │ ├── PutSupport.php │ │ ├── Store.php │ │ ├── Update.php │ │ └── View.php │ │ ├── Page │ │ ├── Create.php │ │ ├── Destroy.php │ │ ├── Edit.php │ │ ├── Index.php │ │ ├── Store.php │ │ └── Update.php │ │ ├── Sponsor │ │ ├── Create.php │ │ ├── DocumentsIndex.php │ │ ├── Edit.php │ │ ├── Index.php │ │ ├── Store.php │ │ └── Update.php │ │ ├── SponsorMember │ │ ├── Create.php │ │ ├── Destroy.php │ │ ├── Index.php │ │ ├── Store.php │ │ └── UpdateRole.php │ │ ├── Translation │ │ └── Index.php │ │ └── User │ │ ├── Edit.php │ │ ├── Settings │ │ ├── UpdateAccount.php │ │ ├── UpdateNotifications.php │ │ └── UpdatePassword.php │ │ └── SponsorsIndex.php ├── Jobs │ └── Job.php ├── Listeners │ ├── .gitkeep │ ├── CommentCreatedNotification.php │ ├── CommentFlaggedNotification.php │ ├── CommentLikedNotification.php │ ├── DocumentPublishedNotification.php │ ├── RegisteredUser.php │ ├── ShouldSendNotification.php │ ├── SponsorCreatedNotification.php │ ├── SponsorMemberAddedNotification.php │ ├── SponsorMemberRemovedNotification.php │ ├── SponsorMemberRoleChangedNotification.php │ ├── SponsorStatusChangedNotification.php │ ├── SupportVoteChangedNotification.php │ ├── UserVerificationRequestNotification.php │ └── UserVerificationStatusChangeNotification.php ├── Mail │ ├── DailyNotifications.php │ ├── EmailVerification.php │ └── SponsorOnboarding │ │ ├── Engage.php │ │ ├── Prepare.php │ │ └── Publish.php ├── Models │ ├── ActivityInterface.php │ ├── Annotation.php │ ├── AnnotationPermission.php │ ├── AnnotationTypes │ │ ├── Comment.php │ │ ├── Flag.php │ │ ├── Hidden.php │ │ ├── Like.php │ │ ├── Range.php │ │ ├── Resolved.php │ │ ├── Seen.php │ │ └── Tag.php │ ├── BillImport.php │ ├── Doc.php │ ├── DocContent.php │ ├── DocMeta.php │ ├── LoginToken.php │ ├── NotificationPreference.php │ ├── Page.php │ ├── PageContent.php │ ├── Permission.php │ ├── Role.php │ ├── Setting.php │ ├── Sponsor.php │ ├── SponsorMember.php │ └── User.php ├── Notifications │ ├── AddedToSponsor.php │ ├── CommentCreatedOnSponsoredDocument.php │ ├── CommentFlagged.php │ ├── CommentLiked.php │ ├── CommentReplied.php │ ├── DocumentPublished.php │ ├── Messages │ │ └── MailMessage.php │ ├── Notification.php │ ├── RemovedFromSponsor.php │ ├── SponsorNeedsApproval.php │ ├── SupportVoteChanged.php │ ├── UserCreated.php │ ├── UserMembershipChanged.php │ └── UserSponsorRoleChanged.php ├── Policies │ ├── .gitkeep │ ├── DocumentPolicy.php │ └── Policy.php ├── Providers │ ├── AnnotationsServiceProvider.php │ ├── AppServiceProvider.php │ ├── AuthServiceProvider.php │ ├── BroadcastServiceProvider.php │ ├── CommentMarkdownServiceProvider.php │ ├── CommentsServiceProvider.php │ ├── DocumentsServiceProvider.php │ ├── EventServiceProvider.php │ ├── PdoEventSessionHandlerProvider.php │ ├── RouteServiceProvider.php │ ├── SessionRejectServiceProvider.php │ └── UserServiceProvider.php ├── Services │ ├── Annotations.php │ ├── Comments.php │ ├── Documents.php │ ├── SearchQueryCompiler.php │ └── UniqId.php ├── Session │ └── Storage │ │ └── Handler │ │ └── PdoEventSessionHandler.php └── Traits │ ├── AnnotatableHelpers.php │ └── RootAnnotatableHelpers.php ├── artisan ├── bootstrap ├── app.php ├── autoload.php └── cache │ └── .gitignore ├── circle.yml ├── circleci └── apache.conf ├── composer.json ├── composer.lock ├── config ├── app.php ├── auth.php ├── broadcasting.php ├── cache.php ├── database.php ├── entrust.php ├── filesystems.php ├── madison.php ├── mail.php ├── markdown.php ├── queue.php ├── services.php ├── session.php └── view.php ├── database ├── .gitignore ├── factories │ └── ModelFactory.php ├── migrations │ ├── .gitkeep │ ├── 2013_03_06_203506_create_docs_table.php │ ├── 2013_03_06_203517_create_doc_contents_table.php │ ├── 2013_03_06_203542_create_organizations_table.php │ ├── 2013_03_06_203552_create_users_table.php │ ├── 2013_03_06_203600_create_settings_table.php │ ├── 2013_03_06_203617_create_doc_meta_table.php │ ├── 2013_04_10_012922_create_note_meta_table.php │ ├── 2014_01_30_175108_create_comments_table.php │ ├── 2014_02_03_224850_add_user_to_doc_meta.php │ ├── 2014_02_03_232541_add_doc_meta_key.php │ ├── 2014_02_11_204013_add_user_meta_table.php │ ├── 2014_02_11_212039_add_user_meta_key.php │ ├── 2014_02_18_221127_create_doc_categories_table.php │ ├── 2014_02_18_230809_create_category_doc_table.php │ ├── 2014_02_20_003208_create_doc_user_table.php │ ├── 2014_02_20_003949_create_roles_table.php │ ├── 2014_02_20_004504_create_role_user_table.php │ ├── 2014_02_20_191548_create_password_reminders_table.php │ ├── 2014_02_20_222629_create_statuses_table.php │ ├── 2014_02_20_224328_create_doc_status_table.php │ ├── 2014_02_24_205855_create_dates_table.php │ ├── 2014_03_05_173240_create_annotations_table.php │ ├── 2014_03_05_174006_create_annotation_comments_table.php │ ├── 2014_03_05_174637_create_annotation_tags_table.php │ ├── 2014_03_05_192222_create_annotation_permissions_table.php │ ├── 2014_03_12_204746_create_annotation_ranges.php │ ├── 2014_03_17_150518_alter_note_meta_table.php │ ├── 2014_03_17_152535_add_foreign_index_note_meta.php │ ├── 2014_03_18_071119_drop_annotation_meta_columns.php │ ├── 2014_03_18_073947_make_annotations_search_id_nullable.php │ ├── 2014_03_18_195216_make_comments_auto_incrementing.php │ ├── 2014_03_21_162921_add_parent_column_to_comments.php │ ├── 2014_03_21_170432_create_comment_meta_table.php │ ├── 2014_03_26_220409_rename_doc_column_in_annotations.php │ ├── 2014_03_26_220422_rename_content_column_in_comments.php │ ├── 2014_03_28_201831_add_seen_columns.php │ ├── 2014_03_31_195008_add_soft_deletes.php │ ├── 2014_04_03_015654_entrust_setup_tables.php │ ├── 2014_04_03_064948_drop_user_level_column.php │ ├── 2014_04_22_202758_add_group_tables.php │ ├── 2014_05_05_173053_add_groups_to_documents.php │ ├── 2014_05_22_163151_alter_annotations_increase_field_length.php │ ├── 2014_06_24_040512_create_notifications_table.php │ ├── 2014_07_01_181718_drop_unused_user_fields.php │ ├── 2014_07_01_181732_add_independent_sponsor_fields_to_users.php │ ├── 2014_08_01_142911_make_password_nullable.php │ ├── 2014_08_01_145651_users_social_auth_fields.php │ ├── 2014_08_05_220609_make_user_token_default_empty.php │ ├── 2014_12_02_213959_alter_doc_meta_meta_key_as_text.php │ ├── 2015_01_07_221330_set_group_address2_default_value.php │ ├── 2015_04_13_211045_add_thumbnail_to_document.php │ ├── 2015_07_10_182013_create_session_table.php │ ├── 2015_07_10_232617_add_userid_to_session_table.php │ ├── 2015_09_11_144251_private_flag.php │ ├── 2015_10_15_192134_doc_template_flag.php │ ├── 2015_11_15_184015_make_sessions_user_id_nullable.php │ ├── 2015_11_17_174445_remove_dislike_entries.php │ ├── 2015_11_24_182254_add_remember_token_to_users.php │ ├── 2015_12_01_142342_remove_duplicates_from_assigned_roles.php │ ├── 2015_12_01_142343_change_assigned_roles_to_role_user.php │ ├── 2015_12_01_142504_add_new_entrust_columns_to_roles.php │ ├── 2015_12_01_142514_add_new_entrust_columns_to_permissions.php │ ├── 2015_12_01_142714_update_indexes_on_role_user.php │ ├── 2015_12_01_142733_update_indexes_on_permission_role.php │ ├── 2016_01_11_213954_create_password_resets_table.php │ ├── 2016_01_20_220338_add_publish_state_to_docs.php │ ├── 2016_01_20_220346_remove_private_from_docs.php │ ├── 2016_01_22_201911_paginate_documents.php │ ├── 2016_01_26_183028_create_doc_types.php │ ├── 2016_02_01_190330_change_doc_types.php │ ├── 2016_02_18_153538_add_discussion_state_to_docs.php │ ├── 2016_03_01_023454_doc_slug_not_unique.php │ ├── 2016_03_07_202808_add_individual_flag_to_groups.php │ ├── 2016_03_22_000807_action_view.php │ ├── 2016_03_22_124953_rename_phone_number_column_on_groups.php │ ├── 2016_03_23_040313_add_user_id_to_groups.php │ ├── 2016_03_24_021134_populate_individual_sponsors_as_groups.php │ ├── 2016_04_06_212715_create_pages_table.php │ ├── 2016_04_07_164123_create_page_contents_table.php │ ├── 2016_04_25_213559_create_jobs_table.php │ ├── 2016_04_26_153504_create_failed_jobs_table.php │ ├── 2016_04_27_200919_rename_notifications_to_notification_preferences.php │ ├── 2016_05_19_160401_create_groups_for_individual_sponsor_role.php │ ├── 2016_05_19_160402_create_groups_for_doc_owning_users.php │ ├── 2016_05_19_160408_move_individual_sponsor_docs_to_individual_groups.php │ ├── 2016_05_25_130314_cleanup_old_independent_sponsor_data.php │ ├── 2016_06_01_162617_comment_unification.php │ ├── 2016_07_25_203547_mark_note_replies_as_notes.php │ ├── 2016_08_11_134833_remove_user_id_from_groups.php │ ├── 2016_08_11_144504_clean_up_duplicate_individual_groups.php │ ├── 2016_12_05_180911_database_queue_driver_changes.php │ ├── 2016_12_05_182306_database_sessions_driver_changes.php │ ├── 2016_12_16_183722_fix_document_thumbnail_url.php │ ├── 2016_12_16_223140_rework_document_thumbnails.php │ ├── 2016_12_21_161640_change_groups_to_sponsors.php │ ├── 2016_12_22_140724_update_indexes_on_doc_sponsor_table.php │ ├── 2016_12_22_145400_update_indexes_on_sponsor_members_table.php │ ├── 2016_12_22_150833_update_indexes_on_notification_preferences_table.php │ ├── 2017_01_03_200257_update_permission_names.php │ ├── 2017_01_03_211454_update_role_names.php │ ├── 2017_01_14_032118_fix_oppose_doc_meta.php │ ├── 2017_01_20_185227_add_str_id_to_annotations.php │ ├── 2017_01_24_204208_sponsor_approval_notification.php │ ├── 2017_01_26_170819_comment_reply_notification.php │ ├── 2017_01_31_170338_user_sponsor_membership_notification.php │ ├── 2017_02_01_224359_enable_sponsor_role_change_notification.php │ ├── 2017_02_02_152806_enable_comment_created_on_sponsored_notification.php │ ├── 2017_02_02_195334_enable_comment_liked_notification.php │ ├── 2017_02_03_194722_enable_support_vote_changed_notification.php │ ├── 2017_02_06_155557_enable_document_published_notification.php │ ├── 2017_02_07_152322_enable_flagged_comment_notification.php │ ├── 2017_02_07_163509_create_config_table.php │ ├── 2017_02_14_034416_create_resolved_and_hidden_annotation_types.php │ ├── 2017_03_03_173336_add_fulltext_idxs_for_doc_search.php │ ├── 2017_03_15_191554_remove_user_verification_columns.php │ ├── 2017_03_21_210637_drop_categories.php │ ├── 2017_03_22_132339_drop_statuses.php │ ├── 2017_03_22_132654_drop_organizations.php │ ├── 2017_03_22_132914_drop_dates.php │ ├── 2017_03_30_003414_drop_user_meta_stuff.php │ ├── 2017_05_04_175750_create_laravel_notifications_table.php │ ├── 2017_05_08_141824_add_frequency_to_notification_preferences.php │ ├── 2017_05_11_153226_create_login_tokens_table.php │ ├── 2017_05_15_191135_add_fulltext_idxs_for_user_search.php │ └── 2017_05_15_191142_add_fulltext_idxs_for_sponsor_search.php └── seeds │ ├── AnnotationsTableSeeder.php │ ├── DatabaseSeeder.php │ ├── DocumentsTableSeeder.php │ ├── NotificationSeeder.php │ ├── PagesTableSeeder.php │ ├── RbacSeeder.php │ ├── SponsorsTableSeeder.php │ ├── TestSeeder.php │ ├── UsersTableSeeder.php │ └── pages │ ├── about.md │ └── faq.md ├── docs ├── README.md ├── RELEASE_NOTES.md ├── ci_workflow.md ├── deploy.md └── develop.md ├── gulpfile.js ├── package.json ├── phpspec.yml ├── phpunit.xml ├── public ├── .htaccess ├── index.php ├── robots.txt └── web.config ├── resources ├── assets │ ├── icons │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── browserconfig.xml │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ ├── manifest.json │ │ ├── mstile-150x150.png │ │ └── safari-pinned-tab.svg │ ├── img │ │ ├── default-featured.jpg │ │ └── logo.svg │ ├── js │ │ ├── annotator-madison.js │ │ ├── app.js │ │ ├── document-edit.js │ │ └── document.js │ ├── sass │ │ ├── annotation.scss │ │ ├── app.scss │ │ ├── document-edit.scss │ │ ├── document-list.scss │ │ ├── document.scss │ │ ├── global.scss │ │ ├── home.scss │ │ ├── mail.scss │ │ └── variables.scss │ └── vendor │ │ └── js │ │ ├── annotator-full.min.js │ │ └── modernizr-custom.js ├── lang │ └── en │ │ ├── auth.php │ │ ├── messages.php │ │ ├── pagination.php │ │ ├── passwords.php │ │ ├── reminders.php │ │ └── validation.php └── views │ ├── admin │ ├── featured-documents.blade.php │ ├── manage-sponsors.blade.php │ ├── manage-users.blade.php │ ├── partials │ │ └── admin-sidebar.blade.php │ └── site-settings.blade.php │ ├── auth │ ├── login.blade.php │ ├── passwords │ │ ├── email.blade.php │ │ └── reset.blade.php │ └── register.blade.php │ ├── components │ ├── breadcrumbs │ │ ├── account.blade.php │ │ ├── admin.blade.php │ │ ├── document.blade.php │ │ ├── pages.blade.php │ │ └── sponsor.blade.php │ ├── date.blade.php │ ├── document-card.blade.php │ ├── errors.blade.php │ ├── form │ │ ├── input.blade.php │ │ ├── select.blade.php │ │ └── submit.blade.php │ ├── pagination.blade.php │ └── relative-time.blade.php │ ├── documents │ ├── comments-page.blade.php │ ├── list.blade.php │ ├── manage │ │ ├── comments.blade.php │ │ └── settings.blade.php │ ├── partials │ │ ├── comment-base.blade.php │ │ ├── comment-card.blade.php │ │ ├── comment-reply.blade.php │ │ ├── comment_table.blade.php │ │ ├── comments.blade.php │ │ ├── new-comment-form.blade.php │ │ └── support-btns.blade.php │ └── show.blade.php │ ├── emails │ ├── daily_notifications.blade.php │ ├── password.blade.php │ ├── sponsor_onboarding │ │ ├── participate.blade.php │ │ ├── prepare.blade.php │ │ └── publish.blade.php │ └── verify_email.blade.php │ ├── errors │ ├── 403.blade.php │ ├── 404.blade.php │ ├── 500.blade.php │ ├── 503.blade.php │ └── partials │ │ └── error_content.blade.php │ ├── home.blade.php │ ├── home │ └── partials │ │ ├── document-card.blade.php │ │ └── welcome.blade.php │ ├── layouts │ ├── app.blade.php │ ├── embed.blade.php │ └── social.blade.php │ ├── pages │ ├── create.blade.php │ ├── edit.blade.php │ ├── list.blade.php │ └── show.blade.php │ ├── partials │ ├── closed-discussion-icon.blade.php │ ├── hotjar-script.blade.php │ └── rollbar-script.blade.php │ ├── sponsor_members │ ├── create.blade.php │ └── list.blade.php │ ├── sponsors │ ├── awaiting-approval.blade.php │ ├── create.blade.php │ ├── documents-list.blade.php │ ├── edit.blade.php │ ├── guide.blade.php │ ├── info.blade.php │ ├── list.blade.php │ ├── onboarding │ │ ├── combined.blade.php │ │ └── en │ │ │ ├── participate.blade.php │ │ │ ├── prepare.blade.php │ │ │ └── publish.blade.php │ └── partials │ │ ├── form.blade.php │ │ ├── sponsor-sidebar.blade.php │ │ └── table.blade.php │ ├── users │ ├── settings.blade.php │ └── settings │ │ ├── account.blade.php │ │ ├── notifications.blade.php │ │ └── password.blade.php │ └── vendor │ └── notifications │ └── email.blade.php ├── routes ├── api.php ├── channels.php ├── console.php └── web.php ├── server.php ├── storage ├── app │ └── .gitignore ├── framework │ ├── .gitignore │ ├── cache │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ └── views │ │ └── .gitignore └── logs │ └── .gitignore ├── tests ├── Browser │ ├── Admin │ │ ├── CustomPagesTest.php │ │ ├── FeaturedDocumentsTest.php │ │ ├── ManageSponsorsTest.php │ │ ├── ManageUsersTest.php │ │ └── SiteSettingsTest.php │ ├── AdminTestCase.php │ ├── Document │ │ ├── ListTest.php │ │ └── Manage │ │ │ ├── CommentsTest.php │ │ │ └── SettingsTest.php │ ├── DocumentPageTest.php │ ├── ExampleTest.php │ ├── HomeTest.php │ ├── LoginTest.php │ ├── LogoutTest.php │ ├── PageTest.php │ ├── Pages │ │ ├── Admin │ │ │ ├── CustomPagesPage.php │ │ │ ├── FeaturedDocumentsPage.php │ │ │ ├── ManageSponsorsPage.php │ │ │ ├── ManageUsersPage.php │ │ │ └── SiteSettingsPage.php │ │ ├── CustomPages │ │ │ ├── CreatePage.php │ │ │ └── EditPage.php │ │ ├── Document │ │ │ ├── ListPage.php │ │ │ └── Manage │ │ │ │ ├── CommentsPage.php │ │ │ │ └── SettingsPage.php │ │ ├── DocumentPage.php │ │ ├── HomePage.php │ │ ├── LoginPage.php │ │ ├── Page.php │ │ ├── RegisterPage.php │ │ ├── Sponsor │ │ │ ├── CreatePage.php │ │ │ ├── DocumentsPage.php │ │ │ ├── EditPage.php │ │ │ └── MembersPage.php │ │ └── User │ │ │ └── Settings │ │ │ ├── AccountPage.php │ │ │ ├── NotificationsPage.php │ │ │ └── PasswordPage.php │ ├── RegisterTest.php │ ├── SponsorTest.php │ ├── UserTest.php │ ├── console │ │ └── .gitignore │ └── screenshots │ │ └── .gitignore ├── CreatesApplication.php ├── DuskTestCase.php ├── FactoryHelpers.php ├── Feature │ ├── Document │ │ └── Manage │ │ │ └── CommentsTest.php │ └── ExampleTest.php ├── TestCase.php └── Unit │ ├── ExampleTest.php │ ├── Notifications │ └── NotificationTest.php │ └── Services │ └── SearchQueryCompilerTest.php └── yarn.lock /.arcconfig: -------------------------------------------------------------------------------- 1 | { 2 | "phabricator.uri": "https://phabricator.opengovfoundation.org/", 3 | "base": "git:merge-base(origin/master), arc:prompt" 4 | } 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 2 9 | trim_trailing_whitespace = true 10 | 11 | [*.js] 12 | indent_style = space 13 | indent_size = 2 14 | 15 | [*.php] 16 | indent_style = space 17 | indent_size = 4 18 | 19 | [*.apib] 20 | indent_style = space 21 | indent_size = 4 22 | 23 | [Makefile] 24 | indent_style = tab 25 | -------------------------------------------------------------------------------- /.env.dusk.testing.example: -------------------------------------------------------------------------------- 1 | APP_ENV=testing 2 | APP_NAME='Madison' 3 | APP_URL='http://localhost' 4 | APP_DEBUG=true 5 | 6 | DB_DATABASE=homestead_testing 7 | DB_USERNAME=homestead 8 | DB_PASSWORD=secret 9 | 10 | BROADCAST_DRIVER=log 11 | CACHE_DRIVER=array 12 | SESSION_DRIVER=database 13 | QUEUE_DRIVER=sync 14 | MAIL_DRIVER=log 15 | -------------------------------------------------------------------------------- /.env.testing.example: -------------------------------------------------------------------------------- 1 | APP_ENV=testing 2 | APP_NAME='Madison' 3 | APP_URL='http://localhost' 4 | APP_DEBUG=true 5 | 6 | DB_DATABASE=homestead_testing 7 | DB_USERNAME=homestead 8 | DB_PASSWORD=secret 9 | 10 | BROADCAST_DRIVER=log 11 | CACHE_DRIVER=array 12 | SESSION_DRIVER=file 13 | QUEUE_DRIVER=sync 14 | MAIL_DRIVER=log 15 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.css linguist-vendored 3 | *.less linguist-vendored 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .env.testing 3 | .env.dusk.testing 4 | .vagrant 5 | 6 | node_modules 7 | storage/db_backups 8 | vendor 9 | 10 | # Mostly generated by Gulp/Elixir 11 | public 12 | # Except a few things 13 | !public/.htaccess 14 | !public/index.php 15 | !public/robots.txt 16 | !public/web.config 17 | 18 | # OS 19 | shared 20 | .settings/ 21 | .DS_Store 22 | .buildpath 23 | .project 24 | .tmp 25 | 26 | log/ 27 | -------------------------------------------------------------------------------- /Homestead.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | ip: "192.168.10.10" 3 | memory: 2048 4 | cpus: 1 5 | hostname: madison 6 | name: madison 7 | provider: virtualbox 8 | mariadb: true 9 | 10 | authorize: ~/.ssh/id_rsa.pub 11 | 12 | keys: 13 | - ~/.ssh/id_rsa 14 | 15 | folders: 16 | - map: "." 17 | to: "/vagrant" 18 | 19 | sites: 20 | - map: madison.app 21 | to: "/vagrant/public" 22 | 23 | databases: 24 | - homestead 25 | - homestead_testing 26 | 27 | # blackfire: 28 | # - id: foo 29 | # token: bar 30 | # client-id: foo 31 | # client-token: bar 32 | 33 | # ports: 34 | # - send: 50000 35 | # to: 5000 36 | # - send: 7777 37 | # to: 777 38 | # protocol: udp 39 | -------------------------------------------------------------------------------- /after.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Fix MariaDB 4 | 5 | sudo ln -sf /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/usr.sbin.mysqld 6 | 7 | sudo systemctl restart apparmor 8 | sudo systemctl restart mysql 9 | 10 | 11 | # Setup stuff for Dusk 12 | 13 | sudo apt-get update 14 | 15 | sudo apt-get -y install \ 16 | chromium-browser \ 17 | xvfb \ 18 | gtk2-engines-pixbuf \ 19 | xfonts-cyrillic \ 20 | xfonts-100dpi \ 21 | xfonts-75dpi \ 22 | xfonts-base \ 23 | xfonts-scalable \ 24 | imagemagick \ 25 | x11-apps \ 26 | 27 | sudo tee /etc/systemd/system/xvfb@.service > /dev/null < 22 | * $config = SiteConfigSaver::get(); 23 | * 24 | * 25 | * @see App\Config\Repository\ConfigSaverRepository 26 | */ 27 | class SiteConfigSaver extends Facade 28 | { 29 | /** 30 | * Get the registered component. 31 | * 32 | * @return object 33 | */ 34 | protected static function getFacadeAccessor() 35 | { 36 | return 'siteconfig'; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Console/Commands/Inspire.php: -------------------------------------------------------------------------------- 1 | comment(PHP_EOL.Inspiring::quote().PHP_EOL); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Contracts/Notification.php: -------------------------------------------------------------------------------- 1 | comment = $comment; 24 | $this->parent = $parent; 25 | } 26 | 27 | /** 28 | * Get the channels the event should be broadcast on. 29 | * 30 | * @return array 31 | */ 32 | public function broadcastOn() 33 | { 34 | return []; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /app/Events/CommentFlagged.php: -------------------------------------------------------------------------------- 1 | flag = $flag; 23 | } 24 | 25 | /** 26 | * Get the channels the event should be broadcast on. 27 | * 28 | * @return array 29 | */ 30 | public function broadcastOn() 31 | { 32 | return []; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /app/Events/CommentLiked.php: -------------------------------------------------------------------------------- 1 | like = $like; 23 | } 24 | 25 | /** 26 | * Get the channels the event should be broadcast on. 27 | * 28 | * @return array 29 | */ 30 | public function broadcastOn() 31 | { 32 | return []; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Events/DocumentPublished.php: -------------------------------------------------------------------------------- 1 | document = $document; 25 | $this->instigator = $instigator; 26 | } 27 | 28 | /** 29 | * Get the channels the event should be broadcast on. 30 | * 31 | * @return array 32 | */ 33 | public function broadcastOn() 34 | { 35 | return []; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/Events/SponsorCreated.php: -------------------------------------------------------------------------------- 1 | sponsor = $sponsor; 25 | $this->user = $user; 26 | } 27 | 28 | /** 29 | * Get the channels the event should be broadcast on. 30 | * 31 | * @return array 32 | */ 33 | public function broadcastOn() 34 | { 35 | return []; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/Events/SponsorMemberAdded.php: -------------------------------------------------------------------------------- 1 | sponsorMember = $sponsorMember; 25 | $this->instigator = $instigator; 26 | } 27 | 28 | /** 29 | * Get the channels the event should be broadcast on. 30 | * 31 | * @return array 32 | */ 33 | public function broadcastOn() 34 | { 35 | return []; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/Events/SponsorMemberRemoved.php: -------------------------------------------------------------------------------- 1 | sponsor = $sponsor; 26 | $this->member = $member; 27 | $this->instigator = $instigator; 28 | } 29 | 30 | /** 31 | * Get the channels the event should be broadcast on. 32 | * 33 | * @return array 34 | */ 35 | public function broadcastOn() 36 | { 37 | return []; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Events/SponsorMemberRoleChanged.php: -------------------------------------------------------------------------------- 1 | oldValue = $oldValue; 27 | $this->newValue = $newValue; 28 | $this->sponsorMember = $sponsorMember; 29 | $this->instigator = $instigator; 30 | } 31 | 32 | /** 33 | * Get the channels the event should be broadcast on. 34 | * 35 | * @return array 36 | */ 37 | public function broadcastOn() 38 | { 39 | return []; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Events/SponsorStatusChanged.php: -------------------------------------------------------------------------------- 1 | oldValue = $oldValue; 27 | $this->newValue = $newValue; 28 | $this->sponsor = $sponsor; 29 | $this->instigator = $instigator; 30 | } 31 | 32 | /** 33 | * Get the channels the event should be broadcast on. 34 | * 35 | * @return array 36 | */ 37 | public function broadcastOn() 38 | { 39 | return []; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Events/SupportVoteChanged.php: -------------------------------------------------------------------------------- 1 | oldValue = $oldValue; 27 | $this->newValue = $newValue; 28 | $this->document = $document; 29 | $this->user = $user; 30 | } 31 | 32 | /** 33 | * Get the channels the event should be broadcast on. 34 | * 35 | * @return array 36 | */ 37 | public function broadcastOn() 38 | { 39 | return []; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /app/Events/UserVerificationRequest.php: -------------------------------------------------------------------------------- 1 | user = $user; 23 | } 24 | 25 | /** 26 | * Get the channels the event should be broadcast on. 27 | * 28 | * @return array 29 | */ 30 | public function broadcastOn() 31 | { 32 | return []; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Events/UserVerificationStatusChange.php: -------------------------------------------------------------------------------- 1 | oldValue = $oldValue; 25 | $this->newValue = $newValue; 26 | $this->user = $user; 27 | } 28 | 29 | /** 30 | * Get the channels the event should be broadcast on. 31 | * 32 | * @return array 33 | */ 34 | public function broadcastOn() 35 | { 36 | return []; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ForgotPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('guest'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ResetPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('guest'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | input('msg_id', []) as $msgId) { 15 | $ret[$msgId] = trans($msgId); 16 | } 17 | 18 | return Response::json($ret); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Middleware/EncryptCookies.php: -------------------------------------------------------------------------------- 1 | get()); 21 | View::share('footerPages', Page::where('footer_nav_link', true)->get()); 22 | 23 | return $next($request); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Middleware/RedirectIfAuthenticated.php: -------------------------------------------------------------------------------- 1 | auth = $auth; 26 | } 27 | 28 | /** 29 | * Handle an incoming request. 30 | * 31 | * @param \Illuminate\Http\Request $request 32 | * @param \Closure $next 33 | * @return mixed 34 | */ 35 | public function handle($request, Closure $next) 36 | { 37 | if ($this->auth->check()) { 38 | return redirect('/'); 39 | } 40 | 41 | return $next($request); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/Http/Middleware/UnapprovedSponsorRedirect.php: -------------------------------------------------------------------------------- 1 | route()->parameter('sponsor'); 20 | $isAdmin = $request->user() && $request->user()->isAdmin(); 21 | 22 | if (!$isAdmin && ($sponsor instanceof Sponsor) && !$sponsor->isActive()) { 23 | return redirect()->route('sponsors.awaiting-approval'); 24 | } 25 | 26 | return $next($request); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Http/Middleware/VerifyCsrfToken.php: -------------------------------------------------------------------------------- 1 | 'required|in:up,down,remove', 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Requests/Admin/SiteSettings/Index.php: -------------------------------------------------------------------------------- 1 | 'in:default,' . implode(',', array_keys(AdminController::validDateFormats())), 19 | 'madison.time_format' => 'in:default,' . implode(',', array_keys(AdminController::validTimeFormats())), 20 | 'madison.google_analytics_property_id' => 'regex:/UA-[0-9]+-[0-9]+/', 21 | ]; 22 | 23 | $keys = array_map(function ($key) { 24 | return str_replace('.', '_', $key); 25 | }, array_keys($rules)); 26 | 27 | return array_combine($keys, $rules); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Http/Requests/Admin/Sponsors/Index.php: -------------------------------------------------------------------------------- 1 | 'in:' . implode(',', Sponsor::getStatuses()), 14 | ]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Http/Requests/Admin/Users/Index.php: -------------------------------------------------------------------------------- 1 | 'required|boolean', 13 | ]; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/Http/Requests/AdminRequest.php: -------------------------------------------------------------------------------- 1 | user() && $this->user()->isAdmin(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Http/Requests/Document/Edit.php: -------------------------------------------------------------------------------- 1 | user(); 17 | $document = null; 18 | 19 | foreach (['document', 'documentTrashed'] as $key) { 20 | if (!empty($this->route()->parameter($key))) { 21 | $document = $this->route()->parameter($key); 22 | break; 23 | } 24 | } 25 | 26 | return $user && $user->can('update', $document); 27 | } 28 | 29 | /** 30 | * Get the validation rules that apply to the request. 31 | * 32 | * @return array 33 | */ 34 | public function rules() 35 | { 36 | return [ 37 | // 38 | ]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/Http/Requests/Document/PutSupport.php: -------------------------------------------------------------------------------- 1 | route()->parameter($key))) { 20 | $document = $this->route()->parameter($key); 21 | break; 22 | } 23 | } 24 | 25 | return $this->user() && $document && $document->canUserView($this->user()); 26 | } 27 | 28 | /** 29 | * Get the validation rules that apply to the request. 30 | * 31 | * @return array 32 | */ 33 | public function rules() 34 | { 35 | return [ 36 | // 37 | ]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Http/Requests/Document/Store.php: -------------------------------------------------------------------------------- 1 | input('sponsor_id')) { 20 | $sponsor = Sponsor::find($this->input('sponsor_id')); 21 | 22 | return $this->user()->can('create', [\App\Models\Doc::class, $sponsor]); 23 | } 24 | 25 | return false; 26 | } 27 | 28 | /** 29 | * Get the validation rules that apply to the request. 30 | * 31 | * @return array 32 | */ 33 | public function rules() 34 | { 35 | return [ 36 | 'title' => 'required', 37 | 'sponsor_id' => 'required|integer', 38 | ]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/Http/Requests/Document/View.php: -------------------------------------------------------------------------------- 1 | route()->parameter($key))) { 19 | $document = $this->route()->parameter($key); 20 | break; 21 | } 22 | } 23 | 24 | return $document && $document->canUserView($this->user()); 25 | } 26 | 27 | /** 28 | * Get the validation rules that apply to the request. 29 | * 30 | * @return array 31 | */ 32 | public function rules() 33 | { 34 | return []; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Http/Requests/Page/Create.php: -------------------------------------------------------------------------------- 1 | 'required' 18 | ]; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Requests/Page/Update.php: -------------------------------------------------------------------------------- 1 | 'string|required', 18 | 'nav_title' => 'string|required', 19 | 'header_nav_link' => 'boolean|required', 20 | 'footer_nav_link' => 'boolean|required', 21 | 'external' => 'boolean|required', 22 | 23 | // These not required if the page is external 24 | 'page_title' => 'string' . ($this->input('external') === "1" ? "" : "|required"), 25 | 'header' => 'string' . ($this->input('external') === "1" ? "" : "|required"), 26 | 'page_content' => 'string' . ($this->input('external') === "1" ? "" : "|required"), 27 | ]; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /app/Http/Requests/Sponsor/Create.php: -------------------------------------------------------------------------------- 1 | sponsor->hasMember(Auth::user()->id) || Auth::user()->isAdmin() 19 | ); 20 | } 21 | 22 | /** 23 | * Get the validation rules that apply to the request. 24 | * 25 | * @return array 26 | */ 27 | public function rules() 28 | { 29 | return [ 30 | // 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Http/Requests/Sponsor/Edit.php: -------------------------------------------------------------------------------- 1 | sponsor->isSponsorOwner(Auth::user()->id) || Auth::user()->isAdmin() 19 | ); 20 | } 21 | 22 | /** 23 | * Get the validation rules that apply to the request. 24 | * 25 | * @return array 26 | */ 27 | public function rules() 28 | { 29 | return [ 30 | // 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Http/Requests/Sponsor/Index.php: -------------------------------------------------------------------------------- 1 | 'integer', 30 | 'name' => 'string|nullable', 31 | 'user_id.*' => 'integer', 32 | 'order' => 'in:created_at,updated_at,name', 33 | 'order_dir' => 'in:ASC,DESC', 34 | 'page' => 'integer', 35 | 'statuses' => 'array|in:' . implode(',', Sponsor::getStatuses()), 36 | ]; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Http/Requests/Sponsor/Store.php: -------------------------------------------------------------------------------- 1 | 'string|required|unique:sponsors', 29 | 'display_name' => 'string|required|unique:sponsors', 30 | 'address1' => 'string|required', 31 | 'address2' => 'string', 32 | 'city' => 'string|required', 33 | 'state' => 'string|required', 34 | 'postal_code' => 'string|required', 35 | 'phone' => 'string', 36 | ]; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/Http/Requests/SponsorMember/Create.php: -------------------------------------------------------------------------------- 1 | user(); 19 | 20 | return $currentUser && ( 21 | $currentUser->isAdmin() || $this->sponsor->isSponsorOwner($currentUser->id) 22 | ); 23 | } 24 | 25 | /** 26 | * Get the validation rules that apply to the request. 27 | * 28 | * @return array 29 | */ 30 | public function rules() 31 | { 32 | return [ 33 | // 34 | ]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Http/Requests/SponsorMember/Destroy.php: -------------------------------------------------------------------------------- 1 | user(); 18 | 19 | return $this->sponsor->isActive() || ( 20 | $currentUser && ( 21 | $currentUser->isAdmin() || $this->sponsor->isSponsorOwner($currentUser->id) 22 | ) 23 | ); 24 | } 25 | 26 | /** 27 | * Get the validation rules that apply to the request. 28 | * 29 | * @return array 30 | */ 31 | public function rules() 32 | { 33 | return [ 34 | // 35 | ]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/Http/Requests/SponsorMember/Index.php: -------------------------------------------------------------------------------- 1 | user(); 18 | 19 | return $this->sponsor->isActive() || ( 20 | $currentUser && ( 21 | $currentUser->isAdmin() || $this->sponsor->hasMember($currentUser->id) 22 | ) 23 | ); 24 | } 25 | 26 | /** 27 | * Get the validation rules that apply to the request. 28 | * 29 | * @return array 30 | */ 31 | public function rules() 32 | { 33 | return [ 34 | 'roles' => 'array|in:' . implode(',', Sponsor::getRoles()), 35 | ]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/Http/Requests/SponsorMember/Store.php: -------------------------------------------------------------------------------- 1 | user(); 18 | 19 | return $this->sponsor->isActive() || ( 20 | $currentUser && ( 21 | $currentUser->isAdmin() || $this->sponsor->isSponsorOwner($currentUser->id) 22 | ) 23 | ); 24 | } 25 | 26 | /** 27 | * Get the validation rules that apply to the request. 28 | * 29 | * @return array 30 | */ 31 | public function rules() 32 | { 33 | return [ 34 | 'email' => 'required|email', 35 | 'role' => 'in:' . implode(',', Sponsor::getRoles()), 36 | ]; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Http/Requests/SponsorMember/UpdateRole.php: -------------------------------------------------------------------------------- 1 | user(); 18 | 19 | return $this->sponsor->isActive() || ( 20 | $currentUser && ( 21 | $currentUser->isAdmin() || $this->sponsor->isSponsorOwner($currentUser->id) 22 | ) 23 | ); 24 | } 25 | 26 | /** 27 | * Get the validation rules that apply to the request. 28 | * 29 | * @return array 30 | */ 31 | public function rules() 32 | { 33 | return [ 34 | 'role' => 'required|in:' . implode(',', Sponsor::getRoles()), 35 | ]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/Http/Requests/Translation/Index.php: -------------------------------------------------------------------------------- 1 | 'string', 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Http/Requests/User/Edit.php: -------------------------------------------------------------------------------- 1 | user(); 18 | $userEditing = $this->route()->parameter('user'); 19 | 20 | return $currentUser && ($userEditing == $currentUser || $currentUser->isAdmin()); 21 | } 22 | 23 | /** 24 | * Get the validation rules that apply to the request. 25 | * 26 | * @return array 27 | */ 28 | public function rules() 29 | { 30 | return [ 31 | // 32 | ]; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /app/Http/Requests/User/Settings/UpdateAccount.php: -------------------------------------------------------------------------------- 1 | 'string|required', 18 | 'lname' => 'string|required', 19 | 'email' => 'email|required|unique:users', 20 | ]; 21 | } 22 | 23 | public function messages() 24 | { 25 | return [ 26 | 'fname.required' => 'The first name field is required.', 27 | 'lname.required' => 'The last name field is required.', 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Http/Requests/User/Settings/UpdateNotifications.php: -------------------------------------------------------------------------------- 1 | 'string|min:6|confirmed', 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Requests/User/SponsorsIndex.php: -------------------------------------------------------------------------------- 1 | user(); 19 | $userEditing = $this->route()->parameter('user'); 20 | 21 | return $currentUser && ($userEditing == $currentUser || $currentUser->isAdmin()); 22 | } 23 | 24 | /** 25 | * Get the validation rules that apply to the request. 26 | * 27 | * @return array 28 | */ 29 | public function rules() 30 | { 31 | return [ 32 | 'limit' => 'integer', 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Jobs/Job.php: -------------------------------------------------------------------------------- 1 | flag->rootAnnotatable->sponsors; 18 | $members = $sponsors 19 | ->flatMap(function ($sponsor) { 20 | return $sponsor->members->pluck('user'); 21 | }) 22 | ->unique('id'); 23 | Notification::send($members, new Notifications\CommentFlagged($event->flag)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Listeners/CommentLikedNotification.php: -------------------------------------------------------------------------------- 1 | like->annotatable->user->notify(new Notifications\CommentLiked($event->like)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Listeners/SponsorCreatedNotification.php: -------------------------------------------------------------------------------- 1 | sponsor, $event->user)); 27 | 28 | Mail::to($event->user) 29 | ->send(new SponsorOnboarding\Prepare($event->user)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Listeners/SponsorMemberAddedNotification.php: -------------------------------------------------------------------------------- 1 | sponsorMember->user->notify(new AddedToSponsor($event->sponsorMember, $event->instigator)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Listeners/SponsorMemberRemovedNotification.php: -------------------------------------------------------------------------------- 1 | member->notify(new RemovedFromSponsor($event->sponsor, $event->member, $event->instigator)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Listeners/SponsorMemberRoleChangedNotification.php: -------------------------------------------------------------------------------- 1 | sponsorMember->user->notify(new UserSponsorRoleChanged( 22 | $event->oldValue, 23 | $event->newValue, 24 | $event->sponsorMember, 25 | $event->instigator 26 | )); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Listeners/SponsorStatusChangedNotification.php: -------------------------------------------------------------------------------- 1 | newValue === Sponsor::STATUS_ACTIVE) { 23 | foreach ($event->sponsor->members->pluck('user') as $member) { 24 | Mail::to($member) 25 | ->send(new SponsorOnboarding\Publish($event->sponsor, $member)); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Listeners/UserVerificationRequestNotification.php: -------------------------------------------------------------------------------- 1 | $event->user, 25 | // ]; 26 | 27 | // $admins = User::findByRoleName(Role::ROLE_ADMIN); 28 | 29 | // $this->notifier->queue('email.notification.verify_request_user', $data, function($message) use ($admins) { 30 | // $message->setSubject('New user requesting account verification'); 31 | // $message->setRecipients($admins); 32 | // }, $event); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Listeners/UserVerificationStatusChangeNotification.php: -------------------------------------------------------------------------------- 1 | oldValue} to {$event->newValue}."; 20 | // $data = [ 21 | // 'text' => $text, 22 | // ]; 23 | // $recipient = $event->user; 24 | 25 | // $this->notifier->queue('notification.simple-html', $data, function ($message) use ($recipient) { 26 | // $message->setSubject('Your account verification status has changed'); 27 | // $message->setRecipients($recipient); 28 | // }, $event); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Mail/EmailVerification.php: -------------------------------------------------------------------------------- 1 | user = $user; 25 | } 26 | 27 | /** 28 | * Build the message. 29 | * 30 | * @return $this 31 | */ 32 | public function build() 33 | { 34 | return $this 35 | ->subject(trans('messages.email_verification.ask')) 36 | ->markdown('emails.verify_email'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Mail/SponsorOnboarding/Engage.php: -------------------------------------------------------------------------------- 1 | user = $user; 26 | } 27 | 28 | /** 29 | * Build the message. 30 | * 31 | * @return $this 32 | */ 33 | public function build() 34 | { 35 | return $this 36 | ->subject(trans('messages.sponsor.onboarding.participate.subject')) 37 | ->markdown('emails.sponsor_onboarding.participate'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Mail/SponsorOnboarding/Prepare.php: -------------------------------------------------------------------------------- 1 | user = $user; 25 | } 26 | 27 | /** 28 | * Build the message. 29 | * 30 | * @return $this 31 | */ 32 | public function build() 33 | { 34 | return $this 35 | ->subject(trans('messages.sponsor.onboarding.prepare.subject')) 36 | ->markdown('emails.sponsor_onboarding.prepare'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Mail/SponsorOnboarding/Publish.php: -------------------------------------------------------------------------------- 1 | sponsor = $sponsor; 27 | $this->user = $user; 28 | } 29 | 30 | /** 31 | * Build the message. 32 | * 33 | * @return $this 34 | */ 35 | public function build() 36 | { 37 | return $this 38 | ->subject(trans('messages.sponsor.onboarding.publish.subject')) 39 | ->markdown('emails.sponsor_onboarding.publish'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Models/ActivityInterface.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\Models\Annotation'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Models/AnnotationTypes/Flag.php: -------------------------------------------------------------------------------- 1 | morphOne('App\Models\Annotation', 'annotation_type'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Models/AnnotationTypes/Hidden.php: -------------------------------------------------------------------------------- 1 | morphOne('App\Models\Annotation', 'annotation_type'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Models/AnnotationTypes/Like.php: -------------------------------------------------------------------------------- 1 | morphOne('App\Models\Annotation', 'annotation_type'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Models/AnnotationTypes/Range.php: -------------------------------------------------------------------------------- 1 | morphOne('App\Models\Annotation', 'annotation_type'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Models/AnnotationTypes/Resolved.php: -------------------------------------------------------------------------------- 1 | morphOne('App\Models\Annotation', 'annotation_type'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Models/AnnotationTypes/Seen.php: -------------------------------------------------------------------------------- 1 | morphOne('App\Models\Annotation', 'annotation_type'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Models/AnnotationTypes/Tag.php: -------------------------------------------------------------------------------- 1 | morphOne('App\Models\Annotation', 'annotation_type'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Models/DocMeta.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\Models\Doc'); 25 | } 26 | 27 | public function user() 28 | { 29 | return $this->belongsTo('App\Models\User'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Models/LoginToken.php: -------------------------------------------------------------------------------- 1 | token)) { 23 | $token->token = str_random(20); 24 | } 25 | 26 | if (empty($token->expires_at)) { 27 | $token->expires_at = Carbon::now()->addDay(); 28 | } 29 | }); 30 | } 31 | 32 | public function user() 33 | { 34 | return $this->belongsTo('App\Models\User'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Models/PageContent.php: -------------------------------------------------------------------------------- 1 | belongsTo(Page::class); 27 | } 28 | 29 | /** 30 | * Return HTML version of page content 31 | */ 32 | public function html() 33 | { 34 | return Markdown::convertToHtml($this->content); 35 | } 36 | 37 | /** 38 | * Return Markdown version of page content 39 | */ 40 | public function markdown() 41 | { 42 | return $this->content; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/Models/Permission.php: -------------------------------------------------------------------------------- 1 | first() ?: static::create(['name' => static::ROLE_ADMIN]); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Models/Setting.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\Models\User'); 22 | } 23 | 24 | public function sponsor() 25 | { 26 | return $this->belongsTo('App\Models\Sponsor'); 27 | } 28 | 29 | public static function findBySponsorId($sponsorId) 30 | { 31 | return static::where('sponsor_id', '=', $sponsorId)->get(); 32 | } 33 | 34 | public function getNameAttribute() 35 | { 36 | return "{$this->user->display_name}"; 37 | } 38 | 39 | public function getEmailAttribute() 40 | { 41 | return "{$this->user->email}"; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/Notifications/Messages/MailMessage.php: -------------------------------------------------------------------------------- 1 | viewData['notification'] = $notification; 14 | $this->viewData['notifiable'] = $notifiable; 15 | $this->viewData['unsubscribeMarkdown'] = NotificationPreference::getUnsubscribeMarkdown($notification, $notifiable); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Notifications/UserMembershipChanged.php: -------------------------------------------------------------------------------- 1 | instigator = $instigator; 24 | } 25 | 26 | 27 | public static function getName() 28 | { 29 | return 'madison.user.sponsor_membership_changed'; 30 | } 31 | 32 | public static function getType() 33 | { 34 | return static::TYPE_USER; 35 | } 36 | 37 | public function getInstigator() 38 | { 39 | return $this->instigator; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Policies/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengovfoundation/madison/a510f15f82a0aa543b0087c4b72e2e0809b92875/app/Policies/.gitkeep -------------------------------------------------------------------------------- /app/Policies/Policy.php: -------------------------------------------------------------------------------- 1 | isAdmin()) { 10 | return true; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/Providers/AuthServiceProvider.php: -------------------------------------------------------------------------------- 1 | \App\Policies\DocumentPolicy::class, 17 | ]; 18 | 19 | /** 20 | * Register any authentication / authorization services. 21 | * 22 | * @return void 23 | */ 24 | public function boot() 25 | { 26 | $this->registerPolicies(); 27 | 28 | // 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | connection($connection); 16 | $table = $db->getTablePrefix().$app['config']['session.table']; 17 | return new PdoEventSessionHandler($db->getPdo(), array( 18 | 'db_table' => $table, 19 | 'db_id_col' => 'id', 20 | 'db_data_col' => 'payload', 21 | 'db_time_col' => 'last_activity') 22 | ); 23 | }); 24 | } 25 | 26 | public function provides() 27 | { 28 | return array( 29 | 'App\\Session\\Storage\\Handler\\PdoEventSessionHandler', 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Providers/SessionRejectServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->bind('session.reject', 15 | function ($app) use ($me) { 16 | return function ($request) use ($me) { 17 | return call_user_func_array(array($me, 'reject'), array($request)); 18 | }; 19 | } 20 | ); 21 | } 22 | 23 | protected function reject($request) 24 | { 25 | return ($request->isMethod('get') && $request->is('api/docs')); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Providers/UserServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->bind( 14 | 'Madison\\Storage\\Interfaces\\UserRepositoryInterface', 15 | 'Madison\\Storage\\UserRepository' 16 | ); 17 | } 18 | 19 | public function provides() 20 | { 21 | return array( 22 | 'Madison\\Storage\\Interfaces\\UserRepositoryInterface', 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Services/UniqId.php: -------------------------------------------------------------------------------- 1 | 4 | DocumentRoot /home/ubuntu/{{REPO}}/public 5 | 6 | 7 | Options Indexes FollowSymLinks MultiViews ExecCGI 8 | DirectoryIndex index.php 9 | AllowOverride all 10 | 11 | Order allow,deny 12 | Allow from all 13 | Require all granted 14 | 15 | 16 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite 2 | -------------------------------------------------------------------------------- /database/migrations/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengovfoundation/madison/a510f15f82a0aa543b0087c4b72e2e0809b92875/database/migrations/.gitkeep -------------------------------------------------------------------------------- /database/migrations/2013_03_06_203506_create_docs_table.php: -------------------------------------------------------------------------------- 1 | engine = "InnoDB"; 14 | $table->increments('id'); 15 | $table->string('title'); 16 | $table->string('slug')->unique(); 17 | $table->string('shortname')->nullable(); 18 | $table->integer('init_section')->unsigned()->nullable(); 19 | $table->timestamps(); 20 | }); 21 | } 22 | 23 | /** 24 | * Revert the changes to the database. 25 | */ 26 | public function down() 27 | { 28 | Schema::drop('docs'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2013_03_06_203542_create_organizations_table.php: -------------------------------------------------------------------------------- 1 | engine = "InnoDB"; 14 | $table->increments('id'); 15 | $table->string('name'); 16 | $table->string('zip'); 17 | $table->string('url'); 18 | $table->timestamps(); 19 | }); 20 | } 21 | 22 | /** 23 | * Revert the changes to the database. 24 | */ 25 | public function down() 26 | { 27 | Schema::drop('organizations'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /database/migrations/2013_03_06_203600_create_settings_table.php: -------------------------------------------------------------------------------- 1 | engine = "InnoDB"; 14 | $table->increments('id'); 15 | $table->string('meta_key'); 16 | $table->string('meta_value')->nullable(); 17 | $table->timestamps(); 18 | }); 19 | } 20 | 21 | /** 22 | * Revert the changes to the database. 23 | */ 24 | public function down() 25 | { 26 | Schema::drop('settings'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /database/migrations/2013_03_06_203617_create_doc_meta_table.php: -------------------------------------------------------------------------------- 1 | engine = "InnoDB"; 14 | $table->increments('id'); 15 | $table->integer('doc_id')->unsigned(); 16 | $table->string('meta_key'); 17 | $table->string('meta_value')->nullable(); 18 | $table->timestamps(); 19 | 20 | //Set foreign keys 21 | $table->foreign('doc_id')->references('id')->on('docs')->on_delete('cascade'); 22 | }); 23 | } 24 | 25 | /** 26 | * Revert the changes to the database. 27 | */ 28 | public function down() 29 | { 30 | Schema::drop('doc_meta'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2013_04_10_012922_create_note_meta_table.php: -------------------------------------------------------------------------------- 1 | engine = "InnoDB"; 14 | $table->increments('id'); 15 | $table->string('note_id'); 16 | $table->integer('user_id')->unsigned()->nullable(); 17 | $table->string('meta_key'); 18 | $table->string('meta_value')->nullable(); 19 | $table->timestamps(); 20 | 21 | //Set foreign keys 22 | $table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); 23 | }); 24 | } 25 | 26 | /** 27 | * Revert the changes to the database. 28 | */ 29 | public function down() 30 | { 31 | Schema::drop('note_meta'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2014_01_30_175108_create_comments_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 14 | $table->integer('user_id')->unsigned(); 15 | $table->integer('doc_id')->unsigned(); 16 | $table->text('content'); 17 | $table->timestamps(); 18 | 19 | $table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); 20 | $table->foreign('doc_id')->references('id')->on('docs')->on_delete('cascade'); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | */ 27 | public function down() 28 | { 29 | Schema::drop('users'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2014_02_03_224850_add_user_to_doc_meta.php: -------------------------------------------------------------------------------- 1 | integer('user_id')->after('doc_id')->unsigned()->nullable(); 14 | 15 | $table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down() 23 | { 24 | Schema::table('doc_meta', function ($table) { 25 | $table->dropForeign('user_id_foreign'); 26 | 27 | $table->dropColumn('user_id'); 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2014_02_03_232541_add_doc_meta_key.php: -------------------------------------------------------------------------------- 1 | unique(array('doc_id', 'user_id', 'meta_key')); 14 | }); 15 | } 16 | 17 | /** 18 | * Reverse the migrations. 19 | */ 20 | public function down() 21 | { 22 | Schema::table('doc_meta', function ($table) { 23 | $table->dropUnique('doc_meta_doc_id_user_id_meta_key_unique'); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /database/migrations/2014_02_11_204013_add_user_meta_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 14 | $table->integer('user_id')->unsigned(); 15 | $table->string('meta_key'); 16 | $table->string('meta_value'); 17 | $table->timestamps(); 18 | 19 | $table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | */ 26 | public function down() 27 | { 28 | Schema::drop('user_meta'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2014_02_11_212039_add_user_meta_key.php: -------------------------------------------------------------------------------- 1 | unique(array('user_id', 'meta_key')); 14 | }); 15 | } 16 | 17 | /** 18 | * Reverse the migrations. 19 | */ 20 | public function down() 21 | { 22 | Schema::table('user_meta', function ($table) { 23 | $table->dropUnique('user_meta_user_id_meta_key_unique'); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /database/migrations/2014_02_18_221127_create_doc_categories_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 14 | $table->string('name')->unique(); 15 | $table->timestamps(); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down() 23 | { 24 | Schema::drop('categories'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /database/migrations/2014_02_18_230809_create_category_doc_table.php: -------------------------------------------------------------------------------- 1 | integer('doc_id')->unsigned(); 14 | $table->integer('category_id')->unsigned(); 15 | 16 | $table->foreign('doc_id')->references('id')->on('docs')->onDelete('cascade'); 17 | $table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade'); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | */ 24 | public function down() 25 | { 26 | Schema::drop('category_doc'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /database/migrations/2014_02_20_003208_create_doc_user_table.php: -------------------------------------------------------------------------------- 1 | integer('doc_id')->unsigned(); 14 | $table->integer('user_id')->unsigned(); 15 | 16 | $table->foreign('doc_id')->references('id')->on('docs')->onDelete('cascade'); 17 | $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | */ 24 | public function down() 25 | { 26 | Schema::drop('doc_user'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /database/migrations/2014_02_20_003949_create_roles_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 14 | $table->string('label'); 15 | $table->string('permissions'); 16 | $table->timestamps(); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | */ 23 | public function down() 24 | { 25 | Schema::drop('roles'); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /database/migrations/2014_02_20_004504_create_role_user_table.php: -------------------------------------------------------------------------------- 1 | integer('role_id')->unsigned(); 14 | $table->integer('user_id')->unsigned(); 15 | 16 | $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade'); 17 | $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | */ 24 | public function down() 25 | { 26 | Schema::drop('role_user'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /database/migrations/2014_02_20_191548_create_password_reminders_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 15 | $table->string('token')->index(); 16 | $table->timestamp('created_at'); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | */ 23 | public function down() 24 | { 25 | Schema::drop('password_reminders'); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /database/migrations/2014_02_20_222629_create_statuses_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 14 | $table->string('label'); 15 | $table->timestamps(); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down() 23 | { 24 | Schema::drop('statuses'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /database/migrations/2014_02_20_224328_create_doc_status_table.php: -------------------------------------------------------------------------------- 1 | integer('doc_id')->unsigned(); 14 | $table->integer('status_id')->unsigned(); 15 | 16 | $table->foreign('doc_id')->references('id')->on('docs')->onDelete('cascade'); 17 | $table->foreign('status_id')->references('id')->on('statuses')->onDelete('cascade'); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | */ 24 | public function down() 25 | { 26 | Schema::drop('doc_status'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /database/migrations/2014_02_24_205855_create_dates_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 14 | $table->integer('doc_id')->unsigned(); 15 | $table->datetime('date'); 16 | $table->string('label'); 17 | $table->timestamps(); 18 | 19 | $table->foreign('doc_id')->references('id')->on('docs')->onDelete('cascade'); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | */ 26 | public function down() 27 | { 28 | Schema::drop('dates'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2014_03_05_174637_create_annotation_tags_table.php: -------------------------------------------------------------------------------- 1 | engine = "InnoDB"; 14 | 15 | $table->increments('id'); 16 | $table->integer('annotation_id')->unsigned(); 17 | $table->string('tag'); 18 | $table->timestamps(); 19 | 20 | $table->foreign('annotation_id')->references('id')->on('annotations')->on_delete('cascade'); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | */ 27 | public function down() 28 | { 29 | Schema::drop('annotation_tags'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2014_03_17_150518_alter_note_meta_table.php: -------------------------------------------------------------------------------- 1 | dropColumn('note_id'); 12 | $table->integer('annotation_id')->unsigned(); 13 | }); 14 | } 15 | 16 | public function down() 17 | { 18 | Schema::table('note_meta', function ($table) { 19 | $table->string('note_id'); 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /database/migrations/2014_03_17_152535_add_foreign_index_note_meta.php: -------------------------------------------------------------------------------- 1 | foreign('annotation_id')->references('id')->on('annotations')->on_delete('cascade'); 14 | }); 15 | } 16 | 17 | /** 18 | * Reverse the migrations. 19 | */ 20 | public function down() 21 | { 22 | Schema::table('note_meta', function ($table) { 23 | $table->dropIndex('note_meta_annotation_id_foreign'); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /database/migrations/2014_03_18_071119_drop_annotation_meta_columns.php: -------------------------------------------------------------------------------- 1 | dropColumn('likes'); 12 | $table->dropColumn('dislikes'); 13 | $table->dropColumn('flags'); 14 | }); 15 | } 16 | 17 | public function down() 18 | { 19 | Schema::table('annotations', function ($table) { 20 | $table->integer('likes'); 21 | $table->integer('dislikes'); 22 | $table->integer('flags'); 23 | }); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /database/migrations/2014_03_18_073947_make_annotations_search_id_nullable.php: -------------------------------------------------------------------------------- 1 | integer('parent_id')->unsigned()->after('doc_id')->nullable(); 12 | 13 | $table->foreign('parent_id')->references('id')->on('comments')->onDelete('cascade'); 14 | }); 15 | } 16 | 17 | public function down() 18 | { 19 | Schema::table('comments', function ($table) { 20 | $table->dropForeign('comments_parent_id_foreign'); 21 | $table->dropColumn('parent_id'); 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /database/migrations/2014_03_21_170432_create_comment_meta_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 14 | $table->integer('comment_id')->unsigned(); 15 | $table->integer('user_id')->unsigned()->nullable(); 16 | $table->string('meta_key'); 17 | $table->string('meta_value')->nullable(); 18 | $table->timestamps(); 19 | 20 | //Set foreign keys 21 | $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); 22 | $table->foreign('comment_id')->references('id')->on('comments')->onDelete('cascade'); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | */ 29 | public function down() 30 | { 31 | Schema::drop('comment_meta'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2014_03_26_220409_rename_doc_column_in_annotations.php: -------------------------------------------------------------------------------- 1 | dropForeign('annotations_doc_foreign'); 12 | $table->renameColumn('doc', 'doc_id'); 13 | 14 | $table->foreign('doc_id')->references('id')->on('docs')->onDelete('cascade'); 15 | }); 16 | } 17 | 18 | public function down() 19 | { 20 | Schema::table('annotations', function ($table) { 21 | $table->dropForeign('annotations_doc_id_foreign'); 22 | $table->renameColumn('doc_id', 'doc'); 23 | 24 | $table->foreign('doc')->references('id')->on('docs'); 25 | }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /database/migrations/2014_03_26_220422_rename_content_column_in_comments.php: -------------------------------------------------------------------------------- 1 | renameColumn('content', 'text'); 12 | }); 13 | } 14 | 15 | public function down() 16 | { 17 | Schema::table('comments', function ($table) { 18 | $table->renameColumn('text', 'content'); 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /database/migrations/2014_03_28_201831_add_seen_columns.php: -------------------------------------------------------------------------------- 1 | tinyInteger('seen')->after('text')->default(0); 14 | }); 15 | Schema::table('annotations', function ($table) { 16 | $table->tinyInteger('seen')->after('uri')->default(0); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | */ 23 | public function down() 24 | { 25 | Schema::table('comments', function ($table) { 26 | $table->dropColumn('seen'); 27 | }); 28 | Schema::table('annotations', function ($table) { 29 | $table->dropColumn('seen'); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2014_04_03_064948_drop_user_level_column.php: -------------------------------------------------------------------------------- 1 | dropColumn('user_level'); 12 | }); 13 | } 14 | 15 | public function down() 16 | { 17 | Schema::table('users', function ($table) { 18 | $table->integer('user_level'); 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /database/migrations/2014_05_05_173053_add_groups_to_documents.php: -------------------------------------------------------------------------------- 1 | integer('doc_id')->unsigned(); 14 | $table->integer('group_id')->unsigned(); 15 | 16 | $table->foreign('doc_id')->references('id')->on('docs')->onDelete('cascade'); 17 | $table->foreign('group_id')->references('id')->on('groups')->onDelete('cascade'); 18 | 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | */ 25 | public function down() 26 | { 27 | Schema::drop('doc_group'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /database/migrations/2014_05_22_163151_alter_annotations_increase_field_length.php: -------------------------------------------------------------------------------- 1 | string('oauth_vendor', 16)->nullable(); 14 | $table->string('oauth_id')->nullable(); 15 | $table->boolean('oauth_update')->nullable(); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down() 23 | { 24 | Schema::table('users', function ($table) { 25 | $table->dropColumn('oauth_vendor'); 26 | $table->dropColumn('oauth_id'); 27 | $table->dropColumn('oauth_update'); 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2014_08_05_220609_make_user_token_default_empty.php: -------------------------------------------------------------------------------- 1 | text('thumbnail')->after('shortname')->nullable(); 14 | }); 15 | } 16 | 17 | /** 18 | * Reverse the migrations. 19 | */ 20 | public function down() 21 | { 22 | Schema::table('docs', function ($table) { 23 | $table->dropColumn('thumbnail'); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /database/migrations/2015_07_10_182013_create_session_table.php: -------------------------------------------------------------------------------- 1 | string('id')->unique(); 17 | $t->text('payload'); 18 | $t->integer('last_activity'); 19 | }); 20 | } 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::drop('sessions'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2015_07_10_232617_add_userid_to_session_table.php: -------------------------------------------------------------------------------- 1 | integer('user_id')->unsigned(); 18 | }); 19 | } 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::table('sessions', function (Blueprint $table) { 30 | $table->dropColumn('user_id'); 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2015_09_11_144251_private_flag.php: -------------------------------------------------------------------------------- 1 | boolean('private')->default(0); 15 | $table->index('private'); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down() 23 | { 24 | Schema::table('docs', function ($table) { 25 | // The name of the index is different than what we create it as. 26 | $table->dropIndex('docs_private_index'); 27 | $table->dropColumn('private'); 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2015_10_15_192134_doc_template_flag.php: -------------------------------------------------------------------------------- 1 | boolean('is_template')->default(0); 15 | $table->index('is_template'); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down() 23 | { 24 | Schema::table('docs', function ($table) { 25 | // The name of the index is different than what we create it as. 26 | $table->dropIndex('docs_is_template_index'); 27 | $table->dropColumn('is_template'); 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2015_11_15_184015_make_sessions_user_id_nullable.php: -------------------------------------------------------------------------------- 1 | string('remember_token', 100)->nullable(); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | * 23 | * @return void 24 | */ 25 | public function down() 26 | { 27 | Schema::table('users', function(Blueprint $table) { 28 | $table->dropColumn('remember_token'); 29 | }); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2015_12_01_142343_change_assigned_roles_to_role_user.php: -------------------------------------------------------------------------------- 1 | string('display_name')->nullable(); 17 | $table->string('description')->nullable(); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::table('roles', function ($table) { 29 | $table->dropColumn('display_name'); 30 | $table->dropColumn('description'); 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2015_12_01_142514_add_new_entrust_columns_to_permissions.php: -------------------------------------------------------------------------------- 1 | string('description')->nullable(); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | * 23 | * @return void 24 | */ 25 | public function down() 26 | { 27 | Schema::table('permissions', function ($table) { 28 | $table->dropColumn('description'); 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2016_01_11_213954_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 17 | $table->string('token')->index(); 18 | $table->timestamp('created_at'); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::drop('password_resets'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2016_01_20_220338_add_publish_state_to_docs.php: -------------------------------------------------------------------------------- 1 | string('publish_state')->default('unpublished'); 17 | }); 18 | 19 | DB::update("update docs set publish_state = 'published' where private = 0"); 20 | DB::update("update docs set publish_state = 'private' where private = 1"); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::table('docs', function($table) { 31 | $table->dropColumn('publish_state'); 32 | }); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2016_01_20_220346_remove_private_from_docs.php: -------------------------------------------------------------------------------- 1 | dropColumn('private'); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | * 23 | * @return void 24 | */ 25 | public function down() 26 | { 27 | Schema::table('docs', function($table) { 28 | $table->boolean('private')->default(0); 29 | }); 30 | 31 | // TODO: Find a way to recover non-published states. Write to file? 32 | DB::update("update docs set private = 0 where publish_state = 'published'"); 33 | DB::update("update docs set private = 1 where publish_state != 'published'"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2016_02_01_190330_change_doc_types.php: -------------------------------------------------------------------------------- 1 | string('discussion_state')->default('open'); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | * 23 | * @return void 24 | */ 25 | public function down() 26 | { 27 | Schema::table('docs', function($table) { 28 | $table->dropColumn('discussion_state'); 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2016_03_01_023454_doc_slug_not_unique.php: -------------------------------------------------------------------------------- 1 | dropIndex('docs_slug_unique'); 18 | $table->index('slug'); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::table('docs', function($table) 30 | { 31 | $table->dropIndex('docs_slug_index'); 32 | $table->unique('slug'); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2016_03_07_202808_add_individual_flag_to_groups.php: -------------------------------------------------------------------------------- 1 | boolean('individual')->default(false); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | * 23 | * @return void 24 | */ 25 | public function down() 26 | { 27 | Schema::table('groups', function($table) { 28 | $table->dropColumn('individual'); 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2016_03_22_124953_rename_phone_number_column_on_groups.php: -------------------------------------------------------------------------------- 1 | integer('user_id')->nullable(); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | * 23 | * @return void 24 | */ 25 | public function down() 26 | { 27 | Schema::table('groups', function($table) { 28 | $table->dropColumn('user_id'); 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2016_04_07_164123_create_page_contents_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->integer('page_id')->unsigned(); 18 | $table->text('content'); 19 | $table->timestamps(); 20 | 21 | // Foreign keys 22 | $table->foreign('page_id')->references('id')->on('pages')->on_delete('cascade'); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::drop('page_contents'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2016_04_26_153504_create_failed_jobs_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->text('connection'); 18 | $table->text('queue'); 19 | $table->longText('payload'); 20 | $table->timestamp('failed_at')->useCurrent(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::drop('failed_jobs'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2016_04_27_200919_rename_notifications_to_notification_preferences.php: -------------------------------------------------------------------------------- 1 | dropColumn('user_id'); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | * 23 | * @return void 24 | */ 25 | public function down() 26 | { 27 | Schema::table('groups', function($table) { 28 | $table->integer('user_id')->nullable(); 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2016_12_05_182306_database_sessions_driver_changes.php: -------------------------------------------------------------------------------- 1 | string('ip_address', 45)->nullable(); 18 | $table->text('user_agent')->nullable(); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::table('sessions', function (Blueprint $table) { 30 | $table->dropColumn('ip_address'); 31 | $table->dropColumn('user_agent'); 32 | }); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2016_12_16_183722_fix_document_thumbnail_url.php: -------------------------------------------------------------------------------- 1 | where('event', 'madison.sponsor.created') 18 | ->update(['event' => 'madison.sponsor.needs_approval']) 19 | ; 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | DB::table('notification_preferences') 30 | ->where('event', 'madison.sponsor.needs_approval') 31 | ->update(['event' => 'madison.sponsor.created']) 32 | ; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2017_01_26_170819_comment_reply_notification.php: -------------------------------------------------------------------------------- 1 | where('event', 'madison.comment.created') 18 | ->update(['event' => 'madison.comment.replied']) 19 | ; 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | DB::table('notification_preferences') 30 | ->where('event', 'madison.comment.replied') 31 | ->update(['event' => 'madison.comment.created']) 32 | ; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2017_01_31_170338_user_sponsor_membership_notification.php: -------------------------------------------------------------------------------- 1 | where('event', 'madison.sponsor.member-added') 18 | ->update(['event' => 'madison.user.sponsor_membership_changed']) 19 | ; 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | DB::table('notification_preferences') 30 | ->where('event', 'madison.user.sponsor_membership_changed') 31 | ->update(['event' => 'madison.sponsor.member-added']) 32 | ; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2017_02_07_163509_create_config_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('environment')->nullable(); 19 | $table->string('group')->default('config')->index(); 20 | $table->string('key'); 21 | $table->longText('value')->nullable(); 22 | $table->string('type'); 23 | $table->timestamps(); 24 | $table->unique(['environment', 'group', 'key']); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::drop('config'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2017_03_03_173336_add_fulltext_idxs_for_doc_search.php: -------------------------------------------------------------------------------- 1 | engine = "InnoDB"; 28 | $table->increments('id'); 29 | $table->string('name'); 30 | $table->string('zip'); 31 | $table->string('url'); 32 | $table->timestamps(); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2017_03_22_132914_drop_dates.php: -------------------------------------------------------------------------------- 1 | increments('id'); 28 | $table->integer('doc_id')->unsigned(); 29 | $table->datetime('date'); 30 | $table->string('label'); 31 | $table->timestamps(); 32 | 33 | $table->foreign('doc_id')->references('id')->on('docs')->onDelete('cascade'); 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2017_03_30_003414_drop_user_meta_stuff.php: -------------------------------------------------------------------------------- 1 | increments('id'); 28 | $table->integer('user_id')->unsigned(); 29 | $table->string('meta_key'); 30 | $table->string('meta_value'); 31 | $table->timestamps(); 32 | 33 | $table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2017_05_04_175750_create_laravel_notifications_table.php: -------------------------------------------------------------------------------- 1 | uuid('id')->primary(); 18 | $table->string('type'); 19 | $table->morphs('notifiable'); 20 | $table->text('data'); 21 | $table->timestamp('read_at')->nullable(); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('notifications'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2017_05_08_141824_add_frequency_to_notification_preferences.php: -------------------------------------------------------------------------------- 1 | enum('frequency', ['immediately', 'daily'])->default('immediately'); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::table('notification_preferences', function ($table) { 29 | $table->dropColumn('frequency'); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_05_15_191135_add_fulltext_idxs_for_user_search.php: -------------------------------------------------------------------------------- 1 | Sponsor::STATUS_ACTIVE ])->first(); 16 | 17 | $documents = factory(Document::class, (int)config('madison.seeder.num_docs'))->create([ 18 | 'publish_state' => Document::PUBLISH_STATE_PUBLISHED, 19 | ])->each(function ($document) use ($sponsor, $faker) { 20 | $document->sponsors()->attach($sponsor); 21 | $document->setIntroText($faker->paragraphs($faker->numberBetween(1, 10), true)); 22 | $document->content()->save(factory(DocContent::class)->make()); 23 | }); 24 | 25 | $documents->first()->setAsFeatured(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /database/seeds/NotificationSeeder.php: -------------------------------------------------------------------------------- 1 | $eventClass) { 18 | NotificationPreference::addNotificationForUser($eventName, $user->id); 19 | } 20 | } 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /database/seeds/TestSeeder.php: -------------------------------------------------------------------------------- 1 | insert(array( 15 | 'email' => 'test@opengovfoundation.org', 16 | 'password' => Hash::make($test_password), 17 | 'fname' => $test_fname, 18 | 'lname' => $test_lname, 19 | 'token' => '', 20 | )); 21 | 22 | // Sample user, unconfirmed email, id 3 23 | DB::table('users')->insert(array( 24 | 'email' => 'test2@opengovfoundation.org', 25 | 'password' => Hash::make($test_password), 26 | 'fname' => $test_fname, 27 | 'lname' => $test_lname, 28 | 'token' => '12345', 29 | )); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "prod": "gulp --production", 5 | "dev": "gulp watch" 6 | }, 7 | "devDependencies": { 8 | "bootstrap-sass": "^3.3.7", 9 | "font-awesome": "^4.7.0", 10 | "gulp": "^3.9.1", 11 | "jquery": "^3.1.0", 12 | "laravel-elixir": "^6.0.0-14", 13 | "laravel-elixir-webpack-official": "^1.0.2", 14 | "lodash": "^4.16.2", 15 | "select2": "^4.0.3", 16 | "select2-bootstrap-theme": "0.1.0-beta.9", 17 | "simplemde": "^1.11.2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /phpspec.yml: -------------------------------------------------------------------------------- 1 | suites: 2 | main: 3 | namespace: App 4 | psr4_prefix: App 5 | src_path: app 6 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /public/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /resources/assets/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengovfoundation/madison/a510f15f82a0aa543b0087c4b72e2e0809b92875/resources/assets/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /resources/assets/icons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengovfoundation/madison/a510f15f82a0aa543b0087c4b72e2e0809b92875/resources/assets/icons/android-chrome-512x512.png -------------------------------------------------------------------------------- /resources/assets/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengovfoundation/madison/a510f15f82a0aa543b0087c4b72e2e0809b92875/resources/assets/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /resources/assets/icons/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #da532c 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /resources/assets/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengovfoundation/madison/a510f15f82a0aa543b0087c4b72e2e0809b92875/resources/assets/icons/favicon-16x16.png -------------------------------------------------------------------------------- /resources/assets/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengovfoundation/madison/a510f15f82a0aa543b0087c4b72e2e0809b92875/resources/assets/icons/favicon-32x32.png -------------------------------------------------------------------------------- /resources/assets/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengovfoundation/madison/a510f15f82a0aa543b0087c4b72e2e0809b92875/resources/assets/icons/favicon.ico -------------------------------------------------------------------------------- /resources/assets/icons/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OpenGov", 3 | "icons": [ 4 | { 5 | "src": "/android-chrome-192x192.png", 6 | "sizes": "192x192", 7 | "type": "image/png" 8 | }, 9 | { 10 | "src": "/android-chrome-512x512.png", 11 | "sizes": "512x512", 12 | "type": "image/png" 13 | } 14 | ], 15 | "theme_color": "#ffffff", 16 | "background_color": "#ffffff", 17 | "display": "standalone" 18 | } -------------------------------------------------------------------------------- /resources/assets/icons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengovfoundation/madison/a510f15f82a0aa543b0087c4b72e2e0809b92875/resources/assets/icons/mstile-150x150.png -------------------------------------------------------------------------------- /resources/assets/img/default-featured.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengovfoundation/madison/a510f15f82a0aa543b0087c4b72e2e0809b92875/resources/assets/img/default-featured.jpg -------------------------------------------------------------------------------- /resources/assets/js/document-edit.js: -------------------------------------------------------------------------------- 1 | // http://stackoverflow.com/a/37192700/738052 2 | window.autoHeightTextarea = function(textarea) { 3 | $(textarea) 4 | .each(function () { adjustHeight(this); }) 5 | .on('input', function () { adjustHeight(this); }); 6 | 7 | function adjustHeight(ctrl) { 8 | $(ctrl).css({'height':'auto','overflow-y':'hidden'}).height(ctrl.scrollHeight); 9 | } 10 | }; 11 | 12 | window.affixMarkdownToolbar = function (textareaSelector) { 13 | var $toolbar = $(textareaSelector).siblings('.editor-toolbar'); 14 | var $editArea = $(textareaSelector).siblings('.CodeMirror-wrap'); 15 | 16 | var bottomOfEditArea = $editArea.height() + $toolbar.offset().top; 17 | var offsetBottom = $(document).height() - bottomOfEditArea; 18 | 19 | var affixOpts = { 20 | offset: { 21 | top: $toolbar.offset().top, 22 | bottom: offsetBottom 23 | } 24 | }; 25 | 26 | $toolbar.affix(affixOpts); 27 | }; 28 | -------------------------------------------------------------------------------- /resources/assets/sass/app.scss: -------------------------------------------------------------------------------- 1 | @import "variables"; 2 | 3 | /** 4 | * Vendor 5 | */ 6 | @import "node_modules/bootstrap-sass/assets/stylesheets/bootstrap"; 7 | @import "node_modules/font-awesome/scss/font-awesome"; 8 | @import "node_modules/select2/dist/css/select2"; 9 | @import "node_modules/select2-bootstrap-theme/src/select2-bootstrap"; 10 | @import "node_modules/simplemde/dist/simplemde.min"; 11 | 12 | /** 13 | * Pages 14 | */ 15 | @import "global"; 16 | @import "home"; 17 | @import "document-edit"; 18 | @import "document-list"; 19 | @import "annotation"; 20 | @import "document"; 21 | -------------------------------------------------------------------------------- /resources/assets/sass/document-list.scss: -------------------------------------------------------------------------------- 1 | .document-grid { 2 | list-style: none; 3 | padding-left: 0; 4 | 5 | li { 6 | list-style: none; 7 | } 8 | } 9 | 10 | .document-card { 11 | border-bottom: 1px solid $gray-lighter; 12 | padding-bottom: $padding-base-vertical * 2; 13 | 14 | h3 .text-muted { 15 | font-family: $font-family-serif; 16 | font-style: italic; 17 | font-size: 45%; 18 | font-weight: bold; 19 | color: $ogf-slate-light; 20 | } 21 | 22 | .document-info { 23 | font-family: $font-family-sans-serif; 24 | color: $ogf-slate-light; 25 | font-size: 80%; 26 | font-weight: bold; 27 | padding-top: $padding-base-vertical; 28 | 29 | small { 30 | padding: 0 ($grid-gutter-width / 3); 31 | 32 | &:first-child { 33 | padding-left: 0; 34 | } 35 | } 36 | } 37 | 38 | } 39 | 40 | @media only screen and (min-width: 992px) { 41 | .document-grid { 42 | padding-bottom: 1rem; 43 | margin-bottom: 2rem; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /resources/assets/sass/home.scss: -------------------------------------------------------------------------------- 1 | .featured .document-card { 2 | h3 { 3 | font-size: $font-size-h3 + ($font-size-h3 * 0.2); 4 | } 5 | .document-info { 6 | font-size: $font-size-base; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /resources/lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 18 | 'next' => 'Next »', 19 | 20 | ); 21 | -------------------------------------------------------------------------------- /resources/lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Passwords must be at least six characters and match the confirmation.', 17 | 'reset' => 'Your password has been reset!', 18 | 'sent' => 'We have e-mailed your password reset link!', 19 | 'token' => 'This password reset token is invalid.', 20 | 'user' => "We can't find a user with that e-mail address.", 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/en/reminders.php: -------------------------------------------------------------------------------- 1 | "Passwords must be at least six characters and match the confirmation.", 17 | 18 | "user" => "We can't find a user with that e-mail address.", 19 | 20 | "token" => "This password reset token is invalid.", 21 | 22 | "sent" => "Password reminder sent!", 23 | 24 | ); 25 | -------------------------------------------------------------------------------- /resources/views/components/breadcrumbs/admin.blade.php: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /resources/views/components/breadcrumbs/pages.blade.php: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /resources/views/components/date.blade.php: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /resources/views/components/document-card.blade.php: -------------------------------------------------------------------------------- 1 |
2 |

3 | 4 | {{ $document->title }} 5 | 6 |
7 | 8 | @lang('messages.document.sponsoredby', ['sponsors' => $document->sponsors->implode('display_name', ', ')]) 9 | 10 |

11 | 12 | @if (isset($showIntro) && $showIntro) 13 |

{{ $document->shortIntroText() }}

14 | @endif 15 | 16 |

17 | @include('components/relative-time', ['datetime' => $document->created_at]) 18 | 19 | 20 | {{ $document->support }} 21 | 22 | 23 | 24 | {{ $document->oppose }} 25 | 26 | 27 | 28 | {{ $document->all_comments_count }} 29 | 30 |

31 |
32 | -------------------------------------------------------------------------------- /resources/views/components/errors.blade.php: -------------------------------------------------------------------------------- 1 | @if (count($errors) > 0) 2 |
3 | 8 |
9 | @endif 10 | -------------------------------------------------------------------------------- /resources/views/components/form/select.blade.php: -------------------------------------------------------------------------------- 1 | @php 2 | $labelSrOnly = false; 3 | if (!empty($attributes['label-sr-only'])) { 4 | $labelSrOnly = true; 5 | unset($attributes['label-sr-only']); 6 | } 7 | @endphp 8 | 9 |
10 | {{ Form::label($name, $displayName, ['class' => 'control-label' . ($labelSrOnly ? ' sr-only' : '')]) }} 11 | {{ Form::select($name, $list, $selected ?: request()->input(trim($name, "[]"), null), array_merge(['class' => 'form-control', 'autocomplete' => 'off'], $attributes)) }} 12 | @if (!empty($helpText)) 13 |

{{ $helpText }}

14 | @endif 15 |
16 | -------------------------------------------------------------------------------- /resources/views/components/form/submit.blade.php: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/views/components/pagination.blade.php: -------------------------------------------------------------------------------- 1 |

2 | {{ trans('messages.pagination', [ 3 | 'start' => $collection->total() === 0 ? 0 : ($collection->currentPage() - 1) * $collection->perPage() + 1, 4 | 'end' => min($collection->currentPage() * $collection->perPage(), $collection->total()), 5 | 'total' => $collection->total() 6 | ]) 7 | }} 8 |

9 | 10 | {{ $collection->appends(request()->query())->links() }} 11 | -------------------------------------------------------------------------------- /resources/views/components/relative-time.blade.php: -------------------------------------------------------------------------------- 1 | {{-- TODO: the title content should be set to users or sites preferred display format --}} 2 | {{-- TODO: only use diffForHumans if the time is fairly recent, otherwise display a more precise date --}} 3 | 4 | -------------------------------------------------------------------------------- /resources/views/documents/comments-page.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('pageTitle', 'Comment') 4 | 5 | @section('content') 6 | @include('components.errors') 7 | 8 | @include('documents.partials.comments', ['view' => 'card', 'comments' => $comments]) 9 | @endsection 10 | -------------------------------------------------------------------------------- /resources/views/documents/partials/comment-card.blade.php: -------------------------------------------------------------------------------- 1 |
  • 2 | @include('documents.partials.comment-base') 3 |
  • 4 | -------------------------------------------------------------------------------- /resources/views/documents/partials/comment-reply.blade.php: -------------------------------------------------------------------------------- 1 |
    2 | @include('documents.partials.comment-base') 3 |
    4 | -------------------------------------------------------------------------------- /resources/views/documents/partials/comments.blade.php: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /resources/views/emails/daily_notifications.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::message') 2 | 3 | @lang('messages.notifications.frequencies.' . App\Models\NotificationPreference::FREQUENCY_DAILY . '.intro') 4 | 5 | @foreach ($groupedAndFormattedNotifications as $notification) 6 | - {!! $notification !!} 7 | @endforeach 8 | 9 | @lang('messages.notifications.salutation', ['name' => config('app.name')]) 10 | 11 | @component('mail::subcopy') 12 | {!! $unsubscribeMarkdown !!} 13 | @endcomponent 14 | 15 | @endcomponent 16 | -------------------------------------------------------------------------------- /resources/views/emails/password.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

    Madison Password Reset

    8 | 9 |
    10 | To reset your password, complete this form: {{ url('password/reset/' . $token) }}. 11 |
    12 | 13 | 14 | -------------------------------------------------------------------------------- /resources/views/emails/sponsor_onboarding/participate.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::message') 2 | 3 | @lang('messages.sponsor.onboarding.salutation', ['name' => $user->fname]) 4 | 5 | 6 | @lang('messages.sponsor.onboarding.participate.opening') 7 | 8 | 9 | @includeLocale('sponsors.onboarding.$locale.participate') 10 | 11 | 12 | # @lang('messages.sponsor.onboarding.learn_more') 13 | 14 | 15 | @lang('messages.sponsor.onboarding.complete_guide', ['guideLink' => route('sponsors.guide')]) 16 | @endcomponent 17 | -------------------------------------------------------------------------------- /resources/views/emails/sponsor_onboarding/prepare.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::message') 2 | 3 | @lang('messages.sponsor.onboarding.salutation', ['name' => $user->fname]) 4 | 5 | 6 | @lang('messages.sponsor.onboarding.prepare.opening') 7 | 8 | 9 | @lang('messages.sponsor.onboarding.prepare.opening_2') 10 | 11 | 12 | @includeLocale('sponsors.onboarding.$locale.prepare') 13 | 14 | 15 | # @lang('messages.sponsor.onboarding.learn_more') 16 | 17 | 18 | @lang('messages.sponsor.onboarding.complete_guide', ['guideLink' => route('sponsors.guide')]) 19 | @endcomponent 20 | -------------------------------------------------------------------------------- /resources/views/emails/sponsor_onboarding/publish.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::message') 2 | 3 | @lang('messages.sponsor.onboarding.salutation', ['name' => $user->fname]) 4 | 5 | 6 | @lang('messages.sponsor.onboarding.publish.opening', ['sponsor' => $sponsor->display_name]) 7 | 8 | 9 | @lang('messages.sponsor.onboarding.publish.opening_2') 10 | 11 | 12 | @includeLocale('sponsors.onboarding.$locale.publish') 13 | 14 | 15 | # @lang('messages.sponsor.onboarding.learn_more') 16 | 17 | 18 | @lang('messages.sponsor.onboarding.complete_guide', ['guideLink' => route('sponsors.guide')]) 19 | @endcomponent 20 | -------------------------------------------------------------------------------- /resources/views/emails/verify_email.blade.php: -------------------------------------------------------------------------------- 1 | @php ($url = route('users.verify_email', [$user, $user->token])) 2 | 3 | @component('mail::message') 4 | # @lang('messages.email_verification.ask') 5 | 6 | @lang('messages.email_verification.reason') 7 | 8 | @component('mail::button', ['url' => $url]) 9 | @lang('messages.email_verification.action') 10 | @endcomponent 11 | 12 | @lang('messages.notifications.salutation', ['name' => config('app.name')]) 13 | 14 | @component('mail::subcopy') 15 | @lang('messages.notifications.having_trouble', ['actionText' => trans('messages.email_verification.action')]) 16 | [{{ $url }}]({{ $url }}) 17 | @endcomponent 18 | @endcomponent 19 | -------------------------------------------------------------------------------- /resources/views/errors/403.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('pageTitle', trans('messages.error.403.title')) 4 | 5 | @section('content') 6 | @include('errors.partials.error_content', ['status' => '403']) 7 | @endsection 8 | -------------------------------------------------------------------------------- /resources/views/errors/404.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('pageTitle', trans('messages.error.404.title')) 4 | 5 | @section('content') 6 | @include('errors.partials.error_content', ['status' => '404']) 7 | @endsection 8 | -------------------------------------------------------------------------------- /resources/views/errors/500.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('pageTitle', trans('messages.error.500.title')) 4 | 5 | @section('content') 6 | @include('errors.partials.error_content', ['status' => '500']) 7 | @endsection 8 | -------------------------------------------------------------------------------- /resources/views/errors/partials/error_content.blade.php: -------------------------------------------------------------------------------- 1 |

    @lang('messages.error.' . $status . '.title')

    2 |
    3 |

    @lang('messages.error.' . $status . '.body')

    4 | -------------------------------------------------------------------------------- /resources/views/home/partials/welcome.blade.php: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |

    @lang('messages.home.how_it_works.title')

    4 |
      5 |
    1. {!! trans('messages.home.how_it_works.step1') !!}
    2. 6 |
    3. {!! trans('messages.home.how_it_works.step2') !!}
    4. 7 |
    5. {!! trans('messages.home.how_it_works.step3') !!}
    6. 8 |
    9 | 10 |

    @lang('messages.home.sponsor_cta.title')

    11 |

    12 | {!! trans('messages.home.sponsor_cta.text') !!} 13 | 14 | @lang('messages.home.sponsor_cta.action_text') 15 | 16 |

    17 |
    18 |
    19 |
    20 | 21 |
    22 |
    23 |
    24 | -------------------------------------------------------------------------------- /resources/views/layouts/embed.blade.php: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | @yield('content') 4 |
    5 |
    6 | -------------------------------------------------------------------------------- /resources/views/layouts/social.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ config('app.name') . ' - ' . $title }} 5 | 6 | 7 | 8 | 9 | 10 | 11 |

    {{ $description }}

    12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /resources/views/pages/create.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('pageTitle', trans('messages.page.create')) 4 | 5 | @section('content') 6 | 7 | 10 | 11 | @include('components.errors') 12 | 13 | {{ Form::open(['route' => ['pages.store']]) }} 14 | {{ Form::mInput('text', 'nav_title', trans('messages.page.title')) }} 15 | {{ Form::mSubmit() }} 16 | {{ Form::close() }} 17 | @endsection 18 | -------------------------------------------------------------------------------- /resources/views/pages/show.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('pageTitle', $page->page_title) 4 | 5 | @section('content') 6 | 7 | 10 | 11 | @include('components.errors') 12 | 13 | {!! $page->content->html() !!} 14 | @endsection 15 | -------------------------------------------------------------------------------- /resources/views/partials/closed-discussion-icon.blade.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /resources/views/partials/hotjar-script.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /resources/views/sponsor_members/create.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('pageTitle', trans('messages.sponsor_member.create')) 4 | 5 | @section('content') 6 | @include('components.breadcrumbs.sponsor', ['sponsor' => $sponsor]) 7 | 8 | 11 | 12 | @include('components.errors') 13 | 14 |
    15 | @include('sponsors.partials.sponsor-sidebar') 16 |
    17 | {{ Form::open(['route' => ['sponsors.members.store', $sponsor]]) }} 18 | {{ Form::mInput('text', 'email', trans('messages.user.email')) }} 19 | {{ Form::mSelect('role', trans('messages.sponsor_member.role'), $allRoles, null) }} 20 | {{ Form::mSubmit(trans('messages.sponsor_member.add_user')) }} 21 | {{ Form::close() }} 22 |
    23 |
    24 | @endsection 25 | -------------------------------------------------------------------------------- /resources/views/sponsors/awaiting-approval.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('pageTitle', trans('messages.sponsor.waiting_approval.page_title')) 4 | 5 | @section('content') 6 |

    @lang('messages.sponsor.waiting_approval.msg_header')

    7 |

    @lang('messages.sponsor.waiting_approval.msg_lead')

    8 |

    @lang('messages.sponsor.waiting_approval.msg_body')

    9 | @endsection 10 | -------------------------------------------------------------------------------- /resources/views/sponsors/create.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('pageTitle', trans('messages.sponsor.create')) 4 | 5 | @section('content') 6 | @include('components.breadcrumbs.account') 7 | 8 | 11 | 12 | @include('components.errors') 13 | 14 |
    15 |
    16 |

    @lang('messages.sponsor.create_help.what_is_a_sponsor')

    17 |

    @lang('messages.sponsor.create_help.next_steps')

    18 |

    @lang('messages.learn_more')

    19 |
    20 |
    21 | {{ Form::open(['route' => ['sponsors.store']]) }} 22 | @include('sponsors.partials.form') 23 | {{ Form::close() }} 24 |
    25 |
    26 | @endsection 27 | -------------------------------------------------------------------------------- /resources/views/sponsors/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('pageTitle', trans('messages.sponsor.page_title_settings', ['sponsorName' => $sponsor->display_name])) 4 | 5 | @section('content') 6 | @include('components.breadcrumbs.sponsor', ['sponsor' => $sponsor]) 7 | 8 | 11 | 12 | @include('components.errors') 13 | 14 |
    15 | @include('sponsors.partials.sponsor-sidebar', ['sponsor' => $sponsor]) 16 | 17 |
    18 | {{ Form::model($sponsor, ['route' => ['sponsors.update', $sponsor->id], 'method' => 'put']) }} 19 | @include('sponsors.partials.form', ['sponsor' => $sponsor]) 20 | {{ Form::close() }} 21 |
    22 |
    23 | @endsection 24 | -------------------------------------------------------------------------------- /resources/views/sponsors/guide.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('pageTitle', trans('messages.sponsor.onboarding.guide')) 4 | 5 | @section('content') 6 | {!! $content !!} 7 | @endsection 8 | -------------------------------------------------------------------------------- /resources/views/sponsors/onboarding/combined.blade.php: -------------------------------------------------------------------------------- 1 | @includeLocale('sponsors.onboarding.$locale.prepare') 2 | 3 | @includeLocale('sponsors.onboarding.$locale.publish') 4 | 5 | @includeLocale('sponsors.onboarding.$locale.participate') 6 | -------------------------------------------------------------------------------- /resources/views/sponsors/onboarding/en/participate.blade.php: -------------------------------------------------------------------------------- 1 | # Actively Participate 2 | 3 | Publishing the document is just the beginning. Once it's published, you as a 4 | sponsor are responsible for creating and curating conversation. *We suggest*: 5 | - Who is **monitoring the activity**? Make sure that someone is clearly identified and that person will receive notifications (see notification settings). 6 | - **Reply to comments**. When appropriate, reply to comments. Constituents love knowing that you are really involved. Note that comments are from your account, not the sponsor account. 7 | - **Moderate comments**. Rarely someone will leave an inappropriate comment. To hide it, you (or any user) can flag it. Once flagged, you can hide any flagged comment using the administration interface. 8 | - **Delegate**. Multiple users can belong to a sponsor, so don't be afraid to delegate tasks. 9 | - **Close the discussion.** When the engagement period is over, close the discussion in the administration interface. 10 | -------------------------------------------------------------------------------- /resources/views/users/settings.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 | @include('components.breadcrumbs.account') 5 | 6 | {{-- TODO: set this differently for each page? --}} 7 | 10 | 11 | @include('components.errors') 12 | 13 |
    14 | @php ($settingsPages = ['account', 'password', 'notifications']) 15 | @foreach($settingsPages as $setting) 16 | @php ($settingUrl = route('users.settings.'.$setting.'.edit', $user->id)) 17 | 18 | @lang('messages.user.settings_pages.'.$setting) 19 | 20 | @endforeach 21 |
    22 | 23 |
    24 | @yield('settings_content') 25 |
    26 | @endsection 27 | -------------------------------------------------------------------------------- /resources/views/users/settings/account.blade.php: -------------------------------------------------------------------------------- 1 | @extends('users.settings') 2 | 3 | @section('pageTitle', trans('messages.user.settings_pages.account')) 4 | 5 | @section('settings_content') 6 | {{ Form::model($user, ['route' => ['users.settings.account.update', $user->id], 'method' => 'put']) }} 7 | {{ Form::mInput('text', 'fname', trans('messages.user.fname'), null, ['required' => '']) }} 8 | {{ Form::mInput('text', 'lname', trans('messages.user.lname'), null, ['required' => '']) }} 9 | {{ Form::mInput('email', 'email', trans('messages.user.email'), null, ['required' => ''], trans('messages.user.email_help')) }} 10 |
    11 | {{ Form::mSubmit(trans('messages.save')) }} 12 | {{ Form::close() }} 13 | @endsection 14 | -------------------------------------------------------------------------------- /resources/views/users/settings/password.blade.php: -------------------------------------------------------------------------------- 1 | @extends('users.settings') 2 | 3 | @section('pageTitle', trans('messages.user.settings_pages.password')) 4 | 5 | @section('settings_content') 6 | {{ Form::open(['route' => ['users.settings.password.update', $user->id], 'method' => 'put']) }} 7 | {{ Form::mInput('password', 'new_password', trans('messages.user.new_password')) }} 8 | {{ Form::mInput('password', 'new_password_confirmation', trans('messages.user.new_password_confirmation')) }} 9 |
    10 | {{ Form::mSubmit(trans('messages.save')) }} 11 | {{ Form::close() }} 12 | @endsection 13 | -------------------------------------------------------------------------------- /routes/api.php: -------------------------------------------------------------------------------- 1 | id === (int) $id; 16 | }); 17 | -------------------------------------------------------------------------------- /routes/console.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 18 | })->describe('Display an inspiring quote'); 19 | -------------------------------------------------------------------------------- /server.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | $uri = urldecode( 11 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) 12 | ); 13 | 14 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the 15 | // built-in PHP web server. This provides a convenient way to test a Laravel 16 | // application without having installed a "real" web server software here. 17 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { 18 | return false; 19 | } 20 | 21 | require_once __DIR__.'/public/index.php'; 22 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | config.php 2 | routes.php 3 | compiled.php 4 | services.json 5 | events.scanned.php 6 | routes.scanned.php 7 | down 8 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /tests/Browser/AdminTestCase.php: -------------------------------------------------------------------------------- 1 | admin = factory(User::class)->create()->makeAdmin(); 19 | $this->user = factory(User::class)->create(); 20 | } 21 | 22 | public function assertNonAdminsDenied($browser, $page) 23 | { 24 | // anonymous user 25 | $browser 26 | ->visit($page->url()) 27 | ->assertPathIs('/login') 28 | ; 29 | 30 | // non-admin 31 | $browser 32 | ->loginAs($this->user) 33 | ->visit($page) 34 | // 403 status 35 | ->assertSee('403') 36 | ; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/Browser/ExampleTest.php: -------------------------------------------------------------------------------- 1 | browse(function (Browser $browser) { 20 | $browser->visit('/') 21 | ->assertSee('Madison'); 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/Browser/LogoutTest.php: -------------------------------------------------------------------------------- 1 | create(); 20 | 21 | $this->browse(function ($browser) use ($user) { 22 | $home = new HomePage; 23 | $browser 24 | ->loginAs($user) 25 | ->assertAuthenticatedAs($user) 26 | ->visit($home) 27 | ->clickLink('Logout') 28 | ->assertPathIs($home->url()) 29 | ->assertGuest() 30 | ; 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/Browser/Pages/Admin/CustomPagesPage.php: -------------------------------------------------------------------------------- 1 | 'a.new', 29 | '@editPageBtn' => '.edit', 30 | '@destroyPageBtn' => '.destroy', 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/Browser/Pages/Admin/ManageSponsorsPage.php: -------------------------------------------------------------------------------- 1 | 'button.admin', 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/Browser/Pages/Admin/SiteSettingsPage.php: -------------------------------------------------------------------------------- 1 | '#content form button[type=submit]', 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/Browser/Pages/CustomPages/CreatePage.php: -------------------------------------------------------------------------------- 1 | '#selector', 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/Browser/Pages/CustomPages/EditPage.php: -------------------------------------------------------------------------------- 1 | customPage = $page; 16 | } 17 | 18 | /** 19 | * Get the URL for the page. 20 | * 21 | * @return string 22 | */ 23 | public function url() 24 | { 25 | return route('pages.edit', $this->customPage, false); 26 | } 27 | 28 | /** 29 | * Get the element shortcuts for the page. 30 | * 31 | * @return array 32 | */ 33 | public function elements() 34 | { 35 | return [ 36 | '@element' => '#selector', 37 | ]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/Browser/Pages/Document/ListPage.php: -------------------------------------------------------------------------------- 1 | '#content .destroy', 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/Browser/Pages/HomePage.php: -------------------------------------------------------------------------------- 1 | '.featured', 38 | '@popular' => '.popular', 39 | ]; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/Browser/Pages/LoginPage.php: -------------------------------------------------------------------------------- 1 | type('email', $user->email) 34 | ->type('password', 'secret') 35 | ->press('Login') 36 | ; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/Browser/Pages/Page.php: -------------------------------------------------------------------------------- 1 | assertPathIs($this->url()); 18 | } 19 | 20 | /** 21 | * Get the global element shortcuts for the site. 22 | * 23 | * @return array 24 | */ 25 | public static function siteElements() 26 | { 27 | return [ 28 | '@headerNav' => '.navbar-static-top .navbar-right', 29 | '@footerNav' => '#main-footer ul', 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Browser/Pages/RegisterPage.php: -------------------------------------------------------------------------------- 1 | type('fname', $user->fname) 34 | ->type('lname', $user->lname) 35 | ->type('email', $user->email) 36 | ->type('password', 'secret') 37 | ->type('password_confirmation', 'secret') 38 | ->press('Register') 39 | ; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/Browser/Pages/User/Settings/AccountPage.php: -------------------------------------------------------------------------------- 1 | user = $user; 16 | } 17 | 18 | /** 19 | * Get the URL for the page. 20 | * 21 | * @return string 22 | */ 23 | public function url() 24 | { 25 | return route('users.settings.account.edit', $this->user, false); 26 | } 27 | 28 | /** 29 | * Get the element shortcuts for the page. 30 | * 31 | * @return array 32 | */ 33 | public function elements() 34 | { 35 | return [ 36 | '@element' => '#selector', 37 | ]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/Browser/Pages/User/Settings/NotificationsPage.php: -------------------------------------------------------------------------------- 1 | user = $user; 16 | } 17 | 18 | /** 19 | * Get the URL for the page. 20 | * 21 | * @return string 22 | */ 23 | public function url() 24 | { 25 | return route('users.settings.notifications.edit', $this->user, false); 26 | } 27 | 28 | /** 29 | * Get the element shortcuts for the page. 30 | * 31 | * @return array 32 | */ 33 | public function elements() 34 | { 35 | return [ 36 | '@element' => '#selector', 37 | ]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/Browser/Pages/User/Settings/PasswordPage.php: -------------------------------------------------------------------------------- 1 | user = $user; 16 | } 17 | 18 | /** 19 | * Get the URL for the page. 20 | * 21 | * @return string 22 | */ 23 | public function url() 24 | { 25 | return route('users.settings.password.edit', $this->user, false); 26 | } 27 | 28 | /** 29 | * Get the element shortcuts for the page. 30 | * 31 | * @return array 32 | */ 33 | public function elements() 34 | { 35 | return [ 36 | '@element' => '#selector', 37 | ]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/Browser/console/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /tests/Browser/screenshots/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /tests/CreatesApplication.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 19 | 20 | return $app; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/Feature/ExampleTest.php: -------------------------------------------------------------------------------- 1 | get('/'); 24 | $response->assertStatus(200); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 19 | } 20 | 21 | } 22 | --------------------------------------------------------------------------------