├── .dockerignore
├── .gitignore
├── .rspec
├── .rubocop.yml
├── .rubocop_todo.yml
├── .stylelintrc.json
├── Dockerfile
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── Makefile
├── Procfile
├── README.md
├── Rakefile
├── app
├── assets
│ ├── images
│ │ ├── favicon.ico
│ │ └── patterns
│ │ │ ├── header-profile.png
│ │ │ └── shattered.png
│ ├── javascripts
│ │ ├── app
│ │ │ ├── components
│ │ │ │ ├── charts.js
│ │ │ │ ├── dataTableShared.js
│ │ │ │ ├── externalDataManipulation.js
│ │ │ │ ├── faIcons.js
│ │ │ │ ├── inlineEditing.js
│ │ │ │ ├── layoutBuilderModal.js
│ │ │ │ ├── listSort.js
│ │ │ │ ├── modal.js
│ │ │ │ ├── permissions_table.js
│ │ │ │ └── tables.js
│ │ │ ├── globals.js
│ │ │ ├── navigation.js
│ │ │ ├── registration.js
│ │ │ ├── target_table_settings.js
│ │ │ ├── twilio.js
│ │ │ └── users.js
│ │ ├── application.js
│ │ ├── draggable.js
│ │ ├── layout_builder.js
│ │ ├── page_specific
│ │ │ ├── adminUser.js
│ │ │ ├── dashboard.js
│ │ │ ├── database.js
│ │ │ ├── layoutBuilder.js
│ │ │ ├── organisationSetting.js
│ │ │ ├── permissions.js
│ │ │ ├── tables.js
│ │ │ └── taskQueue.js
│ │ ├── palomaInitializer.js
│ │ └── task_queue_builder.js
│ └── stylesheets
│ │ ├── admin_users.scss
│ │ ├── application.scss
│ │ ├── base
│ │ ├── activity.scss
│ │ ├── buttons.scss
│ │ ├── form.scss
│ │ ├── globals.scss
│ │ ├── margins_and_paddings.scss
│ │ ├── media.scss
│ │ ├── modal.scss
│ │ ├── navigation.scss
│ │ ├── typography.scss
│ │ └── variables.scss
│ │ ├── components
│ │ ├── _toastr.scss
│ │ └── _tooltipster.scss
│ │ ├── dashboard.scss
│ │ ├── devise.scss
│ │ ├── layout_builder.scss
│ │ ├── single_view_builder.scss
│ │ ├── site.scss
│ │ ├── table.scss
│ │ ├── table_permissions.scss
│ │ ├── task_queues.scss
│ │ └── views.scss
├── controllers
│ ├── activities_controller.rb
│ ├── admin_user_registrations_controller.rb
│ ├── admin_user_sessions_controller.rb
│ ├── admin_users_controller.rb
│ ├── application_controller.rb
│ ├── call_controller.rb
│ ├── concerns
│ │ ├── .keep
│ │ ├── database_actions.rb
│ │ ├── database_presenter_actions.rb
│ │ ├── license.rb
│ │ ├── relatable_tables.rb
│ │ ├── single_view_actions.rb
│ │ ├── table_activity.rb
│ │ ├── table_render.rb
│ │ ├── task_queue_record_activity.rb
│ │ ├── task_queue_render.rb
│ │ └── user_abilities.rb
│ ├── dashboard_controller.rb
│ ├── data_table_states_controller.rb
│ ├── databases_controller.rb
│ ├── errors_controller.rb
│ ├── home_controller.rb
│ ├── layout_builder_controller.rb
│ ├── organisation_settings_controller.rb
│ ├── permissions_controller.rb
│ ├── roles_controller.rb
│ ├── tables_controller.rb
│ ├── task_queues_controller.rb
│ └── token_controller.rb
├── errors
│ ├── invalid_client_database_error.rb
│ ├── not_authorized_error.rb
│ ├── sql_database_error.rb
│ └── unable_to_save_record_error.rb
├── helpers
│ ├── activity_helper.rb
│ ├── application_helper.rb
│ ├── devise_helper.rb
│ ├── table_helper.rb
│ └── view_builder_helper.rb
├── lib
│ ├── assets
│ │ └── .keep
│ ├── catch_error_from_rack.rb
│ ├── kuwinda
│ │ ├── database_adapter.rb
│ │ ├── gateway
│ │ │ └── database_connection_gateway.rb
│ │ ├── presenter
│ │ │ ├── list_available_tables.rb
│ │ │ ├── list_relatable_tables.rb
│ │ │ ├── list_table_fields.rb
│ │ │ ├── list_table_fields_with_type.rb
│ │ │ └── retrieve_data.rb
│ │ ├── repository
│ │ │ └── target_db.rb
│ │ └── use_case
│ │ │ └── database_connection.rb
│ ├── tasks
│ │ ├── .keep
│ │ ├── assets.rake
│ │ ├── dummy_client_db_seeds.rake
│ │ └── setup_staging_org_and_roles.rake
│ └── twilio
│ │ └── capability.rb
├── mailers
│ └── .keep
├── models
│ ├── .keep
│ ├── ability.rb
│ ├── activity.rb
│ ├── admin_user.rb
│ ├── application_record.rb
│ ├── concerns
│ │ ├── .keep
│ │ ├── client_record.rb
│ │ ├── database_connection.rb
│ │ └── sensitive_data.rb
│ ├── data_table_state.rb
│ ├── database.rb
│ ├── layout_setting.rb
│ ├── organisation_setting.rb
│ ├── permission.rb
│ ├── role.rb
│ ├── sql_filter.rb
│ ├── sql_filter
│ │ ├── base.rb
│ │ └── equal.rb
│ ├── sql_filter_factory.rb
│ ├── target_table_setting.rb
│ ├── task_queue.rb
│ ├── task_queue_outcome.rb
│ ├── view_builder.rb
│ ├── work_list.rb
│ └── work_list_outcome.rb
├── services
│ └── verify_license_key_service.rb
└── views
│ ├── activities
│ ├── _activity.html.erb
│ ├── _form.html.erb
│ ├── _task_queue_record_activity_form.html.erb
│ ├── failure.js.erb
│ ├── index.html.erb
│ └── success.js.erb
│ ├── admin_users
│ ├── _new_modal.html.erb
│ ├── _permissions.html.erb
│ ├── _roles.html.erb
│ ├── _show_modal.html.erb
│ ├── _status.html.erb
│ ├── _teams.html.erb
│ ├── _user_form.html.erb
│ ├── _users_table.html.erb
│ ├── create_new.js.erb
│ ├── delete_failure.js.erb
│ ├── destroy.js.erb
│ ├── edit.js.erb
│ ├── index.html.erb
│ ├── new.js.erb
│ ├── show_modal.js.erb
│ ├── update.js.erb
│ ├── update_role.js.erb
│ └── update_status.js.erb
│ ├── dashboard
│ ├── _license_form.html.erb
│ ├── license.html.erb
│ ├── show.html.erb
│ └── verify_license.html.erb
│ ├── databases
│ ├── _credentials_form.html.erb
│ ├── _mission_kontrol_relay_form.html.erb
│ ├── _tabs.html.erb
│ ├── create.js.erb
│ ├── edit.html.erb
│ ├── new.html.erb
│ ├── test_connection.js.erb
│ ├── test_gem.js.erb
│ └── update.js.erb
│ ├── devise
│ ├── confirmations
│ │ └── new.html.erb
│ ├── mailer
│ │ ├── confirmation_instructions.html.erb
│ │ ├── email_changed.html.erb
│ │ ├── password_change.html.erb
│ │ ├── reset_password_instructions.html.erb
│ │ └── unlock_instructions.html.erb
│ ├── passwords
│ │ ├── edit.html.erb
│ │ └── new.html.erb
│ ├── registrations
│ │ ├── _form_content.html.erb
│ │ ├── _form_content_admin_db.html.erb
│ │ ├── _registration_form_one.html.erb
│ │ ├── _registration_form_two.html.erb
│ │ ├── edit.html.erb
│ │ ├── edit.js.erb
│ │ └── new.html.erb
│ ├── sessions
│ │ └── new.html.erb
│ ├── shared
│ │ └── _links.html.erb
│ └── unlocks
│ │ └── new.html.erb
│ ├── errors
│ ├── internal_server_error.html.erb
│ ├── internal_server_error.js.erb
│ ├── not_acceptable.html.erb
│ ├── not_acceptable.js.erb
│ ├── not_authorized.html.erb
│ ├── not_authorized.js.erb
│ ├── not_found.html.erb
│ └── not_found.js.erb
│ ├── home
│ └── index.html.erb
│ ├── layout_builder
│ ├── _draggable_field_settings.html.erb
│ ├── _field_settings_form_old.html.erb
│ ├── _general_settings_form.html.erb
│ ├── _initial_placeholder.html.erb
│ ├── _record_placeholder_old.html.erb
│ ├── configure_table_order_old.html.erb
│ ├── edit.html.erb
│ ├── edit
│ │ ├── _layout_builder_editable_warning_modal_screen_1.html.erb
│ │ ├── error.js.erb
│ │ └── success.js.erb
│ ├── index.html.erb
│ ├── layout
│ │ ├── _header_container1.html.erb
│ │ ├── _header_container2.html.erb
│ │ ├── _main_container1.html.erb
│ │ ├── _main_container2.html.erb
│ │ ├── _main_container3.html.erb
│ │ └── _side_container.html.erb
│ ├── new.html.erb
│ ├── new
│ │ ├── _layout_builder_modal_screen_1.html.erb
│ │ └── _layout_builder_modal_screen_2.html.erb
│ ├── preview.html.erb
│ ├── select_table_fields.html.erb
│ ├── show.html.erb
│ └── update
│ │ └── success.js
│ ├── layouts
│ ├── _footer.html.erb
│ ├── _layout_builder_navigation.html.erb
│ ├── _layout_builder_navigation_old.html.erb
│ ├── _layout_builder_topnavbar.html.erb
│ ├── _mouseflow.html.erb
│ ├── _natterly.html
│ ├── _navigation.html.erb
│ ├── _task_queue_topnavbar.html.erb
│ ├── _topnavbar.html.erb
│ ├── application.html.erb
│ ├── bad_connection.html.erb
│ ├── dashboard.html.erb
│ ├── layout_builder.html.erb
│ ├── license.html.erb
│ ├── standard.html.erb
│ └── task_queue.html.erb
│ ├── organisation_settings
│ ├── edit.html.erb
│ └── update.js.erb
│ ├── permissions
│ ├── add_to_role.js.erb
│ ├── disable_all.js.erb
│ ├── enable_all.js.erb
│ ├── index.html.erb
│ └── remove_from_role.js.erb
│ ├── roles
│ ├── _edit_modal.html.erb
│ ├── edit.js.erb
│ ├── update.js.erb
│ └── update_error.js.erb
│ ├── shared
│ ├── _activity_history.html.erb
│ ├── _activity_history_task_queue_item.html.erb
│ ├── _activity_history_template.html.erb
│ ├── _activity_stream.html.erb
│ ├── _flash_message.html.erb
│ ├── _page_banner_header.html.erb
│ ├── _table_filter_bar.html.erb
│ └── _task_queue_partial.html.erb
│ ├── tables
│ ├── _add_record_modal.html.erb
│ ├── _data_table.html.erb
│ ├── _edit_record_modal.html.erb
│ ├── _record_placeholder_old.html.erb
│ ├── _record_summary.html.erb
│ ├── _related_data_table.html.erb
│ ├── _related_table.html.erb
│ ├── _related_table_with_layout.html.erb
│ ├── _settings_modal.html.erb
│ ├── _single_data_view.html.erb
│ ├── _table.html.erb
│ ├── _table_cell_data.html.erb
│ ├── _table_with_layout.html.erb
│ ├── _table_without_layout.html.erb
│ ├── _twilio_dialer.html.erb
│ ├── add_record.js.erb
│ ├── create_record.js.erb
│ ├── delete_record.js.erb
│ ├── edit_record.js.erb
│ ├── layout
│ │ ├── _container_content.html.erb
│ │ ├── _editable_actions.html.erb
│ │ ├── _editable_input.html.erb
│ │ ├── _header_container1.html.erb
│ │ ├── _header_container2.html.erb
│ │ ├── _main_container1.html.erb
│ │ ├── _main_container2.html.erb
│ │ ├── _main_container3.html.erb
│ │ └── _side_container.html.erb
│ ├── preview.html.erb
│ ├── settings.js.erb
│ ├── show.html.erb
│ ├── show
│ │ ├── failure.js.erb
│ │ └── success.js.erb
│ ├── update_record.js.erb
│ └── update_settings.js.erb
│ └── task_queues
│ ├── _preview.html.erb
│ ├── _preview_show.html.erb
│ ├── _task_queue_builder.html.erb
│ ├── edit.html.erb
│ ├── index.html.erb
│ ├── index_old.html.erb
│ ├── new.html.erb
│ ├── new
│ ├── _new_queue_modal_screen_1.html.erb
│ └── _new_queue_modal_screen_2.html.erb
│ ├── shared
│ ├── _task_queue_create_tab.html.erb
│ ├── _task_queue_define_tab.html.erb
│ ├── _task_queue_navigation.html.erb
│ ├── _task_queue_outcome_settings.html.erb
│ └── _task_queue_publish_tab.html.erb
│ └── show.html.erb
├── bin
├── bundle
├── configure-host
│ ├── README.md
│ └── auto-install.sh
├── docker-entrypoint.sh
├── rails
├── rake
├── rspec
├── setup
├── update
└── yarn
├── clock.rb
├── config.ru
├── config
├── application.rb
├── boot.rb
├── cable.yml
├── client_database.yml
├── database.yml
├── environment.rb
├── environments
│ ├── development.rb
│ ├── production.rb
│ ├── staging.rb
│ └── test.rb
├── initializers
│ ├── application_controller_renderer.rb
│ ├── assets.rb
│ ├── backtrace_silencers.rb
│ ├── content_security_policy.rb
│ ├── cookies_serializer.rb
│ ├── devise.rb
│ ├── feature_policy.rb
│ ├── filter_parameter_logging.rb
│ ├── inflections.rb
│ ├── mime_types.rb
│ ├── models.rb
│ ├── new_framework_defaults_5_1.rb
│ ├── new_framework_defaults_6_1.rb
│ ├── rolify.rb
│ ├── session_store.rb
│ └── wrap_parameters.rb
├── locales
│ ├── devise.en.yml
│ └── en.yml
├── nginx_default.tmpl
├── puma.rb
├── routes.rb
├── secrets.yml
├── spring.rb
└── storage.yml
├── db
├── migrate
│ ├── 20180702090814_devise_create_users.rb
│ ├── 20180703105143_rename_users_table.rb
│ ├── 20181012143652_create_activities.rb
│ ├── 20181018150144_remove_user_id_from_activities.rb
│ ├── 20181018154253_add_polymorphic_assiociation_to_activities.rb
│ ├── 20181104112129_create_table_view_builder.rb
│ ├── 20181105125119_create_work_lists.rb
│ ├── 20181108114556_add_sql_filters_to_work_lists.rb
│ ├── 20181108143841_change_work_lists_sql_query_to_string.rb
│ ├── 20181108144047_add_outcomes_to_work_lists.rb
│ ├── 20181116183747_add_data_table_name_to_work_lists.rb
│ ├── 20181122170852_add_visible_columns_to_work_list.rb
│ ├── 20181123181141_add_view_name_to_view_builder.rb
│ ├── 20181217165628_add_name_and_company_to_admin_users.rb
│ ├── 20181224073927_create_layout_settings_table.rb
│ ├── 20181224123606_add_visible_columns_to_layout_settings.rb
│ ├── 20190107134016_add_show_status_to_view_builders.rb
│ ├── 20190107134621_add_commentable_to_view_builders.rb
│ ├── 20190107134849_add_parent_comment_table_to_view_builders.rb
│ ├── 20190107135321_add_draggable_sections_to_view_builders.rb
│ ├── 20190115204330_rename_draggable_containers_on_view_builders.rb
│ ├── 20190303142750_add_hidden_columns_to_view_builder.rb
│ ├── 20190303142916_drop_layout_settings.rb
│ ├── 20190402151253_add_callable_fields_to_layout_builder.rb
│ ├── 20190424163632_create_task_queues.rb
│ ├── 20190425152656_add_query_builder_rules_to_task_queues.rb
│ ├── 20190429161124_add_raw_sql_to_task_queues.rb
│ ├── 20190513161432_add_query_builder_sql_to_task_queues.rb
│ ├── 20190516152746_add_draggable_fields_to_task_queues.rb
│ ├── 20190518152319_add_license_key_to_admin_users.rb
│ ├── 20190528153818_add_outcome_settings_to_task_queues.rb
│ ├── 20190531093327_add_full_license_to_admin_users.rb
│ ├── 20190605161402_create_task_queue_outcomes.rb
│ ├── 20190605161954_add_outcome_to_task_queue_outcomes.rb
│ ├── 20190605164115_add_unique_constraint_to_task_queue_outcomes.rb
│ ├── 20190620170803_add_related_tables_to_view_builder.rb
│ ├── 20190627172016_create_data_table_states.rb
│ ├── 20190807161323_add_ignore_layout_modal_to_admin_user.rb
│ ├── 20190817190347_create_permissions.rb
│ ├── 20190901110701_rolify_create_roles.rb
│ ├── 20190901125126_create_organisation_settings.rb
│ ├── 20191020103654_create_roles_permissions_table.rb
│ ├── 20191107072022_add_status_to_admin_users.rb
│ ├── 20191111185000_add_fields_to_roles.rb
│ ├── 20191123165832_create_target_table_settings.rb
│ ├── 20200111093456_add_database_table.rb
│ ├── 20200126125119_add_database_id_to_target_table_settings.rb
│ ├── 20200131135708_rename_database_password_field.rb
│ ├── 20200325153714_add_editable_fields_to_target_table_settings.rb
│ ├── 20200408133632_add_relay_gem_to_databases.rb
│ ├── 20200417114658_add_database_id_to_view_builders.rb
│ ├── 20200429134402_add_user_id_to_activity.rb
│ ├── 20200507093234_add_database_id_to_task_queues.rb
│ ├── 20200526152632_add_database_update_to_task_queues.rb
│ ├── 20200528143521_add_enabled_field_to_task_queue.rb
│ ├── 20200605105826_remove_null_restriction_task_queue_item.rb
│ ├── 20200607113114_add_database_id_to_activities.rb
│ ├── 20200628161055_create_active_storage_tables.active_storage.rb
│ ├── 20200628161056_add_service_name_to_active_storage_blobs.active_storage.rb
│ ├── 20200628161057_create_active_storage_variant_records.active_storage.rb
│ ├── 20210117152849_remove_unique_constraint_task_queue_index.rb
│ └── 20210130095843_add_primary_keys_to_target_table_settings.rb
├── schema.rb
└── seeds.rb
├── docker-compose.yml
├── lib
└── catch_error_from_rack.rb
├── log
└── .keep
├── package-lock.json
├── public
├── 422.html
├── assets
│ ├── .sprockets-manifest-45c6413dc95c4344a2238772146bbc2c.json
│ ├── application-2de56da153daf022d256045cc5d53b7183a603e0af9863d1638f6087e9138d52.css
│ ├── application-2de56da153daf022d256045cc5d53b7183a603e0af9863d1638f6087e9138d52.css.gz
│ ├── application-60fcce1a154ba59fc56911eb77ae0500d846e0ab7b1bc414b9b6e497c632d2c1.js
│ ├── application-60fcce1a154ba59fc56911eb77ae0500d846e0ab7b1bc414b9b6e497c632d2c1.js.gz
│ ├── bootstrap
│ │ ├── glyphicons-halflings-regular-13634da87d9e23f8c3ed9108ce1724d183a39ad072e73e1b3d8cbf646d2d0407.eot
│ │ ├── glyphicons-halflings-regular-13634da87d9e23f8c3ed9108ce1724d183a39ad072e73e1b3d8cbf646d2d0407.eot.gz
│ │ ├── glyphicons-halflings-regular-42f60659d265c1a3c30f9fa42abcbb56bd4a53af4d83d316d6dd7a36903c43e5.svg
│ │ ├── glyphicons-halflings-regular-42f60659d265c1a3c30f9fa42abcbb56bd4a53af4d83d316d6dd7a36903c43e5.svg.gz
│ │ ├── glyphicons-halflings-regular-a26394f7ede100ca118eff2eda08596275a9839b959c226e15439557a5a80742.woff
│ │ ├── glyphicons-halflings-regular-e395044093757d82afcb138957d06a1ea9361bdcf0b442d06a18a8051af57456.ttf
│ │ ├── glyphicons-halflings-regular-e395044093757d82afcb138957d06a1ea9361bdcf0b442d06a18a8051af57456.ttf.gz
│ │ └── glyphicons-halflings-regular-fe185d11a49676890d47bb783312a0cda5a44c4039214094e7957b4c040ef11c.woff2
│ ├── dataTable
│ │ ├── datatables.min-39255d21ad998b32b2fc7eb4a073a5e0b89acb2fcbdd1f90d9a6fc3aa43f656b.js
│ │ └── datatables.min-39255d21ad998b32b2fc7eb4a073a5e0b89acb2fcbdd1f90d9a6fc3aa43f656b.js.gz
│ ├── dragula
│ │ ├── dragula.min-94edc9ac879d6bd3fbfa48b57d9742a08cadbbafe2f3233a1a9116c03f2b070f.js
│ │ └── dragula.min-94edc9ac879d6bd3fbfa48b57d9742a08cadbbafe2f3233a1a9116c03f2b070f.js.gz
│ ├── favicon-c14aaa6e1b7af86332a6497364938f801db6b1b3f4513dd70024bea60981a6ed.ico
│ ├── favicon-c14aaa6e1b7af86332a6497364938f801db6b1b3f4513dd70024bea60981a6ed.ico.gz
│ ├── fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2
│ ├── fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot
│ ├── fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot.gz
│ ├── fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf
│ ├── fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf.gz
│ ├── fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg
│ ├── fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg.gz
│ ├── fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff
│ ├── images
│ │ ├── Kuwinda_logo_full-blue-260.png
│ │ └── icons
│ │ │ ├── black-check-box-with-white-check.png
│ │ │ ├── black-checkbox-empty.svg
│ │ │ ├── blue_cat_loading.gif
│ │ │ ├── checked-1.png
│ │ │ ├── circle-with-check-symbol.png
│ │ │ ├── circle-with-contrast.png
│ │ │ ├── circle-with-cross.png
│ │ │ ├── close.png
│ │ │ ├── column.png
│ │ │ ├── database-1.png
│ │ │ ├── database-2.png
│ │ │ ├── edit.png
│ │ │ ├── edit@2x.png
│ │ │ ├── export.png
│ │ │ ├── group-3.png
│ │ │ ├── import.png
│ │ │ ├── magnifying-glass.png
│ │ │ ├── minus-thick.png
│ │ │ ├── plus-thick.png
│ │ │ ├── plus.png
│ │ │ ├── report.png
│ │ │ ├── settings-1.png
│ │ │ ├── settings-black.png
│ │ │ ├── settings.png
│ │ │ ├── team-1.png
│ │ │ └── triangle.svg
│ ├── logos
│ │ ├── MissionKontrol-logo-inverted.png
│ │ ├── MissionKontrol-logo-original.png
│ │ └── kuwinda_thumbnail.png
│ ├── moment
│ │ ├── moment.min-a4f754452a828ad057b1b61c20fcb99251bb8fa7db0dba8ca96417b8e5d59c6c.js
│ │ └── moment.min-a4f754452a828ad057b1b61c20fcb99251bb8fa7db0dba8ca96417b8e5d59c6c.js.gz
│ ├── patterns
│ │ ├── header-profile-c05909898218a521d3bd19ba09a9a43338de6de5fdf1d3fc771b0ec28ae416c5.png
│ │ └── shattered-241155c2a3436bfc0a542fc31fe2908ff2bdfc90e1ac7e26c6ba715b01030dcf.png
│ ├── query-builder
│ │ ├── query-builder.min-252935bd0b5adbde13e1c5c616820f8a3a4f5cf645d690905bc728a80eeebe07.js
│ │ └── query-builder.min-252935bd0b5adbde13e1c5c616820f8a3a4f5cf645d690905bc728a80eeebe07.js.gz
│ ├── shopify
│ │ ├── draggable.bundle-06c5ee80a53567c4a8f91f12174da87600991bb912404d73dbc1e66cbd8b2c94.js
│ │ ├── draggable.bundle-06c5ee80a53567c4a8f91f12174da87600991bb912404d73dbc1e66cbd8b2c94.js.gz
│ │ ├── sortable-8042a7900fcf2bf2e78d523d4cc0b896ec1151b893c9fe62dc702d6e047df669.js
│ │ └── sortable-8042a7900fcf2bf2e78d523d4cc0b896ec1151b893c9fe62dc702d6e047df669.js.gz
│ └── sweetAlert
│ │ ├── sweetalert.min-c517df19a3eecca1c27936dfafd34163d0c1c81271aa6f914db8d5b1e7731d2f.js
│ │ └── sweetalert.min-c517df19a3eecca1c27936dfafd34163d0c1c81271aa6f914db8d5b1e7731d2f.js.gz
├── favicon.ico
└── robots.txt
├── spec
├── factories
│ ├── activity.rb
│ ├── admin_user.rb
│ ├── database.rb
│ ├── organisation_setting.rb
│ ├── permission.rb
│ ├── role.rb
│ ├── target_table_setting.rb
│ ├── task_queue.rb
│ ├── user.rb
│ ├── view_builder.rb
│ └── work_list.rb
├── features
│ ├── cache_connection_spec.rb
│ ├── single_data_view
│ │ ├── create_single_data_view_spec.rb
│ │ └── dragging_primary_fields_to_container_spec.rb
│ ├── tables
│ │ ├── add_record_spec.rb
│ │ ├── admin_views_table_detail_without_layout_spec.rb
│ │ ├── admin_views_table_spec.rb
│ │ ├── delete_records_spec.rb
│ │ ├── edit_record_spec.rb
│ │ └── settings_spec.rb
│ └── users
│ │ ├── admin_log_in_spec.rb
│ │ ├── permissions_spec.rb
│ │ └── registration_spec.rb
├── fixtures
│ ├── events.yml
│ └── users.yml
├── rails_helper.rb
├── spec_helper.rb
├── support
│ ├── features
│ │ ├── session_helpers.rb
│ │ ├── table_session_helpers.rb
│ │ └── target_database_helpers.rb
│ ├── time_helpers.rb
│ ├── unit
│ │ ├── fake_active_record.rb
│ │ └── session_helpers.rb
│ └── wait_for_ajax.rb
└── unit
│ ├── controllers
│ ├── dashboard_controller_spec.rb
│ ├── databases_controller_spec.rb
│ ├── layout_builder_controller_spec.rb
│ ├── organisation_settings_controller_spec.rb
│ ├── permissions_controller_spec.rb
│ ├── roles_controller_spec.rb
│ ├── tables_controller_spec.rb
│ └── task_queues_controller_spec.rb
│ ├── lib
│ └── kuwinda
│ │ ├── database_adapter_spec.rb
│ │ ├── gateway
│ │ └── database_connection_gateway_spec.rb
│ │ ├── presenter
│ │ ├── list_available_tables_spec.rb
│ │ ├── list_relatable_tables_spec.rb
│ │ ├── list_table_fields_spec.rb
│ │ ├── list_table_fields_with_type_spec.rb
│ │ └── retrieve_data_spec.rb
│ │ ├── repository
│ │ └── target_db_spec.rb
│ │ └── use_case
│ │ └── database_connection_spec.rb
│ ├── models
│ ├── activity_spec.rb
│ ├── admin_user_spec.rb
│ ├── concerns
│ │ └── sensitive_data_spec.rb
│ ├── data_table_state_spec.rb
│ ├── database_spec.rb
│ ├── role_spec.rb
│ ├── sql_filter_factory_spec.rb
│ ├── sql_filter_spec.rb
│ ├── target_table_setting_spec.rb
│ ├── task_queue_spec.rb
│ ├── view_builder_spec.rb
│ └── work_list_spec.rb
│ └── services
│ └── verify_license_key_service_spec.rb
└── vendor
└── assets
├── fonts
└── Casino_Hand
│ ├── casino_hand-webfont.eot
│ ├── casino_hand-webfont.svg
│ ├── casino_hand-webfont.ttf
│ └── casino_hand-webfont.woff
├── images
├── animated-overlay.gif
├── blueimp
│ └── img
│ │ ├── error.png
│ │ ├── error.svg
│ │ ├── loading.gif
│ │ ├── play-pause.png
│ │ ├── play-pause.svg
│ │ ├── video-play.png
│ │ └── video-play.svg
├── bootstrap-colorpicker
│ ├── alpha-horizontal.png
│ ├── alpha.png
│ ├── hue-horizontal.png
│ ├── hue.png
│ └── saturation.png
├── chosen-sprite.png
├── chosen-sprite@2x.png
├── green.png
├── green@2x.png
├── iCheck
│ ├── green.png
│ └── green@2x.png
├── images
│ ├── animated-overlay.gif
│ ├── ui-bg_flat_0_aaaaaa_40x100.png
│ ├── ui-bg_flat_75_ffffff_40x100.png
│ ├── ui-bg_glass_55_fbf9ee_1x400.png
│ ├── ui-bg_glass_65_ffffff_1x400.png
│ ├── ui-bg_glass_75_dadada_1x400.png
│ ├── ui-bg_glass_75_e6e6e6_1x400.png
│ ├── ui-bg_glass_95_fef1ec_1x400.png
│ ├── ui-bg_highlight-soft_75_cccccc_1x100.png
│ ├── ui-icons_222222_256x240.png
│ ├── ui-icons_2e83ff_256x240.png
│ ├── ui-icons_454545_256x240.png
│ ├── ui-icons_888888_256x240.png
│ └── ui-icons_cd0a0a_256x240.png
├── sort.png
├── sort_asc.png
├── sort_desc.png
├── sprite-skin-flat.png
├── sprite-skin-flat2.png
├── sprite-skin-nice.png
├── sprite-skin-simple.png
├── spritemap.png
└── spritemap@2x.png
├── javascripts
├── .keep
├── bootstrap
│ └── bootstrap-datepicker.js
├── dataTable
│ └── datatables.min.js
├── dotjs
│ └── doT.min.js
├── dragula
│ └── dragula.min.js
├── dualListbox
│ └── jquery.bootstrap-duallistbox.js
├── enjoyhint
│ └── enjoyhint.js
├── extendext
│ └── jQuery.extendext.min.js
├── flot
│ ├── curvedLines.js
│ ├── excanvas.min.js
│ ├── jquery.flot.js
│ ├── jquery.flot.pie.js
│ ├── jquery.flot.resize.js
│ ├── jquery.flot.spline.js
│ ├── jquery.flot.symbol.js
│ ├── jquery.flot.time.js
│ └── jquery.flot.tooltip.min.js
├── inspinia
│ └── inspinia.js
├── jquery
│ └── jquery-3.1.1.min.js
├── metisMenu
│ └── jquery.metisMenu.js
├── moment
│ └── moment.min.js
├── query-builder
│ └── query-builder.min.js
├── shopify
│ ├── draggable.bundle.js
│ └── sortable.js
├── sweetAlert
│ └── sweetalert.min.js
├── toastr
│ └── toastr.min.js
└── tooltipster
│ └── tooltipster.bundle.min.js
└── stylesheets
├── dataTable
└── datatables.scss
├── dragula
└── dragula.min.css
├── images
├── bootstrap-colorpicker
│ ├── alpha-horizontal.png
│ ├── alpha.png
│ ├── hue-horizontal.png
│ ├── hue.png
│ └── saturation.png
├── sort.png
├── sort_asc.png
├── sort_desc.png
├── sprite-skin-flat.png
├── sprite-skin-flat2.png
├── sprite-skin-nice.png
├── sprite-skin-simple.png
├── spritemap.png
└── spritemap@2x.png
├── jQueryUI
├── images
│ ├── animated-overlay.gif
│ ├── ui-bg_flat_0_aaaaaa_40x100.png
│ ├── ui-bg_flat_75_ffffff_40x100.png
│ ├── ui-bg_glass_55_fbf9ee_1x400.png
│ ├── ui-bg_glass_65_ffffff_1x400.png
│ ├── ui-bg_glass_75_dadada_1x400.png
│ ├── ui-bg_glass_75_e6e6e6_1x400.png
│ ├── ui-bg_glass_95_fef1ec_1x400.png
│ ├── ui-bg_highlight-soft_75_cccccc_1x100.png
│ ├── ui-icons_222222_256x240.png
│ ├── ui-icons_2e83ff_256x240.png
│ ├── ui-icons_454545_256x240.png
│ ├── ui-icons_888888_256x240.png
│ └── ui-icons_cd0a0a_256x240.png
├── jquery-ui-1.10.4.custom.min.css
└── jquery-ui.css
├── query-builder
└── query-builder.default.min.css
├── toastr
└── toastr.min.css
└── tooltipster
├── tooltipster-sideTip-shadow.min.css
└── tooltipster.bundle.min.css
/.dockerignore:
--------------------------------------------------------------------------------
1 | log/*
2 | ssl/*
3 | tmp/*
4 | .git
5 |
6 | Dockerfile
7 | Makefile
8 | .bash_history
9 | docker-compose.yml
10 | .env
11 |
12 | spec/
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files.
2 | #
3 | # If you find yourself ignoring temporary files generated by your text editor
4 | # or operating system, you probably want to add a global ignore instead:
5 | # git config --global core.excludesfile '~/.gitignore_global'
6 |
7 | # Ignore bundler config.
8 | /.bundle
9 | .env
10 |
11 | # Ignore all logfiles and tempfiles.
12 | /log/*
13 | !/log/.keep
14 | /tmp
15 | .bash_history
16 | .env
17 | ssl
18 |
19 | .byebug_history
20 |
21 | Guardfile
22 |
23 | config/admin_db_*
24 | config/target_db_*
25 | config/sensitive_data/*
26 |
27 | .env
28 | .ruby-version
29 | .DS_Store
30 |
31 | coverage/
32 |
33 | node_modules/
34 |
35 | custom_plan.rb
36 | zeus.json
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --require spec_helper
2 | --require rails_helper
3 | --format documentation
4 |
--------------------------------------------------------------------------------
/.rubocop.yml:
--------------------------------------------------------------------------------
1 | inherit_from: .rubocop_todo.yml
2 |
3 | AllCops:
4 | Exclude:
5 | - 'db/schema.rb'
6 | - 'config/initializers/devise.rb'
7 | - 'db/migrate/*'
8 | - 'Guardfile'
9 | - 'bin/*'
10 | - 'config/*'
11 | - 'Rakefile'
12 |
13 | Documentation:
14 | Enabled: false
15 |
16 | Metrics/BlockLength:
17 | ExcludedMethods: ['describe', 'context', 'feature']
18 |
19 | Metrics/ClassLength:
20 | Exclude:
21 | - 'app/lib/kuwinda/repository/target_db.rb'
22 |
23 | Metrics/ModuleLength:
24 | Max: 200
25 | Exclude:
26 | - 'spec/unit/lib/kuwinda/repository/target_db_spec.rb'
27 |
28 | Layout/FirstArrayElementIndentation:
29 | Exclude:
30 | - 'db/seeds.rb'
31 |
--------------------------------------------------------------------------------
/.stylelintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "stylelint-config-standard",
3 | "rules": {
4 | "no-descending-specificity": null,
5 | "at-rule-no-unknown": [
6 | true,
7 | {
8 | "ignoreAtRules": ["extend"]
9 | }
10 | ]
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | start:
2 | docker-compose build
3 | docker-compose up -d
4 |
5 | stop:
6 | docker-compose stop
7 |
8 | restart: stop start
9 |
10 | clean:
11 | docker-compose down -v
12 |
13 | bash:
14 | docker-compose run --rm --service-ports web
15 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: bin/rails server -p $PORT -e $RAILS_ENV
2 | worker: bundle exec clockwork clock.rb
3 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # Add your own tasks in files placed in lib/tasks ending in .rake,
2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3 |
4 | require File.expand_path('../config/application', __FILE__)
5 |
6 | Rails.application.load_tasks
7 |
--------------------------------------------------------------------------------
/app/assets/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/app/assets/images/favicon.ico
--------------------------------------------------------------------------------
/app/assets/images/patterns/header-profile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/app/assets/images/patterns/header-profile.png
--------------------------------------------------------------------------------
/app/assets/images/patterns/shattered.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/app/assets/images/patterns/shattered.png
--------------------------------------------------------------------------------
/app/assets/javascripts/app/components/charts.js:
--------------------------------------------------------------------------------
1 | //= require flot/jquery.flot.js
2 | //= require flot/jquery.flot.spline.js
3 |
--------------------------------------------------------------------------------
/app/assets/javascripts/app/components/faIcons.js:
--------------------------------------------------------------------------------
1 | function replaceArrowGlypicon () {
2 | $(".glyphicon-arrow-right").addClass("fa fa-arrow-right").removeClass("glyphicon glyphicon-arrow-right");
3 | $(".glyphicon-arrow-left").addClass("fa fa-arrow-left").removeClass("glyphicon glyphicon-arrow-left");
4 | }
5 |
6 | $(document).ready(function() {
7 | replaceArrowGlypicon();
8 | });
9 |
--------------------------------------------------------------------------------
/app/assets/javascripts/app/components/listSort.js:
--------------------------------------------------------------------------------
1 | // var ready, setPositions;
2 |
3 | // setPositions = function(){
4 | // $(".tableField").each(function(i){
5 | // $(this).attr("data-pos",i+1);
6 | // });
7 | // }
8 |
9 | // ready = function(){
10 | // setPositions();
11 |
12 | // sortable(".sortable");
13 |
14 | // if (sortable(".sortable")[0]) {
15 | // sortable(".sortable")[0].addEventListener("sortupdate", function(e, ui) {
16 | // // array to store new order
17 | // updatedOrder = [];
18 | // // set the updated positions
19 | // setPositions();
20 |
21 | // // populate the updatedOrder array with the new task positions
22 | // $(".tableField").each(function(i){
23 | // updatedOrder.push({ value: $(this).data("value"), position: i+1 });
24 | // });
25 | // });
26 | // }
27 | // }
28 |
29 | // $(document).ready(ready);
30 | // /**
31 | // * if using turbolinks
32 | // */
33 | // $(document).on("page:load", ready);
34 |
--------------------------------------------------------------------------------
/app/assets/javascripts/app/components/modal.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | function closeModal() {
4 | $("body").on("click", ".modal--close-btn", function () {
5 | var modal = $(this).parents(".show");
6 | modal.removeClass("show");
7 | modal.addClass("hide");
8 | $("button.table--settings").attr("disabled", false);
9 | });
10 | }
11 |
12 | $(document).ready(function () {
13 | closeModal();
14 | });
--------------------------------------------------------------------------------
/app/assets/javascripts/app/components/tables.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/app/assets/javascripts/app/components/tables.js
--------------------------------------------------------------------------------
/app/assets/javascripts/app/registration.js:
--------------------------------------------------------------------------------
1 | function goToRegistrationStep(step) {
2 | $("#registration-step-1, #registration-step-2").toggleClass("hide");
3 | }
4 |
5 | function checkPasswordMatch() {
6 | let password = $("#admin_user_password").val();
7 | let confirmPassword = $("#admin_user_password_confirmation").val();
8 |
9 | if (password === confirmPassword) {
10 | $("#password-mismatch").hide();
11 | $("#next-registration-step").attr("disabled", false);
12 | } else {
13 | $("#password-mismatch").show();
14 | $("#next-registration-step").attr("disabled", true);
15 | }
16 | }
17 |
18 | $(document).ready(function () {
19 | $("#password-mismatch").hide();
20 | $("#admin_user_password, #admin_user_password_confirmation").keyup(function() {
21 | checkPasswordMatch();
22 | });
23 | });
24 |
25 |
--------------------------------------------------------------------------------
/app/assets/javascripts/app/target_table_settings.js:
--------------------------------------------------------------------------------
1 | function toggleCheckbox () {
2 | $("body").on("change", ".toggle-state:checkbox", function (e) {
3 | let value = $(this).val();
4 | if (value === "false") {
5 | $(this).val("true");
6 | } else if (value === "true") {
7 | $(this).val("false");
8 | }
9 | });
10 | }
11 |
12 | $(document).ready(function() {
13 | toggleCheckbox();
14 | });
--------------------------------------------------------------------------------
/app/assets/javascripts/application.js:
--------------------------------------------------------------------------------
1 | // This is a manifest file that'll be compiled into application.js, which will include all the files
2 | // listed below.
3 | //
4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5 | // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6 | //
7 | //
8 | //= require jquery/jquery-3.1.1.min.js
9 | //= require rails-ujs
10 | //= require inspinia/inspinia
11 | //= require bootstrap-sprockets
12 | //= require metisMenu/jquery.metisMenu.js
13 | //= require toastr/toastr.min.js
14 | //= require dualListbox/jquery.bootstrap-duallistbox.js
15 | //= require extendext/jQuery.extendext.min.js
16 | //= require dotjs/doT.min.js
17 | //= require bootstrap/bootstrap-datepicker.js
18 | //= require tooltipster/tooltipster.bundle.min.js
19 | //= require paloma
20 | //= require palomaInitializer
21 | //= require_tree .
22 | //= require draggable
23 | //= require layout_builder
24 | //= require task_queue_builder
25 |
--------------------------------------------------------------------------------
/app/assets/javascripts/page_specific/adminUser.js:
--------------------------------------------------------------------------------
1 | function submitSettingsChange () {
2 | $("body").on("change", "#role--edit-settings:checkbox", function () {
3 | var id = $(this).data("role");
4 | var setting = $(this).data("setting");
5 | $.ajax({
6 | method: "PUT",
7 | url: "/roles",
8 | data: {
9 | id: id,
10 | setting: setting
11 | },
12 | });
13 | });
14 |
15 | $("body").on("change", "#role--export-limit", function () {
16 | var id = $(this).data("role");
17 | var limit = $(this).val();
18 | $.ajax({
19 | method: "PUT",
20 | url: "/roles",
21 | data: {
22 | id: id,
23 | limit: limit
24 | },
25 | })
26 | });
27 | }
28 |
29 | Paloma.controller("AdminUsers", {
30 | index () {
31 | submitSettingsChange();
32 | }
33 | });
34 |
--------------------------------------------------------------------------------
/app/assets/javascripts/page_specific/dashboard.js:
--------------------------------------------------------------------------------
1 | Paloma.controller("Dashboard", {
2 | show () {
3 | $(".spinner").hide();
4 | }
5 | });
--------------------------------------------------------------------------------
/app/assets/javascripts/page_specific/database.js:
--------------------------------------------------------------------------------
1 | function submitPasswordChange () {
2 | $("input#database_password").on("change", function () {
3 | $("#database_password_changed").val(true);
4 | });
5 | }
6 |
7 | function clearGemCredentials () {
8 | $("#remove-gem-connection").on("click", function () {
9 | $("#database_domain_url").val("");
10 | $("#database_gem_token").val("");
11 | });
12 | }
13 |
14 | Paloma.controller("Databases", {
15 | new () {
16 | submitPasswordChange();
17 | },
18 |
19 | edit () {
20 | submitPasswordChange();
21 | clearGemCredentials();
22 | }
23 | });
--------------------------------------------------------------------------------
/app/assets/javascripts/page_specific/organisationSetting.js:
--------------------------------------------------------------------------------
1 | Paloma.controller("OrganisationSettings", {
2 | edit () {
3 | $(".spinner").hide();
4 | }
5 | });
--------------------------------------------------------------------------------
/app/assets/javascripts/page_specific/permissions.js:
--------------------------------------------------------------------------------
1 | Paloma.controller("Permissions", {
2 | index () {
3 | $(".spinner").hide();
4 | }
5 | });
--------------------------------------------------------------------------------
/app/assets/javascripts/palomaInitializer.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function(){
2 | Paloma.start();
3 | $.fn.dataTable.ext.errMode = 'throw';
4 |
5 | });
6 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/application.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * This is a manifest file that'll be compiled into application.css, which will include all the files
3 | * listed below.
4 | *
5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6 | * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7 | *
8 | * You're free to add application-wide styles to this file and they'll appear at the top of the
9 | * compiled file, but it's generally better to create a new file per style scope.
10 | *
11 |
12 | *= require toastr/toastr.min.css
13 | *= require query-builder/query-builder.default.min.css
14 | *= require dataTable/datatables.scss
15 | *= require jQueryUI/jquery-ui.css
16 | *= require dragula/dragula.min.css
17 | *= require tooltipster/tooltipster.bundle.min.css
18 | *= require tooltipster/tooltipster-sideTip-shadow.min.css
19 | *= require font-awesome
20 | *= require site
21 | *= require devise
22 | *= require_self
23 | */
24 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/components/_toastr.scss:
--------------------------------------------------------------------------------
1 | .toast {
2 | background-color: #030303;
3 | }
4 |
5 | .toast-success {
6 | background-color: $blueberry;
7 | }
8 |
9 | .toast-error {
10 | background-color: $info-red;
11 | }
12 |
13 | .toast-info {
14 | background-color: $cool-blue;
15 | }
16 |
17 | .toast-warning {
18 | background-color: $dark-salmon;
19 | }
20 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/components/_tooltipster.scss:
--------------------------------------------------------------------------------
1 | .tooltip_templates {
2 | position: relative;
3 | opacity: 1;
4 | }
5 |
6 | .tooltipster-sidetip.tooltipster-shadow.tooltipster-shadow-customized {
7 | .tooltipster-content {
8 | width: 125px;
9 | height: 64px;
10 | box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.2);
11 | text-align: center;
12 | font-size: 14px;
13 | }
14 |
15 | #tooltip_content {
16 | vertical-align: middle;
17 | padding-top: 6px;
18 |
19 | a {
20 | color: $link-gray;
21 |
22 | &:hover {
23 | color: $purple;
24 | font-weight: bold;
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/dashboard.scss:
--------------------------------------------------------------------------------
1 | .dashboard--title {
2 | padding-left: 3%;
3 | height: 5%;
4 | }
5 |
6 | .dashboard--system {
7 | padding-top: 15px;
8 | }
9 |
10 | .dashboard--trial-license {
11 | border: solid 0.5px $blueberry;
12 | background-color: $white;
13 | padding-left: 3%;
14 | padding-bottom: 1%;
15 | }
16 |
17 | .dashboard--panels {
18 | margin-top: 30px;
19 | }
20 |
21 | .dashboard--panel {
22 | background-color: $white;
23 | height: 200px;
24 | padding: 15px;
25 | padding-top: 22px;
26 | text-align: center;
27 |
28 | img {
29 | height: 80px;
30 | }
31 | }
32 |
33 | [data-link] {
34 | cursor: pointer;
35 | }
36 |
37 | .spinner {
38 | position: absolute;
39 | z-index: 1000;
40 | left: 50%;
41 | top: 45%;
42 | background-color: $white;
43 | border: solid 0.5px $blueberry;
44 | border-radius: 100%;
45 |
46 | img {
47 | border-radius: 100%;
48 | padding: 0.6em;
49 | width: 96px;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/site.scss:
--------------------------------------------------------------------------------
1 | // Google Fonts
2 | @import url("https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&lang=en&display=swap");
3 |
4 | // Bootstrap
5 | @import "bootstrap-sprockets";
6 | @import "bootstrap";
7 |
8 | // Variables, Mixins, Base
9 | @import "base/variables";
10 | @import "base/typography";
11 | @import "base/globals.scss";
12 | @import "base/margins_and_paddings";
13 | @import "base/navigation";
14 | @import "base/buttons";
15 | @import "base/modal";
16 | @import "base/form";
17 | @import "base/activity";
18 | @import "views";
19 | @import "admin_users";
20 | @import 'table';
21 | @import 'layout_builder';
22 | @import 'single_view_builder';
23 | @import 'task_queues';
24 | @import 'dashboard';
25 | @import 'table_permissions';
26 | @import 'components/tooltipster';
27 | @import 'components/toastr';
28 | @import "base/media";
29 |
30 | // Clear layout on print mode
31 | @media print {
32 | nav.navbar-static-side {
33 | display: none;
34 | }
35 |
36 | body { overflow: visible !important; }
37 |
38 | #page-wrapper {
39 | margin: 0;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/views.scss:
--------------------------------------------------------------------------------
1 | .display-inline {
2 | display: inline-block;
3 | }
4 |
5 | span.editable-actions {
6 | margin-left: 5px;
7 | }
8 |
--------------------------------------------------------------------------------
/app/controllers/admin_user_sessions_controller.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class AdminUserSessionsController < Devise::SessionsController
4 | before_action :check_admin_user_exists, only: [:new]
5 |
6 | private
7 |
8 | def check_admin_user_exists
9 | redirect_path = OrganisationSetting.any? && AdminUser.any? ? nil : new_admin_user_registration_path
10 |
11 | redirect_to redirect_path if redirect_path.present?
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/app/controllers/call_controller.rb:
--------------------------------------------------------------------------------
1 | class CallController < ApplicationController
2 | skip_before_action :verify_authenticity_token
3 |
4 | def connect
5 | render xml: twilio_reponse
6 | end
7 |
8 | private
9 |
10 | def twilio_reponse
11 | admin = AdminUser.last
12 |
13 | res = Twilio::TwiML::VoiceResponse.new do |response|
14 | dial = Twilio::TwiML::Dial.new caller_id: admin.twilio_caller_id
15 | dial.number params[:phoneNumber]
16 | response.append(dial)
17 | end
18 | return res.to_s
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/app/controllers/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/app/controllers/concerns/.keep
--------------------------------------------------------------------------------
/app/controllers/concerns/relatable_tables.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module RelatableTables
4 | extend ActiveSupport::Concern
5 |
6 | private
7 |
8 | def set_relatable_tables
9 | @relatable_tables = []
10 |
11 | relatable_tables(@current_table).each do |table|
12 | # layout = ViewBuilder.find_by_table_name(table)
13 | relative = {}
14 | # @target_db.table = table
15 | foreign_key_title = helpers.get_foreign_key(params[:table_name])
16 | foreign_key_value = params[:record_id]
17 | sql_result = @target_db.find_all_related(table, foreign_key_title, foreign_key_value, 10, 0)
18 | relative[:headers] = sql_result ? sql_result.columns : []
19 | relative[:name] = table
20 | @relatable_tables << relative
21 | end
22 |
23 | @relatable_tables
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/app/controllers/concerns/user_abilities.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module UserAbilities
4 | extend ActiveSupport::Concern
5 |
6 | private
7 |
8 | def check_user_admin_abilities
9 | redirect_to(root_path) unless current_admin_user.admin_abilities?
10 | end
11 |
12 | def check_user_editor_abilities
13 | redirect_to(root_path) unless current_admin_user.editor_abilities? || current_admin_user.admin_abilities?
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/controllers/data_table_states_controller.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class DataTableStatesController < ApplicationController
4 | def load
5 | dts = DataTableState.find_by_table(params[:table])
6 | respond_to do |format|
7 | format.js do
8 | if dts
9 | render json: dts.state_as_json
10 | else
11 | render json: {}
12 | end
13 | end
14 | end
15 | end
16 |
17 | def save
18 | dts = DataTableState.where(table: params[:table]).first_or_create
19 | dts.state = state_params.to_h
20 | dts.table = params[:table]
21 | dts.save
22 |
23 | respond_to do |format|
24 | format.js do
25 | render json: dts.state_as_json
26 | end
27 | end
28 | end
29 |
30 | private
31 |
32 | def state_params
33 | params.require(:state).permit!
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/app/controllers/errors_controller.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class ErrorsController < ApplicationController
4 | def not_found
5 | respond_to do |format|
6 | format.html { render status: 404, layout: 'dashboard' }
7 | format.js { render status: 404, layout: 'dashboard' }
8 | end
9 | end
10 |
11 | def internal_server_error
12 | respond_to do |format|
13 | format.html { render status: 500, layout: 'dashboard' }
14 | format.js { render status: 500, layout: 'dashboard' }
15 | end
16 | end
17 |
18 | def not_acceptable
19 | respond_to do |format|
20 | format.html { render status: 406, layout: 'dashboard' }
21 | format.js { render status: 406, layout: 'dashboard' }
22 | end
23 | end
24 |
25 | def not_authorized
26 | respond_to do |format|
27 | format.html { render status: 401, layout: 'dashboard' }
28 | format.js { render status: 401, layout: 'dashboard' }
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/app/controllers/home_controller.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class HomeController < ApplicationController
4 | def index
5 | redirect_to dashboard_path if admin_user_signed_in?
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/app/controllers/organisation_settings_controller.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class OrganisationSettingsController < ApplicationController
4 | include UserAbilities
5 |
6 | layout 'standard'
7 |
8 | before_action :check_user_admin_abilities, only: %i[edit]
9 |
10 | def edit
11 | @organisation = OrganisationSetting.find params[:id]
12 | end
13 |
14 | def update
15 | @organisation = OrganisationSetting.find params[:id]
16 | unchanged_key = organisation_params[:license_key] == @organisation.license_key
17 |
18 | unless unchanged_key
19 | valid_license = activate_license(organisation_params[:license_key])
20 | @invalid_key = !valid_license
21 | end
22 |
23 | @result = @organisation.update!(organisation_params) if valid_license || unchanged_key
24 | end
25 |
26 | private
27 |
28 | def organisation_params
29 | params.require(:organisation_setting).permit(:company_name, :license_key)
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/app/controllers/token_controller.rb:
--------------------------------------------------------------------------------
1 | class TokenController < ApplicationController
2 | skip_before_action :verify_authenticity_token
3 |
4 | ## TODO: FIX THIS SHIT
5 | def generate
6 | # token = Rails.env.test? ? 'token' : ::Twilio::Capability.generate(current_admin_user)
7 |
8 | render json: { token: 'token' }
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/errors/invalid_client_database_error.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class InvalidClientDatabaseError < StandardError
4 | def initialize(msg = 'Client database is invalid')
5 | super
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/app/errors/not_authorized_error.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class NotAuthorizedError < StandardError
4 | def initialize(msg = 'Not authorized to perform this action')
5 | super
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/app/errors/sql_database_error.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class SqlDatabaseError < StandardError
4 | def initialize(msg = 'Something went wrong with the SQL query.')
5 | super
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/app/errors/unable_to_save_record_error.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class UnableToSaveRecordError < StandardError
4 | def initialize(msg = 'Something went wrong and we cannot save the record')
5 | super
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/app/helpers/activity_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module ActivityHelper
4 | def render_activity(activity)
5 | name = activity.admin_user == current_admin_user ? 'You' : activity.admin_user.full_name
6 | case activity.kind
7 | when 'note'
8 | content_tag(:strong, name) +
9 | content_tag(:span, ' added a ') +
10 | content_tag(:strong, 'comment: ') +
11 | content_tag(:span, activity.content.to_s)
12 | when 'outcome'
13 | content_tag(:strong, name) +
14 | content_tag(:span, ' added a ') +
15 | content_tag(:strong, 'tag: ') +
16 | content_tag(:span, activity.content.to_s)
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/app/helpers/devise_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module DeviseHelper
4 | def devise_error_messages!
5 | return '' if resource.errors.empty?
6 |
7 | messages = resource.errors.full_messages.map do |msg|
8 | content_tag(:li, msg)
9 | end.join
10 | html = <<-HTML
11 |
x
13 | #{messages}
14 |
15 | HTML
16 |
17 | html.html_safe
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/app/helpers/view_builder_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module ViewBuilderHelper
4 | def status_options
5 | [
6 | ['Pending', 'pending', { class: 'select-pending' }],
7 | ['Active', 'active', { class: 'select-active' }],
8 | ['Deactivated', 'deactivated', { class: 'select-deactivated' }]
9 | ]
10 | end
11 |
12 | def display_border?(container)
13 | container.empty? ? 'layout-placeholder--border' : ''
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/lib/assets/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/app/lib/assets/.keep
--------------------------------------------------------------------------------
/app/lib/catch_error_from_rack.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'rack'
4 |
5 | class CatchErrorFromRack
6 | def initialize(app)
7 | @app = app
8 | end
9 |
10 | def call(env)
11 | status, headers, body = @app.call(env)
12 | [status, headers, body]
13 | rescue ActiveRecord::ConnectionNotEstablished
14 | ActiveRecord::Base.establish_connection
15 | status, headers, body = @app.call(env)
16 | [status, headers, body]
17 | rescue ActionController::BadRequest
18 | [301, { 'Location' => get_hostname(env) }, []]
19 | end
20 |
21 | def get_hostname(env)
22 | "#{env['SERVER_NAME']}:#{env['SERVER_PORT']}"
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/app/lib/kuwinda/database_adapter.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Kuwinda
4 | class DatabaseAdapter
5 | class << self
6 | def adapter(scheme)
7 | case scheme
8 | when 'postgresql', 'postgres'
9 | 'postgresql'
10 | when 'mysql', 'mysql2'
11 | 'mysql2'
12 | else
13 | raise InvalidClientDatabaseError.new("Do not know how to make adpater for #{scheme}")
14 | end
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/app/lib/kuwinda/presenter/list_table_fields.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Kuwinda
4 | module Presenter
5 | class ListTableFields
6 | def initialize(database, table)
7 | @database = database
8 | @table = table
9 | end
10 |
11 | def call
12 | Rails.cache.fetch("table_fields/#{database.database.friendly_name}/#{table}", expires_in: 12.hours) do
13 | fields = database.connect.connection.columns(table.downcase).map(&:name)
14 | ActiveRecord::Base.connection_pool.disconnect! if ActiveRecord::Base.connection_pool
15 | ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).first)
16 |
17 | fields
18 | end
19 | end
20 |
21 | private
22 |
23 | attr_reader :database, :table
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/app/lib/kuwinda/use_case/database_connection.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Kuwinda
4 | module UseCase
5 | class DatabaseConnection
6 | def initialize(database)
7 | @database = database
8 | @gateway = database_connection_gateway
9 | end
10 |
11 | def execute
12 | gateway
13 | end
14 |
15 | private
16 |
17 | attr_reader :gateway, :database
18 |
19 | def database_connection_gateway
20 | Kuwinda::Gateway::DatabaseConnectionGateway.new(database)
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/app/lib/tasks/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/app/lib/tasks/.keep
--------------------------------------------------------------------------------
/app/lib/tasks/assets.rake:
--------------------------------------------------------------------------------
1 | require 'sprockets/rails/task'
2 |
3 | Sprockets::Rails::Task.new(Rails.application) do |t|
4 | t.logger = Logger.new(STDOUT)
5 | end
--------------------------------------------------------------------------------
/app/lib/tasks/setup_staging_org_and_roles.rake:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | namespace :setup_org_and_roles do
4 | desc 'setup org'
5 | task setup_all: :environment do
6 | OrganisationSetting.create!(
7 | license_key: 'wcCXJZ5fd3TdekwrB5No912UO2-26',
8 | activation_id: '1559143878',
9 | full_license: false,
10 | company_name: 'Kuwinda Test'
11 | )
12 | create_admin
13 | create_roles('Sales')
14 | create_roles('Team Lead')
15 | end
16 | end
17 |
18 | def create_admin
19 | Role.create!(
20 | name: 'Admin',
21 | administrator: true,
22 | editor: true,
23 | export: true,
24 | export_limit: 0
25 | )
26 | end
27 |
28 | def create_roles(role)
29 | Role.create!(
30 | name: role,
31 | administrator: false,
32 | editor: false,
33 | export: false,
34 | export_limit: nil
35 | )
36 | end
37 |
--------------------------------------------------------------------------------
/app/lib/twilio/capability.rb:
--------------------------------------------------------------------------------
1 | module Twilio
2 | class Capability
3 | def self.generate(user)
4 | account_sid = user.twilio_account_sid
5 | auth_token = user.twilio_auth_token
6 | application_sid = user.twilio_application_sid
7 | role = user.role
8 |
9 | capability = Twilio::JWT::ClientCapability.new(account_sid, auth_token)
10 |
11 | outgoing_scope = Twilio::JWT::ClientCapability::OutgoingClientScope.new(application_sid, role)
12 | capability.add_scope outgoing_scope
13 |
14 | capability.to_s
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/mailers/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/app/mailers/.keep
--------------------------------------------------------------------------------
/app/models/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/app/models/.keep
--------------------------------------------------------------------------------
/app/models/ability.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class Ability
4 | include CanCan::Ability
5 |
6 | def initialize(user); end
7 |
8 | def can?(user, action, subject_class, subject_id)
9 | roles = user.roles.map do |role|
10 | role.permissions.where(action: action).any? do |permission|
11 | permission.subject_class == subject_class.to_s && permission.subject_id == subject_id
12 | end
13 | end
14 | roles.any? true
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/app/models/activity.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class Activity < ApplicationRecord
4 | KINDS = %w[note call meeting outcome].freeze
5 | ## TODO: Figure out the feedable_types based on database?
6 | # FEEDABLE_TYPES = Kuwinda::Presenter::ListAvailableTables.new(@database_connection).call
7 |
8 | validates :content, presence: true
9 | validates :kind, presence: true, inclusion: { in: KINDS }
10 | validates :feedable_id, presence: true
11 |
12 | belongs_to :admin_user, class_name: 'AdminUser', foreign_key: 'user_id'
13 | # validates :feedable_type, presence: true, inclusion: { in: FEEDABLE_TYPES }
14 | end
15 |
--------------------------------------------------------------------------------
/app/models/application_record.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class ApplicationRecord < ActiveRecord::Base
4 | self.abstract_class = true
5 | establish_connection Rails.env.to_sym
6 | end
7 |
--------------------------------------------------------------------------------
/app/models/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/app/models/concerns/.keep
--------------------------------------------------------------------------------
/app/models/concerns/client_record.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class ClientRecord < ActiveRecord::Base
4 | # self.abstract_class = true
5 | # Kuwinda::UseCase::DatabaseConnection.new.execute
6 | end
7 |
--------------------------------------------------------------------------------
/app/models/concerns/database_connection.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module DatabaseConnection
4 | def self.reconnect_to_database
5 | ActiveRecord::Base.connection_pool.disconnect! if ActiveRecord::Base.connection_pool
6 | ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).first)
7 | "reconnected" if ActiveRecord::Base.connection.active?
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/models/data_table_state.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class DataTableState < ApplicationRecord
4 | def state_as_json
5 | columns = []
6 |
7 | state['columns'].each do |_k, v|
8 | val = {}
9 | val['visible'] = ActiveModel::Type::Boolean.new.cast(v['visible'])
10 | val['search'] = v['search']
11 | columns << val
12 | end
13 |
14 | {
15 | time: state['time'].to_i,
16 | start: state['start'].to_i,
17 | length: state['length'].to_i,
18 | order: state['order'],
19 | search: state['search'],
20 | columns: columns
21 | }
22 | end
23 |
24 | def visible_columns
25 | visible_columns = []
26 |
27 | state['columns'].each do |key, value|
28 | visible_columns << key if value['visible'] == 'true'
29 | end
30 |
31 | visible_columns
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/app/models/database.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class Database < ApplicationRecord
4 | include DatabaseActions
5 | before_save :encrypt_database_password
6 |
7 | DATABASE_TYPES = [
8 | ['PostgreSQL', 'postgresql'],
9 | ['MySQL', 'mysql2']
10 | ].freeze
11 |
12 | private
13 |
14 | def encrypt_database_password
15 | crypt = ActiveSupport::MessageEncryptor.new(Rails.application.secrets.secret_key_base[0..31])
16 | password = self.password
17 | crypt.decrypt_and_verify(password)
18 | rescue ActiveSupport::MessageVerifier::InvalidSignature
19 | encrypted_data = crypt.encrypt_and_sign(password)
20 | self.password = encrypted_data
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/app/models/layout_setting.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class LayoutSetting < ApplicationRecord
4 | end
5 |
--------------------------------------------------------------------------------
/app/models/permission.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class Permission < ApplicationRecord
4 | # has_and_belongs_to_many :roles, join_table: :roles_permissions
5 | has_many :roles
6 | end
7 |
--------------------------------------------------------------------------------
/app/models/role.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class Role < ApplicationRecord
4 | # has_and_belongs_to_many :admin_users, join_table: :admin_users_roles
5 | has_and_belongs_to_many :permissions, join_table: :roles_permissions
6 | has_many :admin_users
7 |
8 | belongs_to :resource,
9 | polymorphic: true,
10 | optional: true
11 |
12 | validates :resource_type,
13 | inclusion: { in: Rolify.resource_types },
14 | allow_nil: true
15 |
16 | scopify
17 |
18 | def setting(setting_name)
19 | case setting_name
20 | when 'administrator'
21 | administrator? ? false : true
22 | when 'editor'
23 | editor? ? false : true
24 | when 'export'
25 | export? ? false : true
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/app/models/sql_filter.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'sql_filter/equal'
4 |
5 | module SQLFilter
6 | QUERY_CONDITIONS = [
7 | 'equal'
8 | ].freeze
9 | end
10 |
--------------------------------------------------------------------------------
/app/models/sql_filter/base.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SQLFilter
4 | class Base
5 | attr_accessor :kind,
6 | :column,
7 | :value,
8 | :operator
9 |
10 | def initialize(args = {})
11 | self.kind = args[:kind]
12 | self.column = args[:column]
13 | self.value = args[:value]
14 | self.operator = args[:operator]
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/models/sql_filter/equal.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SQLFilter
4 | class Equal < SQLFilter::Base
5 | def initialize(args = {})
6 | args[:kind] = 'equal'
7 | super(args)
8 | end
9 |
10 | def to_sql
11 | if operator
12 | "#{operator} #{column} = '#{value}' "
13 | else
14 | "where #{column} = '#{value}' "
15 | end
16 | end
17 |
18 | def to_hash
19 | hash = {}
20 | hash['kind'] = kind
21 | hash['column'] = column
22 | hash['operator'] = operator
23 | hash['value'] = value
24 | hash
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/app/models/sql_filter_factory.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class SQLFilterFactory
4 | def self.build_sql_filter(filter_attributes)
5 | case filter_attributes['kind']
6 | when 'equal'
7 | build_equal_sql_filter(filter_attributes)
8 | end
9 | end
10 |
11 | def self.build_equal_sql_filter(filter_attributes)
12 | filter = SQLFilter::Equal.new
13 | filter.column = filter_attributes['column']
14 | filter.value = filter_attributes['value']
15 | filter.operator = filter_attributes['operator']
16 | filter
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/app/models/target_table_setting.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class TargetTableSetting < ApplicationRecord
4 | def create_editable_fields(columns)
5 | columns.map do |column|
6 | add_column_to_editable_fields(column)
7 | end
8 | end
9 |
10 | def update_editable_fields(columns)
11 | columns.map do |column|
12 | next if editable_fields[column.name.to_s]
13 |
14 | add_column_to_editable_fields(column)
15 | end
16 |
17 | remove_stale_columns(columns)
18 | save!
19 | end
20 |
21 | def update_primary_keys(table_primary_keys)
22 | self.primary_keys = {}
23 | self.primary_keys = { 'primary_keys' => table_primary_keys }
24 | save!
25 | end
26 |
27 | private
28 |
29 | def add_column_to_editable_fields(column)
30 | self.editable_fields = {} if editable_fields.nil?
31 | editable_fields.merge!(column.name.to_s => { 'editable' => false, 'mandatory' => false })
32 | end
33 |
34 | def remove_stale_columns(columns)
35 | column_names = columns.map(&:name)
36 | editable_fields.delete_if { |key, _value| !column_names.include? key }
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/app/models/task_queue.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class TaskQueue < ApplicationRecord
4 | validates :name, :table, presence: true
5 | has_many :task_queue_outcomes
6 |
7 | scope :enabled, -> { where(enabled: true) }
8 |
9 | def success_outcome_enabled?
10 | success_database_update['enabled'] ? true : false
11 | end
12 |
13 | def failure_outcome_enabled?
14 | failure_database_update['enabled'] ? true : false
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/app/models/task_queue_outcome.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class TaskQueueOutcome < ApplicationRecord
4 | OUTCOMES = %w[
5 | success
6 | failure
7 | ].freeze
8 |
9 | belongs_to :task_queue
10 | validates :outcome, inclusion: { in: OUTCOMES }
11 | validates :outcome,
12 | :task_queue_id,
13 | :task_queue_item_table,
14 | :task_queue_item_primary_key, presence: true
15 | end
16 |
--------------------------------------------------------------------------------
/app/models/view_builder.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class ViewBuilder < ApplicationRecord
4 | validates :table_name, presence: true
5 | validates :table_name, uniqueness: { scope: :database_id }
6 |
7 | def table_headers
8 | table_attributes['visible_fields'].map { |_k, field| field }
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/models/work_list_outcome.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class WorkListOutcome
4 | attr_accessor :title,
5 | :detail
6 |
7 | def initialize(args = {})
8 | self.title = args['title'] || ''
9 | self.detail = args['detail'] || ''
10 | end
11 |
12 | def to_hash
13 | hash = {}
14 | hash['title'] = title
15 | hash['detail'] = detail
16 | hash
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/app/services/verify_license_key_service.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class VerifyLicenseKeyService
4 | class << self
5 | include HTTParty
6 |
7 | STATUS = { sold: '1', delivered: '2', active: '3', inactive: '4' }.freeze
8 |
9 | def verify(license_key)
10 | response = call("/#{license_key}")
11 | return true if response['data']['status'] == STATUS[:active]
12 |
13 | activate(license_key)
14 | end
15 |
16 | def activate(license_key)
17 | response = call("/activate/#{license_key}")
18 | response.code == 200
19 | end
20 |
21 | private
22 |
23 | def call(endpoint); end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/app/views/activities/_activity.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | <%= activity.created_at.strftime('%a, %d %b %Y at %I:%M') %>
4 |
5 |
6 | <%= render_activity(activity) %>
7 | <% if locals[:link] %>
8 | to a <%= link_to "record", table_record_preview_path(table: activity.feedable_type, table_name: activity.feedable_type, record_id: activity.feedable_id, database_id: activity.database_id) %> on <%= link_to activity.feedable_type, table_path(id: activity.database_id, table: activity.feedable_type) %> table
9 | <% end %>
10 |
11 |
--------------------------------------------------------------------------------
/app/views/activities/_form.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= form_with(model: @activity, local: false, data: { 'activity-form' => true }, class: 'activity-comment-form') do |form| %>
3 | <%= form.hidden_field :feedable_type, id: :feedable_type, value: feedable_type %>
4 | <%= form.hidden_field :feedable_id, id: :feedable_id, value: feedable_id %>
5 | <%= form.hidden_field :database_id, value: @database.id %>
6 | <%= form.hidden_field :kind, value: 'note' %>
7 | <%= form.hidden_field :user_id, value: current_admin_user.id %>
8 |
9 |
10 | <%= form.text_field :content, placeholder: 'Click to add a comment', class: "activity-comment-form--input" %>
11 | <%= form.submit 'Submit', class: 'btn btn-info btn-middle-align btn-square' %>
12 | <% end %>
13 |
14 |
--------------------------------------------------------------------------------
/app/views/activities/_task_queue_record_activity_form.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= form_with(model: @activity, local: false, scope: 'activity', html: { id: 'task-queue-record-activity-form' }, url: activities_path) do |form| %>
3 |
4 | <%= form.text_area :content, class: "form-control" %>
5 |
6 |
7 |
8 | <%= form.hidden_field :feedable_type, id: :feedable_type, value: feedable_type %>
9 | <%= form.hidden_field :kind, value: 'note' %>
10 |
11 |
12 |
13 |
14 |
15 | <%= form.submit 'Save', class: 'btn btn-primary', id: 'task-queue-record-activity-submit' %>
16 |
17 |
18 |
19 | <% end %>
20 |
21 |
--------------------------------------------------------------------------------
/app/views/activities/failure.js.erb:
--------------------------------------------------------------------------------
1 | toastr.error('Failed to save activity.');
2 |
--------------------------------------------------------------------------------
/app/views/activities/index.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Activity history
4 |
5 |
6 |
7 | <%= link_to @feedable_type.humanize, table_path(table: @feedable_type, id: @feedable_type.downcase) %>
8 |
9 |
10 |
11 | <%= link_to @feedable_id, table_record_preview_path(table: @feedable_type, table_name: @feedable_type, record_id: @feedable_id, database_id: @database_id) %>
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | <%= render 'shared/activity_history', feedable_type: @feedable_type, feedable_id: @feedable_id, index: true %>
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/views/admin_users/_new_modal.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <%= render partial: 'user_form' %>
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/views/admin_users/_permissions.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/views/admin_users/_roles.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | ID
8 | Name
9 | Actions
10 |
11 |
12 |
13 | <% @roles.each do |role| %>
14 |
15 | <%= role.id %>
16 | <%= role.name %>
17 | action buttons
18 |
19 | <% end %>
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/views/admin_users/_status.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | <% @admin_user_statuses.each do |status, users_count| %>
8 |
9 |
10 | <%= status.capitalize %>
11 |
12 |
13 | <%= pluralize users_count, "user" %>
14 |
15 |
16 | <% end %>
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/views/admin_users/_teams.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | <% @admin_user_roles.sort.each do |role, users_count| %>
9 |
10 |
11 | <%= role %>
12 |
13 |
14 |
15 | <%= pluralize users_count, "user" %>
16 |
17 | Edit
18 |
19 |
20 | <% end %>
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/views/admin_users/_users_table.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= render partial: "shared/table_filter_bar.html.erb", locals: { users: true } %>
3 |
4 |
5 |
Users
6 |
7 |
8 |
9 | <% @headers.each do |header|%>
10 | <%= header.humanize %>
11 | <% end %>
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/views/admin_users/create_new.js.erb:
--------------------------------------------------------------------------------
1 | <% if @result %>
2 | toastr.success('New user has been successfully created.');
3 | $('#users--team-partial').html("<%= j render("teams")%>");
4 | $('#users--status-partial').html("<%= j render("status")%>");
5 | $("#target-table-admin-users").DataTable().ajax.reload();
6 | $('.users--new-modal').removeClass('show');
7 | $('.users--new-modal').addClass('hide');
8 | <% else %>
9 | toastr.error('Unable to save new user. Please check email is not already in use.');
10 | <% end %>
--------------------------------------------------------------------------------
/app/views/admin_users/delete_failure.js.erb:
--------------------------------------------------------------------------------
1 | toastr.error('You cannot delete the last admin user, or yourself. Please make sure there is another admin user set up first.');
--------------------------------------------------------------------------------
/app/views/admin_users/destroy.js.erb:
--------------------------------------------------------------------------------
1 | toastr.success('User has been successfully deleted.');
2 | $('#users--team-partial').html("<%= j render("teams")%>");
3 | $('#users--status-partial').html("<%= j render("status")%>");
4 | $("#target-table-admin-users").DataTable().ajax.reload();
5 | $('.users--edit-modal').removeClass('show');
6 | $('.users--edit-modal').addClass('hide');
--------------------------------------------------------------------------------
/app/views/admin_users/edit.js.erb:
--------------------------------------------------------------------------------
1 | $('.modal--content-container').html("<%= j render('user_form') %>");
2 |
--------------------------------------------------------------------------------
/app/views/admin_users/index.html.erb:
--------------------------------------------------------------------------------
1 | <% content_for :head do %>
2 | <%= javascript_include_tag 'dataTable/datatables.min.js' %>
3 | <% end %>
4 |
5 | <%= render 'shared/page_banner_header', title: 'Settings', items: ['Settings', 'Users'] %>
6 |
7 |
8 |
9 |
10 |
11 |
12 | <%= render partial: 'teams' %>
13 |
14 |
15 | <%= render partial: 'status' %>
16 |
17 |
18 |
19 |
20 |
21 |
22 | <%= render partial: 'users_table' %>
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/views/admin_users/new.js.erb:
--------------------------------------------------------------------------------
1 | $('#users--new-modal').html("<%= j render("new_modal")%>")
2 | $('.users--new-modal').removeClass('hide');
3 | $('.users--new-modal').addClass('show');
--------------------------------------------------------------------------------
/app/views/admin_users/show_modal.js.erb:
--------------------------------------------------------------------------------
1 | $('#users--edit-modal').html("<%= j render("show_modal")%>")
2 | $('.users--edit-modal').removeClass('hide');
3 | $('.users--edit-modal').addClass('show');
--------------------------------------------------------------------------------
/app/views/admin_users/update.js.erb:
--------------------------------------------------------------------------------
1 | <% if @result %>
2 | toastr.success('User has been successfully updated.');
3 | $('#users--team-partial').html("<%= j render("teams")%>");
4 | $('#users--status-partial').html("<%= j render("status")%>");
5 | var table = $("#target-table-admin-users").DataTable()
6 | table.ajax.reload();
7 | filterByTeams(table);
8 | filterByStatus(table);
9 | clearFilters(table);
10 | $('.users--edit-modal').removeClass('show');
11 | $('.users--edit-modal').addClass('hide');
12 | <% else %>
13 | toastr.error('Unable to update user. Please check email is not already in use.');
14 | <% end %>
--------------------------------------------------------------------------------
/app/views/admin_users/update_role.js.erb:
--------------------------------------------------------------------------------
1 | toastr.success('Team has been successfully updated.');
2 | $('#users--team-partial').html("<%= j render("teams")%>");
3 | var table = $("#target-table-admin-users").DataTable()
4 | table.ajax.reload();
5 | filterByTeams(table);
6 | filterByStatus(table);
7 | clearFilters(table);
--------------------------------------------------------------------------------
/app/views/admin_users/update_status.js.erb:
--------------------------------------------------------------------------------
1 | toastr.success('Status has been successfully updated.');
2 | $('#users--status-partial').html("<%= j render("status")%>");
3 | var table = $("#target-table-admin-users").DataTable()
4 | table.ajax.reload();
5 | filterByTeams(table);
6 | filterByStatus(table);
7 | clearFilters(table);
--------------------------------------------------------------------------------
/app/views/dashboard/_license_form.html.erb:
--------------------------------------------------------------------------------
1 | <%= form_tag("/license/verify", method: "post") do %>
2 |
3 | <%= label_tag(:license_key, "License key") %>
4 | <%= text_field_tag(:license_key, '', {class: 'form-control', required: true}) %>
5 |
6 |
7 |
8 | If this was a trial license you will need to buy a license here .
9 |
10 |
11 | <%= submit_tag("Submit", {class: 'btn btn-primary'}) %>
12 | <% end %>
13 |
--------------------------------------------------------------------------------
/app/views/dashboard/license.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
13 |
14 |
Welcome
15 |
16 |
17 |
18 |
Welcome to the installation process. You’ll need a license key to get set-up. You can get a trial or full license key from www.missionkontrol.io
19 |
20 | <%= render 'license_form' %>
21 |
22 |
23 | Server response: License terminated. If this is unexpected please contact team@missionkontrol.io
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/views/dashboard/verify_license.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
13 |
14 |
License invalid
15 |
16 |
17 |
18 |
You’ll need a valid license key to continue. If this is unexpected please contact team@missionkontrol.io
19 |
20 | <%= render 'license_form' %>
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/views/databases/create.js.erb:
--------------------------------------------------------------------------------
1 | <% if @result %>
2 | window.location.assign('/permissions');
3 | toastr.success('Database has been successfully created.')
4 | <% else %>
5 | toastr.error('Unable to save database. Please check your credentials and try again.');
6 | <% end %>
--------------------------------------------------------------------------------
/app/views/databases/edit.html.erb:
--------------------------------------------------------------------------------
1 | <%= render 'shared/page_banner_header', title: 'Settings', items: ['Settings', 'Databases', "#{@database.friendly_name}"] %>
2 |
3 | <%= render 'tabs' %>
--------------------------------------------------------------------------------
/app/views/databases/new.html.erb:
--------------------------------------------------------------------------------
1 | <%= render 'shared/page_banner_header', title: 'Settings', items: ['Settings', 'Databases'] %>
2 |
3 | <%= render 'tabs' %>
--------------------------------------------------------------------------------
/app/views/databases/test_connection.js.erb:
--------------------------------------------------------------------------------
1 | <% if @active_connection %>
2 | toastr.success('Database connection successful.')
3 | <% else %>
4 | toastr.error('Unable to connect to database. Please check your credentials and try again.');
5 | <% end %>
--------------------------------------------------------------------------------
/app/views/databases/test_gem.js.erb:
--------------------------------------------------------------------------------
1 | <% if @active_gem_connection %>
2 | toastr.success('Gem connection successful.')
3 | <% else %>
4 | toastr.error('Unable to connect to your application. Please check your credentials and try again.');
5 | <% end %>
--------------------------------------------------------------------------------
/app/views/databases/update.js.erb:
--------------------------------------------------------------------------------
1 | <% if @result %>
2 | toastr.success("<%= t('successes.has_been_successfully_updated', model: 'Database') %>");
3 | <% else %>
4 | toastr.error("<%= t('errors.unable_to_save', model: 'database') %>");
5 | <% end %>
--------------------------------------------------------------------------------
/app/views/devise/confirmations/new.html.erb:
--------------------------------------------------------------------------------
1 | Resend confirmation instructions
2 |
3 | <%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
4 | <%= devise_error_messages! %>
5 |
6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
9 |
10 |
11 |
12 | <%= f.submit "Resend confirmation instructions" %>
13 |
14 | <% end %>
15 |
16 | <%= render "devise/shared/links" %>
17 |
--------------------------------------------------------------------------------
/app/views/devise/mailer/confirmation_instructions.html.erb:
--------------------------------------------------------------------------------
1 | Welcome <%= @email %>!
2 |
3 | You can confirm your account email through the link below:
4 |
5 | <%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>
6 |
--------------------------------------------------------------------------------
/app/views/devise/mailer/email_changed.html.erb:
--------------------------------------------------------------------------------
1 | Hello <%= @email %>!
2 |
3 | <% if @resource.try(:unconfirmed_email?) %>
4 | We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.
5 | <% else %>
6 | We're contacting you to notify you that your email has been changed to <%= @resource.email %>.
7 | <% end %>
8 |
--------------------------------------------------------------------------------
/app/views/devise/mailer/password_change.html.erb:
--------------------------------------------------------------------------------
1 | Hello <%= @resource.email %>!
2 |
3 | We're contacting you to notify you that your password has been changed.
4 |
--------------------------------------------------------------------------------
/app/views/devise/mailer/reset_password_instructions.html.erb:
--------------------------------------------------------------------------------
1 | Hello <%= @resource.email %>!
2 |
3 | Someone has requested a link to change your password. You can do this through the link below.
4 |
5 | <%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>
6 |
7 | If you didn't request this, please ignore this email.
8 | Your password won't change until you access the link above and create a new one.
9 |
--------------------------------------------------------------------------------
/app/views/devise/mailer/unlock_instructions.html.erb:
--------------------------------------------------------------------------------
1 | Hello <%= @resource.email %>!
2 |
3 | Your account has been locked due to an excessive number of unsuccessful sign in attempts.
4 |
5 | Click the link below to unlock your account:
6 |
7 | <%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>
8 |
--------------------------------------------------------------------------------
/app/views/devise/passwords/edit.html.erb:
--------------------------------------------------------------------------------
1 | Change your password
2 |
3 | <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
4 | <%= devise_error_messages! %>
5 | <%= f.hidden_field :reset_password_token %>
6 |
7 |
8 | <%= f.label :password, "New password" %>
9 | <% if @minimum_password_length %>
10 | (<%= @minimum_password_length %> characters minimum)
11 | <% end %>
12 | <%= f.password_field :password, autofocus: true, autocomplete: "off" %>
13 |
14 |
15 |
16 | <%= f.label :password_confirmation, "Confirm new password" %>
17 | <%= f.password_field :password_confirmation, autocomplete: "off" %>
18 |
19 |
20 |
21 | <%= f.submit "Change my password" %>
22 |
23 | <% end %>
24 |
25 | <%= render "devise/shared/links" %>
26 |
--------------------------------------------------------------------------------
/app/views/devise/passwords/new.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
Forgot your password?
10 |
11 | <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
12 | <%= devise_error_messages! %>
13 |
14 |
15 | <%= f.label :email, "Email" %>
16 | <%= f.email_field :email, autofocus: true, autocomplete: "email", class: 'form-control', required: true %>
17 |
18 |
19 |
20 | <%= f.submit "Send me reset password instructions", class: 'btn btn-primary block full-width m-b' %>
21 |
22 | <% end %>
23 |
24 | <%- if controller_name != 'sessions' %>
25 |
26 | <%= link_to "Log in", new_session_path(resource_name) %>
27 |
28 | <% end -%>
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/views/devise/registrations/_form_content.html.erb:
--------------------------------------------------------------------------------
1 | <%= render 'registration_form_one', f: f %>
--------------------------------------------------------------------------------
/app/views/devise/registrations/edit.js.erb:
--------------------------------------------------------------------------------
1 | $('#users--modal').html("<%= j render("/admin_users/edit_modal")%>")
2 | $('.users--edit-modal').removeClass('hide');
3 | $('.users--edit-modal').addClass('show');
--------------------------------------------------------------------------------
/app/views/devise/registrations/new.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: {class: "m-t"}) do |f| %>
5 | <%= devise_error_messages! %>
6 |
7 | <%= render 'form_content', f: f %>
8 | <% end %>
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/views/devise/unlocks/new.html.erb:
--------------------------------------------------------------------------------
1 | Resend unlock instructions
2 |
3 | <%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %>
4 | <%= devise_error_messages! %>
5 |
6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
9 |
10 |
11 |
12 | <%= f.submit "Resend unlock instructions" %>
13 |
14 | <% end %>
15 |
16 | <%= render "devise/shared/links" %>
17 |
--------------------------------------------------------------------------------
/app/views/errors/internal_server_error.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Oh no! Something seems to have gone wrong!
5 |
6 |
Try reload the page or visit the <%= link_to 'dashboard', dashboard_path %>.
7 |
8 |
If that fails please speak to a system administrator.
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/views/errors/internal_server_error.js.erb:
--------------------------------------------------------------------------------
1 | toastr.error("There appears to be an error with the application. Please reload or speak to an Administrator");
2 |
--------------------------------------------------------------------------------
/app/views/errors/not_acceptable.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Oh no! Something seems to have gone wrong!
5 |
6 |
Try reload the page or visit the <%= link_to 'dashboard', dashboard_path %>.
7 |
8 |
If that fails please speak to a system administrator.
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/views/errors/not_acceptable.js.erb:
--------------------------------------------------------------------------------
1 | toastr.error("There appears to be an error with the application. Please reload or speak to an Administrator");
2 |
--------------------------------------------------------------------------------
/app/views/errors/not_authorized.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Oh no! You're trying to access something you don't have permissions to access!
5 |
6 |
Please speak to a system administrator if you believe this to be wrong.
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/views/errors/not_authorized.js.erb:
--------------------------------------------------------------------------------
1 | toastr.error("You're trying to access something you don't have permissions to access.");
2 |
--------------------------------------------------------------------------------
/app/views/errors/not_found.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Oh no! We seem to have lost connection to your database!
5 |
6 |
This could be due to a few simple things. Let's run through a few simple things to check before you really start panicking...
7 |
8 | Did you just change your database settings? Could you have typed the password wrong?
9 | Has someone changed a firewall surrounding your database so MissionKontrol can no longer see it?
10 | Is your database still connected to the internet?
11 | Is your database even still alive?
12 | ...
13 | Ok maybe you can start panicking now
14 |
15 |
16 | Check your settings or speak to a system administrator.
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/views/errors/not_found.js.erb:
--------------------------------------------------------------------------------
1 | toastr.error("There appears to be an error with your database connection. Please check your credentials or speak to an Administrator");
2 |
--------------------------------------------------------------------------------
/app/views/home/index.html.erb:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/app/views/layout_builder/_field_settings_form_old.html.erb:
--------------------------------------------------------------------------------
1 | <% @action_for_layout_builder = action_name == 'edit' ? 'update' : 'create' %>
2 | <%= form_for @view_builder, :url => url_for(:controller => 'layout_builder', action: @action_for_layout_builder), remote: true, html: {class: 'hide'} do |form| %>
3 |
4 | <%= form.hidden_field :layout_id, value: params[:id] %>
5 |
6 |
7 |
18 |
19 |
20 | <%= form.submit "Save", class: "btn btn-primary" %>
21 |
22 | <% end %>
23 |
--------------------------------------------------------------------------------
/app/views/layout_builder/edit.html.erb:
--------------------------------------------------------------------------------
1 | <% content_for :head do %>
2 | <%= javascript_include_tag 'dragula/dragula.min.js' %>
3 | <%= javascript_include_tag 'shopify/draggable.bundle.js' %>
4 | <%= javascript_include_tag 'sweetAlert/sweetalert.min.js' %>
5 | <% end %>
6 |
7 |
8 | <%= @database.id %>
9 |
10 |
11 |
12 |
13 | <%= render partial: 'layout_builder/edit/layout_builder_editable_warning_modal_screen_1' %>
14 |
15 |
16 |
17 |
18 |
19 |
20 | <%= link_to "Preview", table_record_preview_path(table: @view_builder.table_name, table_name: @view_builder.table_name.downcase, record_id: @row, database_id: @database.id) %>
21 |
22 |
23 |
24 |
25 |
26 | <%= render 'layout_builder/initial_placeholder' %>
27 |
28 |
--------------------------------------------------------------------------------
/app/views/layout_builder/edit/error.js.erb:
--------------------------------------------------------------------------------
1 | toastr.error("Invalid target database, please review credentials.")
2 |
--------------------------------------------------------------------------------
/app/views/layout_builder/edit/success.js.erb:
--------------------------------------------------------------------------------
1 | let layoutId = window.location.pathname.split("/")[2];
2 | window.location.href = window.location.origin + "/layouts/" + layoutId + "/preview"
3 |
--------------------------------------------------------------------------------
/app/views/layout_builder/new.html.erb:
--------------------------------------------------------------------------------
1 | <% content_for :head do %>
2 | <%= javascript_include_tag 'dragula/dragula.min.js' %>
3 | <%= javascript_include_tag 'shopify/draggable.bundle.js' %>
4 | <%= javascript_include_tag 'shopify/sortable.js' %>
5 | <% end %>
6 |
7 |
8 |
9 | <% if current_admin_user.ignore_layout_modal? %>
10 | <%= render partial: 'layout_builder/new/layout_builder_modal_screen_2' %>
11 | <% else %>
12 | <%= render partial: 'layout_builder/new/layout_builder_modal_screen_1' %>
13 | <%= render partial: 'layout_builder/new/layout_builder_modal_screen_2' %>
14 | <% end %>
15 |
16 |
17 |
18 |
19 | <%= render 'layout_builder/initial_placeholder' %>
20 |
21 |
--------------------------------------------------------------------------------
/app/views/layout_builder/select_table_fields.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Next
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/views/layout_builder/update/success.js:
--------------------------------------------------------------------------------
1 | toastr.options = {
2 | closeButton: true,
3 | showMethod: "fadeIn",
4 | hideMethod: "fadeOut",
5 | timeOut: 5000,
6 | preventDuplicates: true,
7 | positionClass: "toast-bottom-right"
8 | };
9 |
10 | toastr.info("Layout successfully updated.");
11 |
--------------------------------------------------------------------------------
/app/views/layouts/_footer.html.erb:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/app/views/layouts/_mouseflow.html.erb:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/app/views/layouts/_natterly.html:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/views/layouts/_topnavbar.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/views/layouts/application.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MissionKontrol
5 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
6 | <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
7 | <%= csrf_meta_tags %>
8 | <%= favicon_link_tag 'favicon.ico' %>
9 | <%= yield(:head) %>
10 |
11 |
12 |
13 |
14 | <%= render 'shared/flash_message' %>
15 | <%= yield %>
16 | <%= insert_paloma_hook %>
17 |
18 |
19 |
20 |
21 | <%= render 'layouts/natterly' %>
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/views/layouts/bad_connection.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Oh no! We seem to have lost connection to your database!
5 |
6 |
This could be due to a few simple things. Let's run through a few simple things to check before you really start panicking...
7 |
8 | Did you just change your database settings? Could you have typed the password wrong?
9 | Has someone changed a firewall surrounding your database so MissionKontrol can no longer see it?
10 | Is your database still connected to the internet?
11 | Is your database even still alive?
12 | ...
13 | Ok maybe you can start panicking now
14 |
15 |
16 | <%= link_to 'Check your settings here', edit_organisation_setting_path(current_organisation), html_options = { class: "underline" } %> and then refresh the page
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/views/layouts/license.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MissionKontrol
5 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
6 | <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
7 | <%= csrf_meta_tags %>
8 | <%= favicon_link_tag 'favicon.ico' %>
9 |
10 |
11 |
12 |
13 | <%= yield %>
14 |
15 |
16 |
17 |
18 | <%= render 'layouts/natterly' %>
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/views/organisation_settings/update.js.erb:
--------------------------------------------------------------------------------
1 | <% if @invalid_key %>
2 | toastr.error("<%= t('errors.unable_to_activate_license_key') %>")
3 | <% elsif @result %>
4 | toastr.success("<%= t('successes.have_been_successfully_updated', model: 'Settings') %>");
5 | <% else %>
6 | toastr.error("<%= t('errors.unable_to_save', model: 'settings') %>");
7 | <% end %>
--------------------------------------------------------------------------------
/app/views/permissions/add_to_role.js.erb:
--------------------------------------------------------------------------------
1 | toastr.success('Settings have been successfully updated.');
2 |
3 | // $('.data-table-permissions').DataTable().ajax.reload();
--------------------------------------------------------------------------------
/app/views/permissions/disable_all.js.erb:
--------------------------------------------------------------------------------
1 | window["datatable"+<%= @database_id %>].ajax.reload();
2 | toastr.success('Settings have been successfully updated.');
--------------------------------------------------------------------------------
/app/views/permissions/enable_all.js.erb:
--------------------------------------------------------------------------------
1 | window["datatable"+<%= @database_id %>].ajax.reload();
2 | toastr.success('Settings have been successfully updated.');
--------------------------------------------------------------------------------
/app/views/permissions/index.html.erb:
--------------------------------------------------------------------------------
1 | <% content_for :head do %>
2 | <%= javascript_include_tag 'dataTable/datatables.min.js' %>
3 | <% end %>
4 |
5 | <%= render 'shared/page_banner_header', title: 'Settings', items: ['Settings', 'Permissions'] %>
6 |
7 |
8 |
9 |
10 | <% @databases.each do |database| %>
11 |
<%= database.friendly_name %>
12 |
13 |
14 |
15 |
16 | <% @headers.each do |header|%>
17 | <%= header.humanize %>
18 | <% end %>
19 |
20 |
21 |
22 |
23 | <% end %>
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/views/permissions/remove_from_role.js.erb:
--------------------------------------------------------------------------------
1 | toastr.success('Settings have been successfully updated.');
2 |
3 | // $('.data-table-permissions').DataTable().ajax.reload();
--------------------------------------------------------------------------------
/app/views/roles/edit.js.erb:
--------------------------------------------------------------------------------
1 | $('#roles--edit-modal').html("<%= j render("edit_modal")%>")
2 | $('.roles--edit-modal').removeClass('hide');
3 | $('.roles--edit-modal').addClass('show');
4 |
--------------------------------------------------------------------------------
/app/views/roles/update.js.erb:
--------------------------------------------------------------------------------
1 | toastr.success('Role settings have been successfully updated.');
2 |
--------------------------------------------------------------------------------
/app/views/roles/update_error.js.erb:
--------------------------------------------------------------------------------
1 | toastr.error('Cannot remove administrator permissions from all Teams. Please add administrator permissions to another team before removing here.');
2 | $('#roles--edit-modal').html("<%= j render("show_modal")%>");
3 | $('.roles--edit-modal').removeClass('hide');
4 | $('.roles--edit-modal').addClass('show');
--------------------------------------------------------------------------------
/app/views/shared/_activity_stream.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | <% activities.each do |activity| %>
4 | <%= render 'activities/activity', activity: activity, locals: { link: locals[:link] } %>
5 | <% end %>
6 |
7 |
--------------------------------------------------------------------------------
/app/views/shared/_flash_message.html.erb:
--------------------------------------------------------------------------------
1 | <% flash.each do |key, value| %>
2 |
3 |
4 |
×
5 |
6 |
7 | <%= value %>
8 |
9 |
10 |
11 | <% end %>
12 |
--------------------------------------------------------------------------------
/app/views/shared/_page_banner_header.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
<%= title %>
4 |
5 |
6 | <% items.each do |item| %>
7 |
8 | <%= item %>
9 |
10 | <% end %>
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/views/tables/_record_summary.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | <% @row.first(5).each do |k, v| %>
6 |
7 | <%= k %>: <%= v %>
8 |
9 | <% end %>
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/views/tables/_related_data_table.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
<%= current_table.humanize %>
4 |
5 | <% table_settings = TargetTableSetting.where(name: current_table, database_id: @database.id).first %>
6 |
7 |
8 |
9 | <% headers.each do |header|%>
10 | <%= header.humanize %>
11 | <% end %>
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/views/tables/_related_table_with_layout.html.erb:
--------------------------------------------------------------------------------
1 | <% r.each_with_index do |(k, v), i| %>
2 | <% @column_is_hidden = hidden_columns.include?(k) %>
3 |
4 | <% if @column_is_hidden %>
5 |
6 | <%= render 'table_cell_data', v: v %>
7 |
8 | <% else %>
9 |
10 | <%= render 'table_cell_data', v: v %>
11 |
12 | <% end %>
13 | <% end %>
14 |
--------------------------------------------------------------------------------
/app/views/tables/_table_cell_data.html.erb:
--------------------------------------------------------------------------------
1 | <% if v %>
2 | <%= v %>
3 | <% else %>
4 | --
5 | <% end %>
6 |
--------------------------------------------------------------------------------
/app/views/tables/_table_with_layout.html.erb:
--------------------------------------------------------------------------------
1 | <% r.each_with_index do |(k, v), i| %>
2 | <% @column_is_hidden = @hidden_columns.include?(k) %>
3 |
4 | <% if @column_is_hidden %>
5 |
6 | <%= render 'table_cell_data', v: v %>
7 |
8 | <% else %>
9 |
10 | <%= render 'table_cell_data', v: v %>
11 |
12 | <% end %>
13 | <% end %>
14 |
--------------------------------------------------------------------------------
/app/views/tables/_table_without_layout.html.erb:
--------------------------------------------------------------------------------
1 | <% r.first(5).each_with_index do |(k, v), i| %>
2 |
3 | <%= render 'table_cell_data', v: v %>
4 |
5 | <% end %>
6 |
--------------------------------------------------------------------------------
/app/views/tables/add_record.js.erb:
--------------------------------------------------------------------------------
1 | $('#table--add-record-modal').html("<%= j render("add_record_modal")%>")
2 | $('.table--add-record-modal').removeClass('hide');
3 | $('.table--add-record-modal').addClass('show');
--------------------------------------------------------------------------------
/app/views/tables/create_record.js.erb:
--------------------------------------------------------------------------------
1 | <% if @error %>
2 | toastr.error("<%= @error_message %>")
3 | <% else %>
4 | toastr.success('Record has been successfully created.');
5 | $(".data-table").DataTable().ajax.reload();
6 | $('.table--add-record-modal').removeClass('show');
7 | $('.table--add-record-modal').addClass('hide');
8 | <% end %>
9 |
--------------------------------------------------------------------------------
/app/views/tables/delete_record.js.erb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/app/views/tables/delete_record.js.erb
--------------------------------------------------------------------------------
/app/views/tables/edit_record.js.erb:
--------------------------------------------------------------------------------
1 | <% if @error %>
2 | toastr.error("<%= @error_message %>")
3 | <% else %>
4 | $('#table--edit-record-modal').html("<%= j render("edit_record_modal")%>")
5 | $('.table--edit-record-modal').removeClass('hide');
6 | $('.table--edit-record-modal').addClass('show');
7 | <% end %>
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/views/tables/layout/_editable_actions.html.erb:
--------------------------------------------------------------------------------
1 |
6 |
7 |
22 |
--------------------------------------------------------------------------------
/app/views/tables/layout/_main_container1.html.erb:
--------------------------------------------------------------------------------
1 | <% fields_for_main_container1(layout_builder).each do |index, field| %>
2 | <%= render partial: 'tables/layout/container_content', locals: { field: field } %>
3 | <% end %>
4 |
--------------------------------------------------------------------------------
/app/views/tables/layout/_main_container2.html.erb:
--------------------------------------------------------------------------------
1 | <% fields_for_main_container2(layout_builder).each do |index, field| %>
2 | <%= render partial: 'tables/layout/container_content', locals: { field: field } %>
3 | <% end %>
4 |
--------------------------------------------------------------------------------
/app/views/tables/layout/_main_container3.html.erb:
--------------------------------------------------------------------------------
1 | <% fields_for_main_container3(layout_builder).each do |index, field| %>
2 | <%= render partial: 'tables/layout/container_content', locals: { field: field } %>
3 | <% end %>
4 |
--------------------------------------------------------------------------------
/app/views/tables/settings.js.erb:
--------------------------------------------------------------------------------
1 | $('#table--settings-modal').html("<%= j render("settings_modal")%>")
2 | $('.table--settings-modal').removeClass('hide');
3 | $('.table--settings-modal').addClass('show');
--------------------------------------------------------------------------------
/app/views/tables/show.html.erb:
--------------------------------------------------------------------------------
1 | <% content_for :head do %>
2 | <%= javascript_include_tag 'dataTable/datatables.min.js' %>
3 | <% end %>
4 |
5 | <%= render 'shared/page_banner_header', title: @current_table.capitalize, items: ['Database', @current_table.capitalize] %>
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | <%= render 'data_table', current_table: @current_table, table_settings: @current_table_settings %>
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/views/tables/show/failure.js.erb:
--------------------------------------------------------------------------------
1 | toastr.error('Failed to update column settings.');
2 |
--------------------------------------------------------------------------------
/app/views/tables/show/success.js.erb:
--------------------------------------------------------------------------------
1 | toastr.success('Column settings updated.');
2 |
--------------------------------------------------------------------------------
/app/views/tables/update_record.js.erb:
--------------------------------------------------------------------------------
1 | <% if @error %>
2 | toastr.error("<%= @error_message || 'Unable to save the record. Please check all your fields.' %>")
3 | <% else %>
4 | toastr.success('Record(s) has been successfully updated.');
5 | $(".data-table").DataTable().ajax.reload();
6 | $(".table--filter-bar").last().remove();
7 | $('.table--edit-record-modal').removeClass('show');
8 | $('.table--edit-record-modal').addClass('hide');
9 | <% end %>
10 |
--------------------------------------------------------------------------------
/app/views/tables/update_settings.js.erb:
--------------------------------------------------------------------------------
1 | <% if @result %>
2 | toastr.success('Table settings have been successfully updated.');
3 | <% if @table_settings.nested_table.nil? %>
4 | $(".data-table").data("nested-table", "");
5 | $(".data-table").data("nested-table-columns", "");
6 | window.location.reload();
7 | <% elsif @table_settings.nested_table.present? %>
8 | $(".data-table").data("nested-table", "<%= @table_settings.nested_table %>");
9 | $(".data-table").data("nested-table-columns", "<%= @nested_column_names %>");
10 | window.location.reload();
11 | <% end %>
12 | window['datatable'].draw();
13 | <% else %>
14 | toastr.error('Unable to update table settings.');
15 | <% end %>
--------------------------------------------------------------------------------
/app/views/task_queues/_preview.html.erb:
--------------------------------------------------------------------------------
1 |
2 | Results
3 |
4 |
5 |
6 |
7 | <% if @task_queue_headers %>
8 |
9 | <% @task_queue_headers.each do |header|%>
10 | <%= header.humanize %>
11 | <% end %>
12 |
13 | <% end %>
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/views/task_queues/_preview_show.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <% task_queue_draggable_field_settings_container(@task_queue).each do |field| %>
9 |
<%= field[1]["title"] %>
10 |
11 | <% end %>
12 |
13 |
14 |
15 |
16 |
17 |
18 | <%= render 'shared/activity_history_template', feedable_type: 'task_queue', feedable_id: @task_queue.id %>
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/views/task_queues/_task_queue_builder.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= @database.id %>
3 |
4 |
5 |
6 |
7 |
8 |
9 |
Update Query
10 |
11 |
--------------------------------------------------------------------------------
/app/views/task_queues/index_old.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
Query Builder Rules
7 |
8 |
9 |
Show rules
10 |
Save
11 |
12 |
13 |
14 |
15 |
16 |
17 | <%= render partial: 'task_queues/new/new_queue_modal_screen_1' %>
18 | <%= render partial: 'task_queues/new/new_queue_modal_screen_2' %>
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/views/task_queues/new.html.erb:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 | <%# <%= render partial: 'task_queues/new/new_queue_modal_screen_1' %>
9 | <%= render partial: 'task_queues/new/new_queue_modal_screen_2' %>
10 |
11 |
--------------------------------------------------------------------------------
/app/views/task_queues/new/_new_queue_modal_screen_1.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 | Queues are an extremely efficient way to get your team to carry our structured tasks. We have found that they can make teams x2 to x3 more efficient.
10 |
11 |
12 |
13 | This could include calling users who are good candidates for an upgrade or managing a step of your onboarding process or calling leads for welcome calls.
14 |
15 |
16 |
17 | VIDEO
18 |
19 |
20 |
21 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/views/task_queues/shared/_task_queue_navigation.html.erb:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/bin/bundle:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
4 | load Gem.bin_path('bundler', 'bundle')
5 |
--------------------------------------------------------------------------------
/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | APP_PATH = File.expand_path('../config/application', __dir__)
3 | require_relative "../config/boot"
4 | require "rails/commands"
5 |
--------------------------------------------------------------------------------
/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require_relative "../config/boot"
3 | require "rake"
4 | Rake.application.run
5 |
--------------------------------------------------------------------------------
/bin/rspec:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'bundler/setup'
3 | load Gem.bin_path('rspec-core', 'rspec')
4 |
--------------------------------------------------------------------------------
/bin/update:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | require 'pathname'
4 | require 'fileutils'
5 | include FileUtils
6 |
7 | # path to your application root.
8 | APP_ROOT = Pathname.new File.expand_path('..', __dir__)
9 |
10 | def system!(*args)
11 | system(*args) || abort("\n== Command #{args} failed ==")
12 | end
13 |
14 | chdir APP_ROOT do
15 | # This script is a way to update your development environment automatically.
16 | # Add necessary update steps to this file.
17 |
18 | puts '== Installing dependencies =='
19 | system! 'gem install bundler --conservative'
20 | system('bundle check') || system!('bundle install')
21 |
22 | puts "\n== Updating database =="
23 | system! 'bin/rails db:migrate'
24 |
25 | puts "\n== Removing old logs and tempfiles =="
26 | system! 'bin/rails log:clear tmp:clear'
27 |
28 | puts "\n== Restarting application server =="
29 | system! 'bin/rails restart'
30 | end
31 |
--------------------------------------------------------------------------------
/bin/yarn:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | APP_ROOT = File.expand_path('..', __dir__)
3 | Dir.chdir(APP_ROOT) do
4 | exec "yarn", *ARGV
5 | rescue Errno::ENOENT
6 | $stderr.puts "Yarn executable was not detected in the system."
7 | $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
8 | exit 1
9 | end
10 |
--------------------------------------------------------------------------------
/clock.rb:
--------------------------------------------------------------------------------
1 | require 'clockwork'
2 | include Clockwork
3 |
4 | handler do |job|
5 | puts "Running #{job}"
6 | end
7 |
8 | # every(3600, 'bundle exec rake dummy_client_database:reset')
9 |
--------------------------------------------------------------------------------
/config.ru:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # This file is used by Rack-based servers to start the application.
4 |
5 | require ::File.expand_path('../config/environment', __FILE__)
6 | run Rails.application
7 |
--------------------------------------------------------------------------------
/config/application.rb:
--------------------------------------------------------------------------------
1 | require_relative "boot"
2 |
3 | require "rails/all"
4 |
5 | # Require the gems listed in Gemfile, including any gems
6 | # you've limited to :test, :development, or :production.
7 | Bundler.require(*Rails.groups)
8 |
9 | module Kuwinda
10 | class Application < Rails::Application
11 | # Initialize configuration defaults for originally generated Rails version.
12 | config.load_defaults 5.1
13 |
14 | config.autoloader = :classic
15 | # Settings in config/environments/* take precedence over those specified here.
16 | # Application configuration can go into files in config/initializers
17 | # -- all .rb files in that directory are automatically loaded after loading
18 | # the framework and any gems in your application.
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/config/boot.rb:
--------------------------------------------------------------------------------
1 | begin
2 | load File.expand_path("../bin/spring", __dir__)
3 | rescue LoadError => e
4 | raise unless e.path.end_with?("/bin/spring")
5 | end
6 |
7 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
8 |
9 | require "bundler/setup" # Set up gems listed in the Gemfile.
10 |
--------------------------------------------------------------------------------
/config/cable.yml:
--------------------------------------------------------------------------------
1 | development:
2 | adapter: async
3 |
4 | test:
5 | adapter: test
6 |
7 | production:
8 | adapter: redis
9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
10 | channel_prefix: kuwinda_production
11 |
--------------------------------------------------------------------------------
/config/client_database.yml:
--------------------------------------------------------------------------------
1 | default: &default
2 | adapter: postgresql
3 | encoding: unicode
4 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
5 | host: <%= ENV['CLIENT_DATABASE_HOST'] %>
6 | username: <%= ENV['CLIENT_DATABASE_USER'] %>
7 | password: <%= ENV['CLIENT_DATABASE_PASSWORD'] %>
8 | reaping_frequency: 0
9 |
10 | development:
11 | <<: *default
12 | database: <%= ENV['CLIENT_DATABASE_URL'] %>
13 |
14 | test:
15 | <<: *default
16 | database: <%= ENV['CLIENT_DATABASE_DEVELOPMENT'] %>
17 |
18 | staging:
19 | <<: *default
20 | database: <%= ENV['CLIENT_DATABASE_URL'] %>
21 |
22 | production:
23 | <<: *default
24 | database: <%= ENV['CLIENT_DATABASE_URL'] %>
25 |
--------------------------------------------------------------------------------
/config/database.yml:
--------------------------------------------------------------------------------
1 | default: &default
2 | adapter: postgresql
3 | encoding: unicode
4 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
5 | host: <%= ENV['KUWINDA_DATABASE_HOST'] %>
6 | username: <%= ENV['KUWINDA_DATABASE_USER'] %>
7 | password: <%= ENV['KUWINDA_DATABASE_PASSWORD'] %>
8 | port: <%= ENV['KUWINDA_DATABASE_PORT'] { 5432 } %>
9 | reaping_frequency: 0
10 |
11 | development:
12 | <<: *default
13 | database: kuwinda_development
14 |
15 | test:
16 | <<: *default
17 | database: kuwinda_test
18 |
19 | staging:
20 | <<: *default
21 | database: kuwinda_staging
22 |
23 | production:
24 | <<: *default
25 | database: kuwinda_production
26 |
--------------------------------------------------------------------------------
/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the Rails application.
2 | require_relative "application"
3 |
4 | # Initialize the Rails application.
5 | Rails.application.initialize!
6 |
--------------------------------------------------------------------------------
/config/initializers/application_controller_renderer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # ActiveSupport::Reloader.to_prepare do
4 | # ApplicationController.renderer.defaults.merge!(
5 | # http_host: 'example.org',
6 | # https: false
7 | # )
8 | # end
9 |
--------------------------------------------------------------------------------
/config/initializers/assets.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Version of your assets, change this if you want to expire all your assets.
4 | Rails.application.config.assets.version = '1.0'
5 |
6 | # Add additional assets to the asset load path.
7 | # Rails.application.config.assets.paths << Emoji.images_path
8 | # Add Yarn node_modules folder to the asset load path.
9 | Rails.application.config.assets.paths << Rails.root.join('node_modules')
10 |
11 | # Precompile additional assets.
12 | # application.js, application.css, and all non-JS/CSS in the app/assets
13 | # folder are already added.
14 | # Rails.application.config.assets.precompile += %w( admin.js admin.css )
15 |
16 | Rails.application.config.assets.precompile += %w[
17 | dataTable/datatables.min.js
18 | dragula/dragula.min.js
19 | shopify/draggable.bundle.js
20 | shopify/sortable.js
21 | sweetAlert/sweetalert.min.js
22 | moment/moment.min.js
23 | query-builder/query-builder.min.js
24 | ]
25 |
--------------------------------------------------------------------------------
/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code
7 | # by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'".
8 | Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"]
9 |
--------------------------------------------------------------------------------
/config/initializers/cookies_serializer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Specify a serializer for the signed and encrypted cookie jars.
4 | # Valid options are :json, :marshal, and :hybrid.
5 | Rails.application.config.action_dispatch.cookies_serializer = :json
6 |
--------------------------------------------------------------------------------
/config/initializers/feature_policy.rb:
--------------------------------------------------------------------------------
1 | # Define an application-wide HTTP feature policy. For further
2 | # information see https://developers.google.com/web/updates/2018/06/feature-policy
3 | #
4 | # Rails.application.config.feature_policy do |f|
5 | # f.camera :none
6 | # f.gyroscope :none
7 | # f.microphone :none
8 | # f.usb :none
9 | # f.fullscreen :self
10 | # f.payment :self, "https://secure.example.com"
11 | # end
12 |
--------------------------------------------------------------------------------
/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Configure sensitive parameters which will be filtered from the log file.
4 | Rails.application.config.filter_parameters += [
5 | :password, :secret, :token, :_key, :auth, :crypt, :salt, :certificate, :otp, :access, :private, :protected, :ssn
6 | ]
7 |
--------------------------------------------------------------------------------
/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format. Inflections
4 | # are locale specific, and you may define rules for as many different
5 | # locales as you wish. All of these examples are active by default:
6 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
7 | # inflect.plural /^(ox)$/i, '\1en'
8 | # inflect.singular /^(ox)en/i, '\1'
9 | # inflect.irregular 'person', 'people'
10 | # inflect.uncountable %w( fish sheep )
11 | # end
12 |
13 | # These inflection rules are supported but not enabled by default:
14 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
15 | # inflect.acronym 'RESTful'
16 | # end
17 |
--------------------------------------------------------------------------------
/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 |
--------------------------------------------------------------------------------
/config/initializers/models.rb:
--------------------------------------------------------------------------------
1 | if Rails.env == "development"
2 | require_dependency "task_queue"
3 | # Dir.foreach("#{Rails.root}/app/models") do |model_name|
4 | # require_dependency model_name
5 | # end
6 | end
--------------------------------------------------------------------------------
/config/initializers/new_framework_defaults_5_1.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # Be sure to restart your server when you modify this file.
4 | #
5 | # This file contains migration options to ease your Rails 5.1 upgrade.
6 | #
7 | # Once upgraded flip defaults one by one to migrate to the new default.
8 | #
9 | # Read the Guide for Upgrading Ruby on Rails for more info on each option.
10 |
11 | # Make `form_with` generate non-remote forms.
12 | Rails.application.config.action_view.form_with_generates_remote_forms = false
13 |
14 | # Unknown asset fallback will return the path passed in when the given
15 | # asset is not present in the asset pipeline.
16 | # Rails.application.config.assets.unknown_asset_fallback = false
17 |
--------------------------------------------------------------------------------
/config/initializers/rolify.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | Rolify.configure do |config|
4 | # By default ORM adapter is ActiveRecord. uncomment to use mongoid
5 | # config.use_mongoid
6 |
7 | # Dynamic shortcuts for User class (user.is_admin? like methods). Default is: false
8 | # config.use_dynamic_shortcuts
9 |
10 | # Configuration to remove roles from database once the last resource is removed. Default is: true
11 | # config.remove_role_if_empty = false
12 | end
13 |
--------------------------------------------------------------------------------
/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # Be sure to restart your server when you modify this file.
4 |
5 | Rails.application.config.session_store :cookie_store, key: '_kuwinda_session'
6 |
--------------------------------------------------------------------------------
/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json]
9 | end
10 |
11 | # To enable root element in JSON for ActiveRecord objects.
12 | # ActiveSupport.on_load(:active_record) do
13 | # self.include_root_in_json = true
14 | # end
15 |
--------------------------------------------------------------------------------
/config/spring.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # %w[
4 | # .ruby-version
5 | # .rbenv-vars
6 | # tmp/restart.txt
7 | # tmp/caching-dev.txt
8 | # ].each { |path| Spring.watch(path) }
9 | Spring.watch(
10 | ".ruby-version",
11 | ".rbenv-vars",
12 | "tmp/restart.txt",
13 | "tmp/caching-dev.txt"
14 | )
--------------------------------------------------------------------------------
/db/migrate/20180703105143_rename_users_table.rb:
--------------------------------------------------------------------------------
1 | class RenameUsersTable < ActiveRecord::Migration[5.1]
2 | def change
3 | rename_table :users, :admin_users
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20181012143652_create_activities.rb:
--------------------------------------------------------------------------------
1 | class CreateActivities < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :activities do |t|
4 | t.integer :user_id, null: false
5 | t.string :kind, null: false
6 | t.text :content
7 | t.timestamps null: false
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20181018150144_remove_user_id_from_activities.rb:
--------------------------------------------------------------------------------
1 | class RemoveUserIdFromActivities < ActiveRecord::Migration[5.1]
2 | def change
3 | remove_column :activities, :user_id
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20181018154253_add_polymorphic_assiociation_to_activities.rb:
--------------------------------------------------------------------------------
1 | class AddPolymorphicAssiociationToActivities < ActiveRecord::Migration[5.1]
2 | def self.up
3 | add_column :activities, :feedable_type, :string
4 | add_column :activities, :feedable_id, :integer
5 | add_index :activities, [:feedable_type, :feedable_id]
6 | change_column_null :activities, :feedable_type, false
7 | change_column_null :activities, :feedable_id, false
8 | end
9 |
10 | def self.down
11 | remove_column :activities, :feedable_type, :string
12 | remove_column :activities, :feedable_id, :integer
13 | remove_index :activities, [:feedable_type, :feedable_id]
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/db/migrate/20181104112129_create_table_view_builder.rb:
--------------------------------------------------------------------------------
1 | class CreateTableViewBuilder < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :view_builders do |t|
4 | t.string :table_name, null: false
5 | t.jsonb :table_attributes, null: false, default: '{}'
6 | end
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/db/migrate/20181105125119_create_work_lists.rb:
--------------------------------------------------------------------------------
1 | class CreateWorkLists < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :work_lists do |t|
4 | t.string :name, null: false
5 | t.text :details
6 | t.jsonb :sql_query, null: false, default: []
7 | t.timestamps null: false
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20181108114556_add_sql_filters_to_work_lists.rb:
--------------------------------------------------------------------------------
1 | class AddSqlFiltersToWorkLists < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :work_lists, :sql_filters, :jsonb, default: []
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20181108143841_change_work_lists_sql_query_to_string.rb:
--------------------------------------------------------------------------------
1 | class ChangeWorkListsSqlQueryToString < ActiveRecord::Migration[5.1]
2 | def change
3 | remove_column :work_lists, :sql_query
4 | add_column :work_lists, :sql_query, :string
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20181108144047_add_outcomes_to_work_lists.rb:
--------------------------------------------------------------------------------
1 | class AddOutcomesToWorkLists < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :work_lists, :outcomes, :jsonb, default: []
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20181116183747_add_data_table_name_to_work_lists.rb:
--------------------------------------------------------------------------------
1 | class AddDataTableNameToWorkLists < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :work_lists, :data_table_name, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20181122170852_add_visible_columns_to_work_list.rb:
--------------------------------------------------------------------------------
1 | class AddVisibleColumnsToWorkList < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :work_lists, :visible_columns, :jsonb, default: []
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20181123181141_add_view_name_to_view_builder.rb:
--------------------------------------------------------------------------------
1 | class AddViewNameToViewBuilder < ActiveRecord::Migration[5.1]
2 | def self.up
3 | add_column :view_builders, :view_name, :string, required: true
4 | add_column :view_builders, :status, :string, required: true, default: 'pending'
5 | end
6 |
7 | def self.down
8 | remove_column :view_builders, :view_name
9 | remove_column :view_builders, :status
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20181217165628_add_name_and_company_to_admin_users.rb:
--------------------------------------------------------------------------------
1 | class AddNameAndCompanyToAdminUsers < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :admin_users, :first_name, :string
4 | add_column :admin_users, :last_name, :string
5 | add_column :admin_users, :company_name, :string
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/db/migrate/20181224073927_create_layout_settings_table.rb:
--------------------------------------------------------------------------------
1 | class CreateLayoutSettingsTable < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :layout_settings do |t|
4 | t.integer :layout_id, null: false
5 | t.string :primary_table
6 | t.boolean :show_status, default: false, null: false
7 | t.boolean :commentable, default: false, null: false
8 | t.string :parent_comments_table
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20181224123606_add_visible_columns_to_layout_settings.rb:
--------------------------------------------------------------------------------
1 | class AddVisibleColumnsToLayoutSettings < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :layout_settings, :visible_columns, :jsonb, default: []
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190107134016_add_show_status_to_view_builders.rb:
--------------------------------------------------------------------------------
1 | class AddShowStatusToViewBuilders < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :view_builders, :show_status, :boolean, default: false, null: false
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190107134621_add_commentable_to_view_builders.rb:
--------------------------------------------------------------------------------
1 | class AddCommentableToViewBuilders < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :view_builders, :commentable, :boolean, default: false, null: false
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190107134849_add_parent_comment_table_to_view_builders.rb:
--------------------------------------------------------------------------------
1 | class AddParentCommentTableToViewBuilders < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :view_builders, :parent_comment_table, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190107135321_add_draggable_sections_to_view_builders.rb:
--------------------------------------------------------------------------------
1 | class AddDraggableSectionsToViewBuilders < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :view_builders, :draggable_fields_header_container, :jsonb, default: []
4 | add_column :view_builders, :draggable_fields_side_container, :jsonb, default: []
5 | add_column :view_builders, :draggable_fields_main_container, :jsonb, default: []
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/db/migrate/20190115204330_rename_draggable_containers_on_view_builders.rb:
--------------------------------------------------------------------------------
1 | class RenameDraggableContainersOnViewBuilders < ActiveRecord::Migration[5.1]
2 | def change
3 | remove_column :view_builders, :draggable_fields_header_container
4 | remove_column :view_builders, :draggable_fields_main_container
5 | add_column :view_builders, :draggable_fields_header_container1, :jsonb, default: []
6 | add_column :view_builders, :draggable_fields_header_container2, :jsonb, default: []
7 | add_column :view_builders, :draggable_fields_main_container1, :jsonb, default: []
8 | add_column :view_builders, :draggable_fields_main_container2, :jsonb, default: []
9 | add_column :view_builders, :draggable_fields_main_container3, :jsonb, default: []
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20190303142750_add_hidden_columns_to_view_builder.rb:
--------------------------------------------------------------------------------
1 | class AddHiddenColumnsToViewBuilder < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :view_builders, :hidden_columns, :jsonb, default: []
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190303142916_drop_layout_settings.rb:
--------------------------------------------------------------------------------
1 | class DropLayoutSettings < ActiveRecord::Migration[5.1]
2 | def change
3 | drop_table :layout_settings
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190402151253_add_callable_fields_to_layout_builder.rb:
--------------------------------------------------------------------------------
1 | class AddCallableFieldsToLayoutBuilder < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :view_builders, :callable_fields, :jsonb, default: []
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190424163632_create_task_queues.rb:
--------------------------------------------------------------------------------
1 | class CreateTaskQueues < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :task_queues do |t|
4 | t.string :name, null: false
5 | t.text :details
6 | t.string :table
7 | t.timestamps null: false
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20190425152656_add_query_builder_rules_to_task_queues.rb:
--------------------------------------------------------------------------------
1 | class AddQueryBuilderRulesToTaskQueues < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :task_queues, :query_builder_rules, :jsonb, default: []
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190429161124_add_raw_sql_to_task_queues.rb:
--------------------------------------------------------------------------------
1 | class AddRawSqlToTaskQueues < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :task_queues, :raw_sql, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190513161432_add_query_builder_sql_to_task_queues.rb:
--------------------------------------------------------------------------------
1 | class AddQueryBuilderSqlToTaskQueues < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :task_queues, :query_builder_sql, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190516152746_add_draggable_fields_to_task_queues.rb:
--------------------------------------------------------------------------------
1 | class AddDraggableFieldsToTaskQueues < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :task_queues, :draggable_fields, :jsonb, default: []
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190518152319_add_license_key_to_admin_users.rb:
--------------------------------------------------------------------------------
1 | class AddLicenseKeyToAdminUsers < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :admin_users, :license_key, :string
4 | add_column :admin_users, :activation_id, :string
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20190528153818_add_outcome_settings_to_task_queues.rb:
--------------------------------------------------------------------------------
1 | class AddOutcomeSettingsToTaskQueues < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :task_queues, :success_outcome_title, :string
4 | add_column :task_queues, :success_outcome_timeout, :string
5 | add_column :task_queues, :failure_outcome_title, :string
6 | add_column :task_queues, :failure_outcome_timeout, :string
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/db/migrate/20190531093327_add_full_license_to_admin_users.rb:
--------------------------------------------------------------------------------
1 | class AddFullLicenseToAdminUsers < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :admin_users, :full_license, :boolean, default: false
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190605161402_create_task_queue_outcomes.rb:
--------------------------------------------------------------------------------
1 | class CreateTaskQueueOutcomes < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :task_queue_outcomes do |t|
4 | t.integer :task_queue_id, null: false
5 | t.string :task_queue_item_table, null: false
6 | t.string :task_queue_item_primary_key, null: false
7 | t.datetime :task_queue_item_reappear_at, null: false
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20190605161954_add_outcome_to_task_queue_outcomes.rb:
--------------------------------------------------------------------------------
1 | class AddOutcomeToTaskQueueOutcomes < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :task_queue_outcomes, :outcome, :string, null: false
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190605164115_add_unique_constraint_to_task_queue_outcomes.rb:
--------------------------------------------------------------------------------
1 | class AddUniqueConstraintToTaskQueueOutcomes < ActiveRecord::Migration[5.1]
2 | def change
3 | add_index :task_queue_outcomes, [:task_queue_id, :task_queue_item_primary_key], unique: true, name: 'task_queue_item_unique'
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190620170803_add_related_tables_to_view_builder.rb:
--------------------------------------------------------------------------------
1 | class AddRelatedTablesToViewBuilder < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :view_builders, :related_tables, :jsonb, default: []
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190627172016_create_data_table_states.rb:
--------------------------------------------------------------------------------
1 | class CreateDataTableStates < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :data_table_states do |t|
4 | t.string :table, null: false
5 | t.jsonb :state
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20190807161323_add_ignore_layout_modal_to_admin_user.rb:
--------------------------------------------------------------------------------
1 | class AddIgnoreLayoutModalToAdminUser < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :admin_users, :ignore_layout_modal, :boolean, default: false
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190817190347_create_permissions.rb:
--------------------------------------------------------------------------------
1 | class CreatePermissions < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :permissions do |t|
4 | t.integer :admin_user_id
5 | t.string :name
6 | t.string :subject_class
7 | t.integer :subject_id
8 | t.string :action
9 | t.text :description
10 |
11 | t.timestamps
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/db/migrate/20190901110701_rolify_create_roles.rb:
--------------------------------------------------------------------------------
1 | class RolifyCreateRoles < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table(:roles) do |t|
4 | t.string :name
5 | t.references :resource, :polymorphic => true
6 |
7 | t.timestamps
8 | end
9 |
10 | create_table(:admin_users_roles, :id => false) do |t|
11 | t.references :admin_user
12 | t.references :role
13 | end
14 |
15 | add_index(:roles, [ :name, :resource_type, :resource_id ])
16 | add_index(:admin_users_roles, [ :admin_user_id, :role_id ])
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/db/migrate/20190901125126_create_organisation_settings.rb:
--------------------------------------------------------------------------------
1 | class CreateOrganisationSettings < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :organisation_settings do |t|
4 | t.string :license_key
5 | t.string :activation_id
6 | t.boolean :full_license, default: false
7 | t.string :company_name
8 | end
9 |
10 | remove_column :admin_users, :company_name, :string
11 | remove_column :admin_users, :license_key, :string
12 | remove_column :admin_users, :activation_id, :string
13 | remove_column :admin_users, :full_license, :boolean, default: false
14 |
15 | remove_column :permissions, :admin_user_id, :integer
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/db/migrate/20191020103654_create_roles_permissions_table.rb:
--------------------------------------------------------------------------------
1 | class CreateRolesPermissionsTable < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :roles_permissions do |t|
4 | t.references :role
5 | t.references :permission
6 | end
7 |
8 | add_index(:roles_permissions, [ :role_id, :permission_id ])
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20191107072022_add_status_to_admin_users.rb:
--------------------------------------------------------------------------------
1 | class AddStatusToAdminUsers < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :admin_users, :active, :boolean
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20191111185000_add_fields_to_roles.rb:
--------------------------------------------------------------------------------
1 | class AddFieldsToRoles < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :roles, :administrator, :boolean
4 | add_column :roles, :editor, :boolean
5 | add_column :roles, :export, :boolean
6 | add_column :roles, :export_limit, :integer
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/db/migrate/20191123165832_create_target_table_settings.rb:
--------------------------------------------------------------------------------
1 | class CreateTargetTableSettings < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :target_table_settings do |t|
4 | t.string :name, null: false
5 | t.string :nested_table
6 | t.string :create_destination
7 | t.string :delete_destination
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20200111093456_add_database_table.rb:
--------------------------------------------------------------------------------
1 | class AddDatabaseTable < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :databases do |t|
4 | t.string :adapter, null: false
5 | t.string :encoding
6 | t.integer :pool, default: 5
7 | t.string :host, null: false
8 | t.string :username, null: false
9 | t.string :password_digest, null: false
10 | t.integer :port, null: false
11 | t.string :name
12 | t.string :friendly_name
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/db/migrate/20200126125119_add_database_id_to_target_table_settings.rb:
--------------------------------------------------------------------------------
1 | class AddDatabaseIdToTargetTableSettings < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :target_table_settings, :database_id, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20200131135708_rename_database_password_field.rb:
--------------------------------------------------------------------------------
1 | class RenameDatabasePasswordField < ActiveRecord::Migration[5.1]
2 | def change
3 | rename_column :databases, :password_digest, :password
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20200325153714_add_editable_fields_to_target_table_settings.rb:
--------------------------------------------------------------------------------
1 | class AddEditableFieldsToTargetTableSettings < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :target_table_settings, :editable_fields, :jsonb
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20200408133632_add_relay_gem_to_databases.rb:
--------------------------------------------------------------------------------
1 | class AddRelayGemToDatabases < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :databases, :domain_url, :string
4 | add_column :databases, :gem_token, :string
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20200417114658_add_database_id_to_view_builders.rb:
--------------------------------------------------------------------------------
1 | class AddDatabaseIdToViewBuilders < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :view_builders, :database_id, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20200429134402_add_user_id_to_activity.rb:
--------------------------------------------------------------------------------
1 | class AddUserIdToActivity < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :activities, :user_id, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20200507093234_add_database_id_to_task_queues.rb:
--------------------------------------------------------------------------------
1 | class AddDatabaseIdToTaskQueues < ActiveRecord::Migration[5.2]
2 | def change
3 | add_column :task_queues, :database_id, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20200526152632_add_database_update_to_task_queues.rb:
--------------------------------------------------------------------------------
1 | class AddDatabaseUpdateToTaskQueues < ActiveRecord::Migration[5.2]
2 | def change
3 | add_column :task_queues, :success_database_update, :jsonb
4 | add_column :task_queues, :failure_database_update, :jsonb
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20200528143521_add_enabled_field_to_task_queue.rb:
--------------------------------------------------------------------------------
1 | class AddEnabledFieldToTaskQueue < ActiveRecord::Migration[5.2]
2 | def change
3 | add_column :task_queues, :enabled, :boolean, default: true
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20200605105826_remove_null_restriction_task_queue_item.rb:
--------------------------------------------------------------------------------
1 | class RemoveNullRestrictionTaskQueueItem < ActiveRecord::Migration[5.2]
2 | def change
3 | change_column :task_queue_outcomes, :task_queue_item_reappear_at, :datetime, null: true
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20200607113114_add_database_id_to_activities.rb:
--------------------------------------------------------------------------------
1 | class AddDatabaseIdToActivities < ActiveRecord::Migration[5.2]
2 | def change
3 | add_column :activities, :database_id, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20200628161056_add_service_name_to_active_storage_blobs.active_storage.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from active_storage (originally 20190112182829)
2 | class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0]
3 | def up
4 | unless column_exists?(:active_storage_blobs, :service_name)
5 | add_column :active_storage_blobs, :service_name, :string
6 |
7 | if configured_service = ActiveStorage::Blob.service.name
8 | ActiveStorage::Blob.unscoped.update_all(service_name: configured_service)
9 | end
10 |
11 | change_column :active_storage_blobs, :service_name, :string, null: false
12 | end
13 | end
14 |
15 | def down
16 | remove_column :active_storage_blobs, :service_name
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/db/migrate/20200628161057_create_active_storage_variant_records.active_storage.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from active_storage (originally 20191206030411)
2 | class CreateActiveStorageVariantRecords < ActiveRecord::Migration[6.0]
3 | def change
4 | unless table_exists?(:active_storage_variant_records)
5 | create_table :active_storage_variant_records do |t|
6 | t.belongs_to :blob, null: false, index: false
7 | t.string :variation_digest, null: false
8 |
9 | t.index %i[ blob_id variation_digest ], name: "index_active_storage_variant_records_uniqueness", unique: true
10 | t.foreign_key :active_storage_blobs, column: :blob_id
11 | end
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/db/migrate/20210117152849_remove_unique_constraint_task_queue_index.rb:
--------------------------------------------------------------------------------
1 | class RemoveUniqueConstraintTaskQueueIndex < ActiveRecord::Migration[6.1]
2 | def change
3 | remove_index :task_queue_outcomes, [:task_queue_id, :task_queue_item_primary_key]
4 |
5 | add_index :task_queue_outcomes, [:task_queue_id, :task_queue_item_primary_key], name: 'task_queue_item_index'
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/db/migrate/20210130095843_add_primary_keys_to_target_table_settings.rb:
--------------------------------------------------------------------------------
1 | class AddPrimaryKeysToTargetTableSettings < ActiveRecord::Migration[6.1]
2 | def change
3 | add_column :target_table_settings, :primary_keys, :jsonb
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # This file should contain all the record creation needed to seed the database
4 | # with its default values.
5 | # The data can then be loaded with the rake db:seed (or created alongside the db
6 | # with db:setup).
7 | #
8 | # Examples:
9 | #
10 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
11 | # Mayor.create(name: 'Emanuel', city: cities.first)
12 |
13 | if Role.all.empty?
14 | Role.create([
15 | {
16 | name: 'Admin',
17 | administrator: true,
18 | editor: true,
19 | export: true
20 | },
21 | {
22 | name: 'Editor',
23 | administrator: false,
24 | editor: true,
25 | export: false
26 | },
27 | {
28 | name: 'User',
29 | administrator: false,
30 | editor: false,
31 | export: false
32 | }
33 | ])
34 | end
35 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 |
3 | services:
4 | db:
5 | image: postgres:11.2-alpine
6 | ports:
7 | - '15432:5432'
8 | environment:
9 | POSTGRES_PASSWORD: postgres
10 |
11 | web:
12 | build: .
13 | command: bash
14 | volumes:
15 | - .:/app
16 | volumes_from:
17 | - bundle
18 | ports:
19 | - "3000:3000"
20 | env_file:
21 | - ./.env
22 | environment:
23 | BUNDLE_SILENCE_ROOT_WARNING: "true"
24 | HISTFILE: /app/.bash_history
25 | KUWINDA_DATABASE_HOST: db
26 | KUWINDA_DATABASE_USER: postgres
27 | KUWINDA_DATABASE_PASSWORD: postgres
28 | KUWINDA_DATABASE_PORT: 5432
29 | depends_on:
30 | - db
31 |
32 | bundle:
33 | image: busybox
34 | volumes:
35 | - /bundle
36 |
--------------------------------------------------------------------------------
/log/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/log/.keep
--------------------------------------------------------------------------------
/public/assets/application-2de56da153daf022d256045cc5d53b7183a603e0af9863d1638f6087e9138d52.css.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/application-2de56da153daf022d256045cc5d53b7183a603e0af9863d1638f6087e9138d52.css.gz
--------------------------------------------------------------------------------
/public/assets/application-60fcce1a154ba59fc56911eb77ae0500d846e0ab7b1bc414b9b6e497c632d2c1.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/application-60fcce1a154ba59fc56911eb77ae0500d846e0ab7b1bc414b9b6e497c632d2c1.js.gz
--------------------------------------------------------------------------------
/public/assets/bootstrap/glyphicons-halflings-regular-13634da87d9e23f8c3ed9108ce1724d183a39ad072e73e1b3d8cbf646d2d0407.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/bootstrap/glyphicons-halflings-regular-13634da87d9e23f8c3ed9108ce1724d183a39ad072e73e1b3d8cbf646d2d0407.eot
--------------------------------------------------------------------------------
/public/assets/bootstrap/glyphicons-halflings-regular-13634da87d9e23f8c3ed9108ce1724d183a39ad072e73e1b3d8cbf646d2d0407.eot.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/bootstrap/glyphicons-halflings-regular-13634da87d9e23f8c3ed9108ce1724d183a39ad072e73e1b3d8cbf646d2d0407.eot.gz
--------------------------------------------------------------------------------
/public/assets/bootstrap/glyphicons-halflings-regular-42f60659d265c1a3c30f9fa42abcbb56bd4a53af4d83d316d6dd7a36903c43e5.svg.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/bootstrap/glyphicons-halflings-regular-42f60659d265c1a3c30f9fa42abcbb56bd4a53af4d83d316d6dd7a36903c43e5.svg.gz
--------------------------------------------------------------------------------
/public/assets/bootstrap/glyphicons-halflings-regular-a26394f7ede100ca118eff2eda08596275a9839b959c226e15439557a5a80742.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/bootstrap/glyphicons-halflings-regular-a26394f7ede100ca118eff2eda08596275a9839b959c226e15439557a5a80742.woff
--------------------------------------------------------------------------------
/public/assets/bootstrap/glyphicons-halflings-regular-e395044093757d82afcb138957d06a1ea9361bdcf0b442d06a18a8051af57456.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/bootstrap/glyphicons-halflings-regular-e395044093757d82afcb138957d06a1ea9361bdcf0b442d06a18a8051af57456.ttf
--------------------------------------------------------------------------------
/public/assets/bootstrap/glyphicons-halflings-regular-e395044093757d82afcb138957d06a1ea9361bdcf0b442d06a18a8051af57456.ttf.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/bootstrap/glyphicons-halflings-regular-e395044093757d82afcb138957d06a1ea9361bdcf0b442d06a18a8051af57456.ttf.gz
--------------------------------------------------------------------------------
/public/assets/bootstrap/glyphicons-halflings-regular-fe185d11a49676890d47bb783312a0cda5a44c4039214094e7957b4c040ef11c.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/bootstrap/glyphicons-halflings-regular-fe185d11a49676890d47bb783312a0cda5a44c4039214094e7957b4c040ef11c.woff2
--------------------------------------------------------------------------------
/public/assets/dataTable/datatables.min-39255d21ad998b32b2fc7eb4a073a5e0b89acb2fcbdd1f90d9a6fc3aa43f656b.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/dataTable/datatables.min-39255d21ad998b32b2fc7eb4a073a5e0b89acb2fcbdd1f90d9a6fc3aa43f656b.js.gz
--------------------------------------------------------------------------------
/public/assets/dragula/dragula.min-94edc9ac879d6bd3fbfa48b57d9742a08cadbbafe2f3233a1a9116c03f2b070f.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/dragula/dragula.min-94edc9ac879d6bd3fbfa48b57d9742a08cadbbafe2f3233a1a9116c03f2b070f.js.gz
--------------------------------------------------------------------------------
/public/assets/favicon-c14aaa6e1b7af86332a6497364938f801db6b1b3f4513dd70024bea60981a6ed.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/favicon-c14aaa6e1b7af86332a6497364938f801db6b1b3f4513dd70024bea60981a6ed.ico
--------------------------------------------------------------------------------
/public/assets/favicon-c14aaa6e1b7af86332a6497364938f801db6b1b3f4513dd70024bea60981a6ed.ico.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/favicon-c14aaa6e1b7af86332a6497364938f801db6b1b3f4513dd70024bea60981a6ed.ico.gz
--------------------------------------------------------------------------------
/public/assets/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2
--------------------------------------------------------------------------------
/public/assets/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot
--------------------------------------------------------------------------------
/public/assets/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot.gz
--------------------------------------------------------------------------------
/public/assets/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf
--------------------------------------------------------------------------------
/public/assets/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf.gz
--------------------------------------------------------------------------------
/public/assets/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg.gz
--------------------------------------------------------------------------------
/public/assets/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff
--------------------------------------------------------------------------------
/public/assets/images/Kuwinda_logo_full-blue-260.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/Kuwinda_logo_full-blue-260.png
--------------------------------------------------------------------------------
/public/assets/images/icons/black-check-box-with-white-check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/black-check-box-with-white-check.png
--------------------------------------------------------------------------------
/public/assets/images/icons/black-checkbox-empty.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/public/assets/images/icons/blue_cat_loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/blue_cat_loading.gif
--------------------------------------------------------------------------------
/public/assets/images/icons/checked-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/checked-1.png
--------------------------------------------------------------------------------
/public/assets/images/icons/circle-with-check-symbol.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/circle-with-check-symbol.png
--------------------------------------------------------------------------------
/public/assets/images/icons/circle-with-contrast.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/circle-with-contrast.png
--------------------------------------------------------------------------------
/public/assets/images/icons/circle-with-cross.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/circle-with-cross.png
--------------------------------------------------------------------------------
/public/assets/images/icons/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/close.png
--------------------------------------------------------------------------------
/public/assets/images/icons/column.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/column.png
--------------------------------------------------------------------------------
/public/assets/images/icons/database-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/database-1.png
--------------------------------------------------------------------------------
/public/assets/images/icons/database-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/database-2.png
--------------------------------------------------------------------------------
/public/assets/images/icons/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/edit.png
--------------------------------------------------------------------------------
/public/assets/images/icons/edit@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/edit@2x.png
--------------------------------------------------------------------------------
/public/assets/images/icons/export.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/export.png
--------------------------------------------------------------------------------
/public/assets/images/icons/group-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/group-3.png
--------------------------------------------------------------------------------
/public/assets/images/icons/import.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/import.png
--------------------------------------------------------------------------------
/public/assets/images/icons/magnifying-glass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/magnifying-glass.png
--------------------------------------------------------------------------------
/public/assets/images/icons/minus-thick.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/minus-thick.png
--------------------------------------------------------------------------------
/public/assets/images/icons/plus-thick.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/plus-thick.png
--------------------------------------------------------------------------------
/public/assets/images/icons/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/plus.png
--------------------------------------------------------------------------------
/public/assets/images/icons/report.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/report.png
--------------------------------------------------------------------------------
/public/assets/images/icons/settings-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/settings-1.png
--------------------------------------------------------------------------------
/public/assets/images/icons/settings-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/settings-black.png
--------------------------------------------------------------------------------
/public/assets/images/icons/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/settings.png
--------------------------------------------------------------------------------
/public/assets/images/icons/team-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/images/icons/team-1.png
--------------------------------------------------------------------------------
/public/assets/images/icons/triangle.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/public/assets/logos/MissionKontrol-logo-inverted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/logos/MissionKontrol-logo-inverted.png
--------------------------------------------------------------------------------
/public/assets/logos/MissionKontrol-logo-original.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/logos/MissionKontrol-logo-original.png
--------------------------------------------------------------------------------
/public/assets/logos/kuwinda_thumbnail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/logos/kuwinda_thumbnail.png
--------------------------------------------------------------------------------
/public/assets/moment/moment.min-a4f754452a828ad057b1b61c20fcb99251bb8fa7db0dba8ca96417b8e5d59c6c.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/moment/moment.min-a4f754452a828ad057b1b61c20fcb99251bb8fa7db0dba8ca96417b8e5d59c6c.js.gz
--------------------------------------------------------------------------------
/public/assets/patterns/header-profile-c05909898218a521d3bd19ba09a9a43338de6de5fdf1d3fc771b0ec28ae416c5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/patterns/header-profile-c05909898218a521d3bd19ba09a9a43338de6de5fdf1d3fc771b0ec28ae416c5.png
--------------------------------------------------------------------------------
/public/assets/patterns/shattered-241155c2a3436bfc0a542fc31fe2908ff2bdfc90e1ac7e26c6ba715b01030dcf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/patterns/shattered-241155c2a3436bfc0a542fc31fe2908ff2bdfc90e1ac7e26c6ba715b01030dcf.png
--------------------------------------------------------------------------------
/public/assets/query-builder/query-builder.min-252935bd0b5adbde13e1c5c616820f8a3a4f5cf645d690905bc728a80eeebe07.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/query-builder/query-builder.min-252935bd0b5adbde13e1c5c616820f8a3a4f5cf645d690905bc728a80eeebe07.js.gz
--------------------------------------------------------------------------------
/public/assets/shopify/draggable.bundle-06c5ee80a53567c4a8f91f12174da87600991bb912404d73dbc1e66cbd8b2c94.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/shopify/draggable.bundle-06c5ee80a53567c4a8f91f12174da87600991bb912404d73dbc1e66cbd8b2c94.js.gz
--------------------------------------------------------------------------------
/public/assets/shopify/sortable-8042a7900fcf2bf2e78d523d4cc0b896ec1151b893c9fe62dc702d6e047df669.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/shopify/sortable-8042a7900fcf2bf2e78d523d4cc0b896ec1151b893c9fe62dc702d6e047df669.js.gz
--------------------------------------------------------------------------------
/public/assets/sweetAlert/sweetalert.min-c517df19a3eecca1c27936dfafd34163d0c1c81271aa6f914db8d5b1e7731d2f.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/assets/sweetAlert/sweetalert.min-c517df19a3eecca1c27936dfafd34163d0c1c81271aa6f914db8d5b1e7731d2f.js.gz
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/public/favicon.ico
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | # User-agent: *
5 | # Disallow: /
6 |
--------------------------------------------------------------------------------
/spec/factories/activity.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | FactoryBot.define do
4 | factory :activity do
5 | content { 'met with a user today' }
6 | kind { 'meeting' }
7 |
8 | trait :user do
9 | feedable_id { 1 }
10 | feedable_type { 'users' }
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/factories/admin_user.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | FactoryBot.define do
4 | factory :admin_user do
5 | email { FFaker::Internet.email }
6 | password { 'password' }
7 | password_confirmation { 'password' }
8 | active { true }
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/spec/factories/database.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | FactoryBot.define do
4 | factory :database do
5 | friendly_name { 'Test Company' }
6 | adapter { 'postgresql' }
7 | host { ENV['DEMO_CLIENT_DB_HOST'] }
8 | port { 5432 }
9 | name { ENV['DEMO_CLIENT_DB_NAME'] }
10 | username { ENV['DEMO_CLIENT_DB_USER'] }
11 | password { ENV['DEMO_CLIENT_DB_PASSWORD'] }
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/factories/organisation_setting.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | FactoryBot.define do
4 | factory :organisation_setting do
5 | company_name { 'Test Company' }
6 | activation_id { '1559143878' }
7 | license_key { 'license_key' }
8 | full_license { false }
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/spec/factories/permission.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | FactoryBot.define do
4 | factory :permission do
5 | subject_class { 'events' }
6 | action { 'view' }
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/spec/factories/role.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | FactoryBot.define do
4 | factory :role do
5 | name { 'Admin' }
6 | administrator { false }
7 | editor { false }
8 | export { false }
9 |
10 | trait :admin do
11 | name { 'Admin' }
12 | administrator { true }
13 | editor { true }
14 | export { true }
15 | end
16 |
17 | trait :Editor do
18 | name { 'Editor' }
19 | end
20 |
21 | trait :editor do
22 | name { 'Editor' }
23 | editor { true }
24 | end
25 |
26 | trait :user do
27 | name { 'User' }
28 | end
29 |
30 | trait :export do
31 | export { true }
32 | end
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/spec/factories/target_table_setting.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | FactoryBot.define do
4 | factory :target_table_setting do
5 | name { 'users' }
6 | nested_table { 'attending_events' }
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/spec/factories/task_queue.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | FactoryBot.define do
4 | factory :task_queue do
5 | name { 'Task Queue Test' }
6 | table { FFaker::Name.name }
7 | database_id { 1 }
8 | details { 'Task Queue Details' }
9 | query_builder_rules { 'Query Builder Rules' }
10 | query_builder_sql { 'Query Builder SQL' }
11 | raw_sql { 'Raw SQL' }
12 | draggable_fields { [] }
13 | success_outcome_title { 'Customer has cookies' }
14 | success_outcome_timeout { 1 }
15 | failure_outcome_title { 'Customer does not have cookies' }
16 | failure_outcome_timeout { 30 }
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/spec/factories/user.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | FactoryBot.define do
4 | factory :user do
5 | sequence(:email) { |i| "test#{i}@example.com" }
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/spec/factories/view_builder.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | FactoryBot.define do
4 | factory :view_builder do
5 | view_name { 'View name' }
6 | table_name { FFaker::Name.name }
7 | status { 'active' }
8 | table_attributes do
9 | {
10 | 'visible_fields' => {
11 | '1' => 'area',
12 | '2' => 'level',
13 | '3' => 'plan',
14 | '4' => 'space'
15 | },
16 | 'default_rows' => '10'
17 | }
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/spec/factories/work_list.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | FactoryBot.define do
4 | factory :work_list do
5 | name { 'test' }
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/spec/features/cache_connection_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | feature 'Loading table with corrrect permissions', js: true do
4 | background do
5 | sign_in_as_admin_with_license
6 | setup_tables_and_roles('events')
7 | create(:target_table_setting, name: @table, database_id: @database.id)
8 | give_role_all_permissions(@user.roles.first, 'events')
9 | end
10 |
11 | xscenario 'user with sales role with permissions to view table can view table page' do
12 | visit table_path(id: @database.id, table: 'events')
13 | expect(page).to have_content('Nairobi')
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/spec/features/tables/add_record_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | feature 'Adding records with sufficient permissions', js: true do
4 | background do
5 | sign_in_admin_user_with_complete_table_settings('attending_events')
6 | end
7 |
8 | scenario 'with a single record selected creates the record' do
9 | find('.table--add-record-button').click
10 | fill_in 'record[transaction_id]', with: 5
11 | fill_in 'record[user_id]', with: 7
12 | click_button 'Save'
13 | expect(find("tr:last-child > td:nth-child(3)").text).to eq '5'
14 | end
15 | end
16 |
17 | feature 'Adding records without sufficient permissions', js: true do
18 | background do
19 | sign_in_admin_user_with_single_permissions('attending_events', :view)
20 | end
21 |
22 | scenario 'user cannot see the add option' do
23 | expect(page).not_to have_content('.table--add-record-button')
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/spec/features/tables/admin_views_table_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | feature 'Admin views a table', type: :feature do
4 | before do
5 | delete_layout_for_users
6 | end
7 |
8 | xscenario 'clicking on a table will show the selected table' do
9 | VCR.use_cassette('license_key/validation_success') do
10 | sign_in_as_admin_with_license
11 | when_i_click_the_users_link
12 | end
13 |
14 | then_i_expect_to_be_redirected_to_the_users_table
15 | end
16 | end
17 |
18 | def delete_layout_for_users
19 | ViewBuilder.where(table_name: 'users').delete_all
20 | end
21 |
22 | def when_i_click_the_users_link
23 | within('#side-menu') do
24 | click_link 'users'
25 | end
26 | end
27 |
28 | def then_i_expect_to_be_redirected_to_the_users_table
29 | expect(page).to have_current_path(table_path(id: 'users', table: 'users'))
30 | end
31 |
--------------------------------------------------------------------------------
/spec/features/tables/settings_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | feature 'Modifying Table settings', js: true do
4 | background do
5 | sign_in_admin_user_with_complete_table_settings('attending_events')
6 | end
7 |
8 | scenario 'editing editable and mandatory settings' do
9 | find('.table--settings').click
10 | select 'No', from: '[editable_fields][transaction_id][editable]'
11 | click_button 'Save'
12 | visit table_path(id: @database.id, table: 'attending_events')
13 | wait_for_ajax
14 | first('.data-table--select-input').click
15 | find('.filter-bar--edit > .white').click
16 | expect(page).not_to have_content("input[name$='[user_id]']")
17 | end
18 | end
19 |
20 | feature 'Modifying table settings without sufficient permissions', js: true do
21 | background do
22 | sign_in_admin_user_with_single_permissions('attending_events', :view)
23 | end
24 |
25 | scenario 'user cannot see the add option' do
26 | expect(page).not_to have_content('.table--settings')
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/spec/features/users/admin_log_in_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | feature 'User login', js: true do
4 | scenario 'when user is active' do
5 | sign_in_as_user_with_license
6 | expect(page).to have_current_path(dashboard_path)
7 | end
8 |
9 | scenario 'when user is inactive' do
10 | create_org_with_license
11 | @user = create(:admin_user, active: false)
12 | sign_in_user
13 | expect(page).to have_current_path(new_admin_user_session_path)
14 | expect(page).to have_content 'Your account is not active. Please speak to an Administrator.'
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/spec/fixtures/events.yml:
--------------------------------------------------------------------------------
1 | sailing:
2 | id: 1
3 | day: Tuesday
4 | user_id: 1
5 |
6 | snowboarding:
7 | id: 2
8 | day: Friday
9 | user_id: 3
10 |
11 | # ["id", "day", "area", "level", "plan", "space", "meeting", "created_at", "updated_at", "user_id"]
12 |
--------------------------------------------------------------------------------
/spec/fixtures/users.yml:
--------------------------------------------------------------------------------
1 | marko:
2 | id: 1
3 | name: Marko
4 | email: marko@example.com
5 |
6 | # "id",
7 | # "email",
8 | # "encrypted_password",
9 | # "reset_password_token",
10 | # "reset_password_sent_at",
11 | # "remember_created_at",
12 | # "sign_in_count",
13 | # "current_sign_in_at",
14 | # "last_sign_in_at",
15 | # "current_sign_in_ip",
16 | # "last_sign_in_ip",
17 | # "created_at",
18 | # "updated_at",
19 | # "provider",
20 | # "uid",
21 | # "user",
22 | # "name",
23 | # "image_file_name",
24 | # "image_content_type",
25 | # "image_file_size",
26 | # "image_updated_at",
27 | # "level",
28 | # "choice",
29 | # "number"
30 |
--------------------------------------------------------------------------------
/spec/support/features/target_database_helpers.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Features
4 | module TargetDatabaseHelpers
5 | def connect_to_target_database(database)
6 | @connection = establish_connection(database)
7 | @connection.connection
8 | end
9 |
10 | def remove_connection_to_target_database
11 | ActiveRecord::Base.remove_connection(@connection)
12 | end
13 |
14 | def establish_connection(database)
15 | ActiveRecord::Base.establish_connection(
16 | adapter: database.adapter,
17 | host: database.host,
18 | username: database.username,
19 | password: database.password,
20 | database: database.name,
21 | port: database.port
22 | )
23 | end
24 | end
25 | end
26 |
27 | RSpec.configure do |config|
28 | config.include Features::TargetDatabaseHelpers, type: :feature
29 | end
30 |
--------------------------------------------------------------------------------
/spec/support/time_helpers.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | RSpec.configure do |config|
4 | config.include ActiveSupport::Testing::TimeHelpers
5 | end
6 |
--------------------------------------------------------------------------------
/spec/support/unit/fake_active_record.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class FakeActiveRecord
4 | COLUMNS = %w[name].freeze
5 |
6 | def respond_to_missing?(method_name)
7 | COLUMNS.include?(method_name.to_s) || super
8 | end
9 |
10 | def method_missing(method_name, *args)
11 | if respond_to?(method_name)
12 | instance_variable_get("@#{method_name}")
13 | else
14 | super
15 | end
16 | end
17 |
18 | def self.define_attribute_methods
19 | COLUMNS.each do |name|
20 | define_method(name) { instance_variable_get("@#{name}") }
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/spec/support/wait_for_ajax.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module WaitForAjax
4 | def wait_for_ajax
5 | Timeout.timeout(25) do
6 | loop until finished_all_ajax_requests?
7 | end
8 | end
9 |
10 | def finished_all_ajax_requests?
11 | page.evaluate_script('jQuery.active').zero?
12 | end
13 | end
14 |
15 | RSpec.configure do |config|
16 | config.include WaitForAjax, type: :feature
17 | end
18 |
--------------------------------------------------------------------------------
/spec/unit/lib/kuwinda/presenter/list_available_tables_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'rails_helper'
4 |
5 | describe Kuwinda::Presenter::ListAvailableTables do
6 | subject { list_tables.call }
7 |
8 | let(:list_tables) do
9 | described_class.new(database_connection)
10 | end
11 | let(:database_connection) do
12 | Kuwinda::UseCase::DatabaseConnection.new(database).execute
13 | end
14 | let(:database) { create(:database) }
15 |
16 | context 'listing tables' do
17 | it 'displays the available tables' do
18 | expect(subject).to include('attending_events', 'users')
19 | end
20 |
21 | it 'does not display the schema_migrations table' do
22 | expect(subject).to_not include('schema_migrations')
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/spec/unit/lib/kuwinda/presenter/list_table_fields_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'rails_helper'
4 |
5 | describe Kuwinda::Presenter::ListTableFields do
6 | subject { list_fields.call }
7 |
8 | let(:list_fields) do
9 | described_class.new(database_connection, table)
10 | end
11 | let(:database_connection) do
12 | Kuwinda::UseCase::DatabaseConnection.new(database).execute
13 | end
14 | let(:database) { create(:database) }
15 | let(:table) { 'Users' }
16 |
17 | context 'listing connections' do
18 | it 'displays the available table fields' do
19 | expect(subject).to include('email', 'name')
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/spec/unit/lib/kuwinda/presenter/list_table_fields_with_type_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'rails_helper'
4 |
5 | describe Kuwinda::Presenter::ListTableFieldsWithType do
6 | subject { list_fields_with_type.call }
7 |
8 | let(:list_fields_with_type) do
9 | described_class.new(database_connection, table)
10 | end
11 | let(:database_connection) do
12 | Kuwinda::UseCase::DatabaseConnection.new(database).execute
13 | end
14 | let(:database) { create(:database) }
15 | let(:table) { 'Users' }
16 |
17 | context 'listing connections' do
18 | it 'displays the available tables their types' do
19 | expect(subject).to include(["id", "integer", "Users"], ["email", "string", "Users"])
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/spec/unit/lib/kuwinda/presenter/retrieve_data_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe Kuwinda::Presenter::RetrieveData do
4 | subject { retrieve_data.call }
5 |
6 | let(:retrieve_data) do
7 | described_class.new(database_connection, view_builder, query_limiter)
8 | end
9 | let(:database_connection) do
10 | Kuwinda::UseCase::DatabaseConnection.new(database).execute
11 | end
12 | let(:database) { create(:database) }
13 | let(:view_builder) { create(:view_builder) }
14 | let(:query_limiter) { 'WHERE user_id = 3' }
15 | let(:expected_result) do
16 | {
17 | 0 => ['London', 'pro', 'gold', 6],
18 | 1 => ['Morzine', 'beginner', 'silver', 2]
19 | }
20 | end
21 |
22 | # TODO: this is failing intermittently due to a different id
23 | # create on every run, expected_result is not always consistent
24 | context 'retrieving data' do
25 | xit 'returns the correct fields from the table' do
26 | expect(subject).to eq expected_result
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/spec/unit/lib/kuwinda/use_case/database_connection_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'rails_helper'
4 |
5 | describe Kuwinda::UseCase::DatabaseConnection do
6 | context 'when establishing a database connection' do
7 | subject { described_class.new(database).execute }
8 |
9 | let(:database) { create(:database) }
10 | let(:expected_result) do
11 | %w[attending_events schema_migrations welcomes users transactions companies]
12 | end
13 | # TODO: more specific testing of error messages - InvalidClientDatabaseError not valid
14 |
15 | it 'establishes an active connection' do
16 | expect(subject.connect.connection.active?).to eq true
17 | end
18 |
19 | it 'can list the tables available in the database' do
20 | expect(subject.connect.connection.tables).to match_array expected_result
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/spec/unit/models/database_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe Database do
4 | let(:database) { build(:database, password: password) }
5 |
6 | describe '#encrypt_database_password' do
7 | subject { database.encrypt_database_password }
8 | let(:password) { 'password' }
9 |
10 | context 'when saving the database' do
11 | it 'encrypts the password' do
12 | database.save
13 | expect(database.password).not_to eq password
14 | end
15 | end
16 |
17 | context 'when password has been encrypted' do
18 | context 'and trying to save the database with the encypted password' do
19 | it 'saves the originally encrypted password' do
20 | database.save
21 | encrypted_password = database.password
22 | database.password = encrypted_password
23 | database.save
24 | expect(database.password).to eq encrypted_password
25 | end
26 | end
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/spec/unit/models/sql_filter_factory_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'rails_helper'
4 |
5 | describe SQLFilterFactory do
6 | it 'responds to .build_sql_filter' do
7 | expect(described_class).to respond_to(:build_sql_filter)
8 | end
9 |
10 | describe '.build_sql_filter' do
11 | context 'when sql filter kind is equal' do
12 | it 'returns a SQLFilter::Equal filter' do
13 | filter_attributes = {}
14 | filter_attributes['kind'] = 'equal'
15 | actual = described_class.build_sql_filter(filter_attributes)
16 | expect(actual).to be_a(SQLFilter::Equal)
17 | end
18 | end
19 |
20 | context 'when sql filter kind is unknown' do
21 | it 'returns nil' do
22 | filter_attributes = {}
23 | filter_attributes['kind'] = 'notknown'
24 | actual = described_class.build_sql_filter(filter_attributes)
25 | expect(actual).to be_nil
26 | end
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/spec/unit/models/task_queue_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'rails_helper'
4 |
5 | describe TaskQueue do
6 | let(:a_task_queue) { described_class.new }
7 |
8 | it 'responds to name' do
9 | expect(a_task_queue).to respond_to(:name)
10 | end
11 |
12 | it 'responds to details' do
13 | expect(a_task_queue).to respond_to(:details)
14 | end
15 |
16 | it 'responds to query_builder_rules' do
17 | expect(a_task_queue).to respond_to(:query_builder_rules)
18 | end
19 |
20 | it 'responds to query_builder_sql' do
21 | expect(a_task_queue).to respond_to(:query_builder_sql)
22 | end
23 |
24 | it 'responds to table' do
25 | expect(a_task_queue).to respond_to(:table)
26 | end
27 |
28 | it 'is invalid without a name' do
29 | a_task_queue.name = nil
30 | a_task_queue.valid?
31 | expect(a_task_queue.errors.keys).to include(:name)
32 | end
33 |
34 | it 'is invalid without a table' do
35 | a_task_queue.table = nil
36 | a_task_queue.valid?
37 | expect(a_task_queue.errors.keys).to include(:table)
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/spec/unit/models/view_builder_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'rails_helper'
4 |
5 | describe ViewBuilder, type: :model do
6 | describe 'validations' do
7 | it 'requires a table_name' do
8 | view_builder = described_class.new
9 | view_builder.valid?
10 | expect(view_builder.errors[:table_name]).to include("can't be blank")
11 | end
12 | end
13 |
14 | describe 'configurations' do
15 | it 'can save which fields to use for the view' do
16 | view_builder = described_class.new(table_name: 'Users', table_attributes: { visible: 'email' })
17 | expect(view_builder.table_attributes['visible']).to include('email')
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/vendor/assets/fonts/Casino_Hand/casino_hand-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/fonts/Casino_Hand/casino_hand-webfont.eot
--------------------------------------------------------------------------------
/vendor/assets/fonts/Casino_Hand/casino_hand-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/fonts/Casino_Hand/casino_hand-webfont.ttf
--------------------------------------------------------------------------------
/vendor/assets/fonts/Casino_Hand/casino_hand-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/fonts/Casino_Hand/casino_hand-webfont.woff
--------------------------------------------------------------------------------
/vendor/assets/images/animated-overlay.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/animated-overlay.gif
--------------------------------------------------------------------------------
/vendor/assets/images/blueimp/img/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/blueimp/img/error.png
--------------------------------------------------------------------------------
/vendor/assets/images/blueimp/img/error.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/vendor/assets/images/blueimp/img/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/blueimp/img/loading.gif
--------------------------------------------------------------------------------
/vendor/assets/images/blueimp/img/play-pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/blueimp/img/play-pause.png
--------------------------------------------------------------------------------
/vendor/assets/images/blueimp/img/play-pause.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/vendor/assets/images/blueimp/img/video-play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/blueimp/img/video-play.png
--------------------------------------------------------------------------------
/vendor/assets/images/blueimp/img/video-play.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/vendor/assets/images/bootstrap-colorpicker/alpha-horizontal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/bootstrap-colorpicker/alpha-horizontal.png
--------------------------------------------------------------------------------
/vendor/assets/images/bootstrap-colorpicker/alpha.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/bootstrap-colorpicker/alpha.png
--------------------------------------------------------------------------------
/vendor/assets/images/bootstrap-colorpicker/hue-horizontal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/bootstrap-colorpicker/hue-horizontal.png
--------------------------------------------------------------------------------
/vendor/assets/images/bootstrap-colorpicker/hue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/bootstrap-colorpicker/hue.png
--------------------------------------------------------------------------------
/vendor/assets/images/bootstrap-colorpicker/saturation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/bootstrap-colorpicker/saturation.png
--------------------------------------------------------------------------------
/vendor/assets/images/chosen-sprite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/chosen-sprite.png
--------------------------------------------------------------------------------
/vendor/assets/images/chosen-sprite@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/chosen-sprite@2x.png
--------------------------------------------------------------------------------
/vendor/assets/images/green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/green.png
--------------------------------------------------------------------------------
/vendor/assets/images/green@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/green@2x.png
--------------------------------------------------------------------------------
/vendor/assets/images/iCheck/green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/iCheck/green.png
--------------------------------------------------------------------------------
/vendor/assets/images/iCheck/green@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/iCheck/green@2x.png
--------------------------------------------------------------------------------
/vendor/assets/images/images/animated-overlay.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/images/animated-overlay.gif
--------------------------------------------------------------------------------
/vendor/assets/images/images/ui-bg_flat_0_aaaaaa_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/images/ui-bg_flat_0_aaaaaa_40x100.png
--------------------------------------------------------------------------------
/vendor/assets/images/images/ui-bg_flat_75_ffffff_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/images/ui-bg_flat_75_ffffff_40x100.png
--------------------------------------------------------------------------------
/vendor/assets/images/images/ui-bg_glass_55_fbf9ee_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/images/ui-bg_glass_55_fbf9ee_1x400.png
--------------------------------------------------------------------------------
/vendor/assets/images/images/ui-bg_glass_65_ffffff_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/images/ui-bg_glass_65_ffffff_1x400.png
--------------------------------------------------------------------------------
/vendor/assets/images/images/ui-bg_glass_75_dadada_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/images/ui-bg_glass_75_dadada_1x400.png
--------------------------------------------------------------------------------
/vendor/assets/images/images/ui-bg_glass_75_e6e6e6_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/images/ui-bg_glass_75_e6e6e6_1x400.png
--------------------------------------------------------------------------------
/vendor/assets/images/images/ui-bg_glass_95_fef1ec_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/images/ui-bg_glass_95_fef1ec_1x400.png
--------------------------------------------------------------------------------
/vendor/assets/images/images/ui-bg_highlight-soft_75_cccccc_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/images/ui-bg_highlight-soft_75_cccccc_1x100.png
--------------------------------------------------------------------------------
/vendor/assets/images/images/ui-icons_222222_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/images/ui-icons_222222_256x240.png
--------------------------------------------------------------------------------
/vendor/assets/images/images/ui-icons_2e83ff_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/images/ui-icons_2e83ff_256x240.png
--------------------------------------------------------------------------------
/vendor/assets/images/images/ui-icons_454545_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/images/ui-icons_454545_256x240.png
--------------------------------------------------------------------------------
/vendor/assets/images/images/ui-icons_888888_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/images/ui-icons_888888_256x240.png
--------------------------------------------------------------------------------
/vendor/assets/images/images/ui-icons_cd0a0a_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/images/ui-icons_cd0a0a_256x240.png
--------------------------------------------------------------------------------
/vendor/assets/images/sort.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/sort.png
--------------------------------------------------------------------------------
/vendor/assets/images/sort_asc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/sort_asc.png
--------------------------------------------------------------------------------
/vendor/assets/images/sort_desc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/sort_desc.png
--------------------------------------------------------------------------------
/vendor/assets/images/sprite-skin-flat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/sprite-skin-flat.png
--------------------------------------------------------------------------------
/vendor/assets/images/sprite-skin-flat2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/sprite-skin-flat2.png
--------------------------------------------------------------------------------
/vendor/assets/images/sprite-skin-nice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/sprite-skin-nice.png
--------------------------------------------------------------------------------
/vendor/assets/images/sprite-skin-simple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/sprite-skin-simple.png
--------------------------------------------------------------------------------
/vendor/assets/images/spritemap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/spritemap.png
--------------------------------------------------------------------------------
/vendor/assets/images/spritemap@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/images/spritemap@2x.png
--------------------------------------------------------------------------------
/vendor/assets/javascripts/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/javascripts/.keep
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/dragula/dragula.min.css:
--------------------------------------------------------------------------------
1 | .gu-mirror{position:fixed!important;margin:0!important;z-index:9999!important;opacity:.8;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";filter:alpha(opacity=80)}.gu-hide{display:none!important}.gu-unselectable{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.gu-transit{opacity:.2;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";filter:alpha(opacity=20)}
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/images/bootstrap-colorpicker/alpha-horizontal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/images/bootstrap-colorpicker/alpha-horizontal.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/images/bootstrap-colorpicker/alpha.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/images/bootstrap-colorpicker/alpha.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/images/bootstrap-colorpicker/hue-horizontal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/images/bootstrap-colorpicker/hue-horizontal.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/images/bootstrap-colorpicker/hue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/images/bootstrap-colorpicker/hue.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/images/bootstrap-colorpicker/saturation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/images/bootstrap-colorpicker/saturation.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/images/sort.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/images/sort.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/images/sort_asc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/images/sort_asc.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/images/sort_desc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/images/sort_desc.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/images/sprite-skin-flat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/images/sprite-skin-flat.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/images/sprite-skin-flat2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/images/sprite-skin-flat2.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/images/sprite-skin-nice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/images/sprite-skin-nice.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/images/sprite-skin-simple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/images/sprite-skin-simple.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/images/spritemap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/images/spritemap.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/images/spritemap@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/images/spritemap@2x.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/jQueryUI/images/animated-overlay.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/jQueryUI/images/animated-overlay.gif
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/jQueryUI/images/ui-bg_flat_0_aaaaaa_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/jQueryUI/images/ui-bg_flat_0_aaaaaa_40x100.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/jQueryUI/images/ui-bg_flat_75_ffffff_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/jQueryUI/images/ui-bg_flat_75_ffffff_40x100.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/jQueryUI/images/ui-bg_glass_55_fbf9ee_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/jQueryUI/images/ui-bg_glass_55_fbf9ee_1x400.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/jQueryUI/images/ui-bg_glass_65_ffffff_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/jQueryUI/images/ui-bg_glass_65_ffffff_1x400.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/jQueryUI/images/ui-bg_glass_75_dadada_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/jQueryUI/images/ui-bg_glass_75_dadada_1x400.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/jQueryUI/images/ui-bg_glass_75_e6e6e6_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/jQueryUI/images/ui-bg_glass_75_e6e6e6_1x400.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/jQueryUI/images/ui-bg_glass_95_fef1ec_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/jQueryUI/images/ui-bg_glass_95_fef1ec_1x400.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/jQueryUI/images/ui-bg_highlight-soft_75_cccccc_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/jQueryUI/images/ui-bg_highlight-soft_75_cccccc_1x100.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/jQueryUI/images/ui-icons_222222_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/jQueryUI/images/ui-icons_222222_256x240.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/jQueryUI/images/ui-icons_2e83ff_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/jQueryUI/images/ui-icons_2e83ff_256x240.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/jQueryUI/images/ui-icons_454545_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/jQueryUI/images/ui-icons_454545_256x240.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/jQueryUI/images/ui-icons_888888_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/jQueryUI/images/ui-icons_888888_256x240.png
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/jQueryUI/images/ui-icons_cd0a0a_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mission-Kontrol/MissionKontrol/3164f543272d1299663be147300217f9067682cb/vendor/assets/stylesheets/jQueryUI/images/ui-icons_cd0a0a_256x240.png
--------------------------------------------------------------------------------