diff --git a/week_5/activity-tracker/Gemfile b/week_5/activity-tracker/Gemfile index 6a97ca54..7f78e313 100644 --- a/week_5/activity-tracker/Gemfile +++ b/week_5/activity-tracker/Gemfile @@ -46,7 +46,7 @@ gem "bootsnap", require: false # gem "sassc-rails" # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] -# gem "image_processing", "~> 1.2" +gem "image_processing", "~> 1.2" group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem @@ -75,4 +75,6 @@ gem "rails-controller-testing" gem 'bootstrap', '~> 5.2.2' -gem 'devise' \ No newline at end of file +gem 'prawn', '~> 2.4' + +gem 'devise' diff --git a/week_5/activity-tracker/Gemfile.lock b/week_5/activity-tracker/Gemfile.lock index bc7790d9..724d0351 100644 --- a/week_5/activity-tracker/Gemfile.lock +++ b/week_5/activity-tracker/Gemfile.lock @@ -107,6 +107,9 @@ GEM activesupport (>= 5.0) i18n (1.12.0) concurrent-ruby (~> 1.0) + image_processing (1.12.2) + mini_magick (>= 4.9.5, < 5) + ruby-vips (>= 2.0.17, < 3) importmap-rails (1.1.5) actionpack (>= 6.0.0) railties (>= 6.0.0) @@ -127,6 +130,7 @@ GEM marcel (1.0.2) matrix (0.4.2) method_source (1.0.0) + mini_magick (4.12.0) mini_mime (1.1.2) minitest (5.17.0) msgpack (1.6.0) @@ -143,7 +147,11 @@ GEM nokogiri (1.14.0-x86_64-linux) racc (~> 1.4) orm_adapter (0.5.0) + pdf-core (0.9.0) popper_js (2.11.6) + prawn (2.4.0) + pdf-core (~> 0.9.0) + ttfunk (~> 1.7) public_suffix (5.0.1) puma (5.6.5) nio4r (~> 2.0) @@ -189,6 +197,8 @@ GEM actionpack (>= 5.2) railties (>= 5.2) rexml (3.2.5) + ruby-vips (2.1.4) + ffi (~> 1.12) rubyzip (2.3.2) sassc (2.4.0) ffi (~> 1.9) @@ -215,6 +225,7 @@ GEM thor (1.2.1) tilt (2.0.11) timeout (0.3.1) + ttfunk (1.7.0) turbo-rails (1.3.2) actionpack (>= 6.0.0) activejob (>= 6.0.0) @@ -249,8 +260,10 @@ DEPENDENCIES capybara debug devise + image_processing (~> 1.2) importmap-rails jbuilder + prawn (~> 2.4) puma (~> 5.0) rails (~> 7.0.4) rails-controller-testing diff --git a/week_5/activity-tracker/app/assets/stylesheets/light-mode.css b/week_5/activity-tracker/app/assets/stylesheets/light-mode.css new file mode 100644 index 00000000..79c6f209 --- /dev/null +++ b/week_5/activity-tracker/app/assets/stylesheets/light-mode.css @@ -0,0 +1,911 @@ +:root { + /* Colors */ + --primary: #49c195; + --secondary: #5e5e5e; + --success: #28a745; + --info: #17a2b8; + --warning: #ffc107; + --danger: #dc3545; + --focus: #007bff; + --alternate: #712cf9; + + /* Borders */ + --primary-border: #349672; + --secondary-border: #d3d3d3; + --success-border: #28a745; + --info-border: #17a2b8; + --warning-border: #ffc107; + --danger-border: #dc3545; + --focus-border: #007bff; + --alternate-border: #8f33b1; + + /* Text */ + --text: #212529; + --text-disabled: #6c757d; + --placeholder-text: #6c757d; + --primary-text: #bf27a3; + --secondary-text:white; + --success-text: #28a745; + --info-text: #17a2b8; + --warning-text: #ca370f; + --danger-text: #14c422; + --focus-text: #007bff; + --alternate-text: #e3872b; + + /* Table */ + --table-border: #dee2e6; + --table-hover: #f8f9fa; + + /* Other */ + --switchery-background: #dee2e6; + --loader-img: #212529; + --form-control-bg: #f8f9fa; + --form-control-border: #ced4da; + --primary-checkbox: #0077cc; + --toggle-light-mode-text: #212529; + --profile-update-detail: #0077cc; +} + +/* Placeholder for input */ +::-webkit-input-placeholder { + /* WebKit, Blink, Edge */ + color: var(--placeholder-text) !important; +} + +:-moz-placeholder { + /* Mozilla Firefox 4 to 18 */ + color: var(--placeholder-text) !important; + opacity: 1; +} + +::-moz-placeholder { + /* Mozilla Firefox 19+ */ + color: var(--placeholder-text) !important; + opacity: 1; +} + +:-ms-input-placeholder { + /* Internet Explorer 10-11 */ + color: var(--placeholder-text) !important; +} + +::-ms-input-placeholder { + /* Microsoft Edge */ + color: var(--placeholder-text) !important; +} + +::placeholder { + /* Most modern browsers support this now. */ + color: var(--placeholder-text) !important; +} + +input { + color: var(--text) !important; + background: var(--form-control-bg); + border: 1px solid var(--form-control-border); +} + +/* Text color */ +body { + color: var(--text); + background:white; +} + +a { + /* TODO: Change link colors */ + color: white !important; +} + +.text-primary { + color: var(--primary-text) !important; +} + +.text-secondary { + color: var(--secondary-text) !important; +} + +.text-alternate { + color: var(--alternate-text) !important; +} + +/* Top Bar */ +.bg-royal { + background-image: linear-gradient(to right, #1b1b1b, #000000) !important; +} + +/* Title-Nav Bar */ +.app-theme-gray .app-header { + background: #030607; + -webkit-box-shadow: -1px 14px 44px -4px rgba(0, 0, 0, 0.65); + -moz-box-shadow: -1px 14px 44px -4px rgba(0, 0, 0, 0.65); + box-shadow: -1px 14px 44px -4px rgba(0, 0, 0, 0.65); +} + +.horizontal-nav-menu>li>a span::before { + background: var(--primary); +} + +.app-theme-gray .app-page-title { + border-bottom: none; +} + +.header-mobile-open { + background: #1a1a1a; + border-color: #151515; +} + +/* IRIS LOGO */ +.app-header__logo { + background: var(--primary); +} + +/* Page Title -- Bread crumb Bar */ +.app-theme-gray .app-page-title { + background: #1a1a1a; +} + +.app-page-title .page-title-wrapper::before { + background: var(--primary); +} + +/* show/hide menu bar */ +.app-theme-gray .app-inner-bar { + background: #262626; + border-bottom: none; +} + +/* menu */ +.dropdown-menu { + background-color: #262626; +} + +.header-mobile-open .horizontal-nav-menu { + background-color: #212121; +} + +.header-mobile-open .horizontal-nav-menu>li { + border-color: #1f1f1f; +} + +/* side bar color */ +.app-inner-layout__sidebar { + background: #1e1e1e !important; + color: white; +} + +.dropdown-item { + color: white; +} + +.dropdown-item:hover, +.dropdown-item:focus { + color: #fff; + background: var(--primary-border); +} + +.dropdown-item.active, +.dropdown-item:active { + color: #fff; + text-decoration: none; + background-color: var(--primary); +} + +.app-inner-layout.app-inner-layout-page .app-inner-layout__wrapper .app-inner-layout__sidebar { + border-right: none; +} + +.app-main__inner { + background: #1a1a1a; +} + +/* content body */ +.app-inner-layout__wrapper { + background: #1a1a1a; +} + +/* HEADER */ + +.header-btn-lg::before { + background: #474747; +} + +.grid-menu [class*="col-"] { + border-right: #474747 solid 0; + border-bottom: #474747 solid 1px; +} + +.nav-item.nav-item-header { + color: var(--secondary-text); +} + +.divider { + background: #474747; +} + +/* When scrolling up to the top, a small bar or 2 appears. Color of bar is this */ +.app-theme-gray.app-container { + background: rgb(26, 26, 26); +} + +/* FOOTER */ +.app-wrapper-footer .app-footer { + border: none; +} + +.app-theme-gray .app-footer { + background: #131313; +} + +.footer-dots .dots-separator { + background: #474747; +} + +.list-group-item { + background-color: transparent; +} + +.border-light { + border-color: #2a2a2a !important; +} + +.widget-numbers { + color: var(--text); +} + +/* FORMS */ + +select { + background-color: #f5f5f5; + border-color: #ddd; + color: #333; +} + +.form-control { + background: #f5f5f5; + border-color: #ddd; + color: #333; +} + +.form-control:focus { + background-color: #eee; + border-color: #66afe9; + color: #333; +} + +.form-control:disabled, +.form-control[readonly] { + background-color: #292929 !important; +} + +.input-group-text { + background-color: #f5f5f5; + border: 1px solid #ddd; + color: #333; +} + +.custom-select { + color: #333; + background-color: #f5f5f5; + border-color: #ddd; +} + +.custom-select:focus { + border-color: #66afe9; + box-shadow: 0 0 0 0.2rem #ccebff; +} + +.custom-control-label::before { + background-color: #f5f5f5; + border-color: #ddd; +} + +.custom-control-input:checked~.custom-control-label::before { + background-color: #66afe9; + border-color: #66afe9; +} + +/* Progress Bar */ + +.progress { + background-color: transparent; +} + +.progress-bar { + background-color: var(--primary); +} + +/* Select2 */ + +.select2-container--bootstrap4 .select2-selection { + background-color: var(--form-control-bg); + border: 1px solid #1a1a1a; + color: white !important; +} + +.select2-container--bootstrap4 .select2-selection--single .select2-selection__rendered { + color: white; + padding: 0; +} + +.select2-container--open .select2-dropdown { + color: #fff; + background-color: #262626; +} + +.select2-container--bootstrap4 .select2-results__option[aria-selected=true] { + background-color: var(--primary); + color: #fff; +} + +.select2-container--bootstrap4 .select2-results__option--highlighted[aria-selected] { + background-color: var(--primary); +} + +.select2-container--bootstrap4 .select2-search--dropdown .select2-search__field { + background-color: var(--form-control-bg); + border-color: #1a1a1a; + color: #fff; +} + +.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice { + background-color: #333131; + border-color: #1a1a1a; + color: #fff; +} + +.select2-container--bootstrap4.select2-container--focus .select2-selection, +.select2-container--bootstrap4.select2-container--open .select2-selection { + border-color: #1a1a1a; +} + +/* Daterangepicker */ + +.daterangepicker { + color: var(--text); +} + +.daterangepicker .calendar-table { + background-color: #262626; + border: #232323; +} + +.daterangepicker td.off, +.daterangepicker td.off.in-range, +.daterangepicker td.off.start-date, +.daterangepicker td.off.end-date { + background-color: #202020; + color: var(--text-disabled); +} + +.daterangepicker td.active, +.daterangepicker td.active:hover { + background-color: var(--primary); +} + +.daterangepicker td.available:hover, +.daterangepicker th.available:hover { + background-color: var(--primary); +} + +.daterangepicker select.hourselect, +.daterangepicker select.minuteselect, +.daterangepicker select.secondselect, +.daterangepicker select.ampmselect { + background-color: var(--form-control-bg); + border-color: var(--form-control-border); +} + +/* FullCalendar */ + +.fc-state-active { + background-color: #464646 !important; + color: #fff !important; +} + +/* Tooltip */ + +.popover-body { + background: #262626; + color: #fff; +} + +.bs-popover-right .arrow::after, +.bs-popover-auto[x-placement^="right"] .arrow::after { + border-right-color: #262626; +} + +.ui-widget.ui-widget-content { + border-color: #232323; +} + +.ui-widget-content { + border-color: #232323; + background: #262626; + color: var(--text); +} + +.ui-widget-shadow { + -webkit-box-shadow: 0px 0px 5px #222; + box-shadow: 0px 0px 5px #222; +} + +/* CARD STYLES */ +.card { + background-color: #f7f7f7; + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); +} + +.card-body { + background: #fff; + color: #333; + position: relative; + display: flex; + flex-direction: column; + min-width: 0; + word-wrap: break-word; + background-clip: border-box; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 0.25rem; +} + +.card-deck { + display: flex; + flex-direction: column; +} + +.card-deck .card { + margin-bottom: 15px; +} + +@media (min-width: 576px) { + .card-deck { + flex-flow: row wrap; + margin-right: -15px; + margin-left: -15px; + } + .card-deck .card { + display: flex; + flex: 1 0 0%; + flex-direction: column; + margin-right: 15px; + margin-bottom: 15px; + margin-left: 15px; + } +} + +.ui-widget-header { + border: 1px solid #ccc; + background: #f7f7f7; + color: #333; + font-weight: bold; +} + +.card-header { + background: #f7f7f7 !important; + color: #333; +} + +.card-header>.nav .nav-link.active { + color: var(--primary); +} + +.card-footer { + background: #f7f7f7 !important; + color: #333; +} + +.card-title { + color: rgb(0, 0, 0); +} + +.card-subtitle { + color: var(--secondary-text); +} + +.card:hover { + transform: scale(1.015); + transition: all 0.25s ease; + } + + +/* MODAL STYLES */ + +.modal-body { + background: #2d2d2d; + color: white; +} + +.modal-content { + background-color: #2d2d2d; + border: none; +} + +.modal-header { + background: #262626 !important; + border-bottom: 1px solid #1f1f1f; + color: white; +} + +.modal-footer { + background: #262626 !important; + border-top: 1px solid #1f1f1f; + color: white; +} + +.modal-dialog { + box-shadow: 0 0.76875rem 2.4875rem rgb(20 20 20 / 30%), 0 1.3375rem 1.70625rem rgb(20 20 20 / 30%), 0 0.55rem 0.53125rem rgb(0 0 0 / 5%), 0 0.225rem 0.4375rem rgb(20 20 20 / 30%); + border-radius: 0.25rem; +} + +.card-title { + color: rgb(22, 22, 22); + text-align: center; +} + +.card-subtitle { + color: rgb(111, 118, 219); +} + + +/* BUTTON STYLES */ + +.btn { + color: white; +} + +.btn-light { + background-color: #2f2f2f; + border-color: #242424; +} + +.btn-light.btn-shadow:hover { + box-shadow: 0 0.125rem 0.625rem #262626, 0 0.0625rem 0.125rem #262626; +} + +.btn-light:hover, +.btn-light:focus, +.btn-light:active { + background-color: #363636; + border-color: #1c1c1c; + color: #fff; +} + +.btn-light.btn-shadow { + box-shadow: 0 0.125rem 0.625rem #262626, 0 0.0625rem 0.125rem #262626; +} + +.btn-primary { + background-color: var(--primary); + border-color: var(--primary-border); +} + +.btn-primary:hover { + background-color: var(--primary-border); + border-color: var(--primary); +} + +.btn-secondary { + background-color: var(--secondary); + border-color: var(--secondary-border); +} + +.btn-success { + background-color: var(--success); + border-color: var(--success-border); +} + +.btn-info { + background-color: var(--info); + border-color: var(--info-border); +} + +.btn-warning { + background-color: var(--warning); + border-color: var(--warning-border); +} + +.btn-danger { + background-color: var(--danger); + border-color: var(--danger-border); +} + +.btn-focus { + background-color: var(--focus); + border-color: var(--focus-border); +} + +.btn-alternate { + background-color: var(--alternate); + border-color: var(--alternate-border); +} + +.btn-new { + background-color: #712cf9; + +} + +.btn-outline-primary { + border-color: var(--primary-border); +} + +.btn-outline-secondary { + border-color: var(--secondary-border); +} + +.btn-outline-success { + border-color: var(--success-border); +} + +.btn-outline-info { + border-color: var(--info-border); +} + +.btn-outline-warning { + border-color: var(--warning-border); +} + +.btn-outline-danger { + border-color: var(--danger-border); +} + + + +/* Bootstrap Alerts */ + +.alert { + color: #ffffff !important; +} + +.alert-primary { + background-color: var(--primary); + border-color: var(--primary-border); +} + +.alert-success { + background-color: var(--success); + border-color: var(--success-border); +} + +.alert-info { + background-color: var(--info); + border-color: var(--info-border); +} + +.alert-warning { + background-color: var(--warning); + border-color: var(--warning-border); +} + +.alert-danger { + color: #fff; + background-color: var(--danger); + border-color: var(--danger-border); +} + +.close { + color: #fff; +} + +.close:hover { + color: inherit; +} + +/* bootstrap backgrounds */ + + +.bg-primary { + background-color: var(--primary) !important; +} + +.bg-secondary { + background-color: var(--secondary) !important; +} + +.bg-success { + background-color: var(--success) !important; +} + +.bg-info { + background-color: var(--info) !important; +} + +.bg-warning { + background-color: var(--warning) !important; +} + +.bg-danger { + background-color: var(--danger) !important; +} + +.bg-focus { + background-color: var(--focus) !important; +} + +.bg-alternate { + background-color: var(--alternate) !important; +} + +/* Bootstrap Badges */ + +.badge-primary { + background-color: var(--primary); +} + +.badge-secondary { + background-color: var(--secondary); +} + +.badge-info { + background-color: var(--info); +} + +.badge-success { + background-color: var(--success); +} + +.badge-warning { + background-color: var(--warning); +} + +.badge-danger { + background-color: var(--danger); +} + +/* TABLE */ + +tr { + border-color: var(--table-border); +} + +.table thead th { + vertical-align: bottom; + border-color: var(--table-border); + background: #1f1f1f; +} + +.table tbody tr { + background: #242424; +} + +.table-bordered th, +.table-bordered td { + border-color: var(--table-border); +} + +.table-striped tbody tr:nth-child(odd) { + background-color: #212121 !important; +} + +.table { + border-color: var(--table-border); +} + +.table-hover tbody tr:hover { + background-color: var(--table-hover) !important; +} + +.table-primary { + background-color: var(--primary); +} + +.table-primary:hover { + background-color: var(--primary-border) !important; +} + +.table th, +.table td { + border-color: var(--table-border); +} + +/* Datatable */ + +/* pagination buttons (selected) */ +.pagination li a { + color: var(--primary); + background-color: #383838; + border: 1px solid #262626; +} + +/*other pagination buttons*/ +.page-item.disabled .page-link, +.pagination .disabled.page-number .page-link { + color: var(--text-disabled) !important; + background-color: #383838; + border-color: #262626; +} + +.pagination li a:hover { + background-color: #555555; + border-color: #262626; +} + +.pagination li.disabled a { + background-color: #383838; + border-color: #262626; +} + +.page-item.active .page-link, +.pagination .active.page-number .page-link { + background-color: var(--primary); + border-color: var(--primary-border); +} + +/* Copy button */ +div.dt-button-info { + background-color: #212121 !important; + border-color: #111 !important; + box-shadow: 3px 3px 8px rgba(0, 0, 0, 0.3); +} + +div.dt-button-info h2 { + border-color: #1a1a1a !important; + background-color: #262626 !important; +} + +/* Dashboard Buttons */ + +/* TODO: Add transparent background dashboard images before uncommenting */ +/*.option_buttons {*/ +/* border-color: #444 !important;*/ +/*}*/ + +/*.button-label {*/ +/* color: var(--text) !important;*/ +/*}*/ + +/*DARK MODE TOGGLE */ +.toggle-link, +.toggle-link:active, +.toggle-link:focus { + color: #fff; +} + +/* Miscalleneous */ + +.tabs-animated .nav-link::before { + background-color: var(--primary); +} + +.tabs-animated-shadow .nav-link::before { + box-shadow: 0 16px 26px -10px var(--primary-border), 0 4px 25px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(31, 36, 64, 0.2); +} + +.font-icon-wrapper { + border-color: var(--table-border); +} + +.font-icon-wrapper:hover { + color: transparent; +} + + +.toggle-handle, +.toggle-handle:hover { + background-color: var(--switchery-background); +} + +/* jQuery TagsInput */ +[data-theme="dark"] div.tagsinput { + border: 1px solid var(--form-control-border) !important; + background: var(--form-control-bg) !important; + padding: 5px; + width: 300px; + height: 100px; + overflow-y: auto; +} + +[data-theme="dark"] div.tagsinput span.tag { + border: 1px solid #a5d24a; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + display: block; + float: left; + padding: 5px; + text-decoration: none; + background: #a0db2d !important; + color: #341 !important; + margin-right: 5px; + margin-bottom: 5px; + font-family: helvetica; + font-size: 13px; +} \ No newline at end of file diff --git a/week_5/activity-tracker/app/controllers/activities_controller.rb b/week_5/activity-tracker/app/controllers/activities_controller.rb index a1dc90c1..c0a107ea 100644 --- a/week_5/activity-tracker/app/controllers/activities_controller.rb +++ b/week_5/activity-tracker/app/controllers/activities_controller.rb @@ -3,13 +3,45 @@ class ActivitiesController < ApplicationController # GET /activities or /activities.json def index - @activities = Activity.all + @activities=Activity.where(user_id: current_user.id) end # GET /activities/1 or /activities/1.json def show end + def stats + @total_duration = Activity.where(user_id: current_user.id).sum(:duration) + @total_calories = Activity.where(user_id: current_user.id).sum(:calories) + end + + def pdf + require "prawn" + pdf1 = Prawn::Document.new + pdf1.text current_user.email,align: :center ,size: 30,style: :bold + pdf1.text "\nActivities\n\n",align: :center ,size: 25,style: :bold + @activities=Activity.where(user_id: current_user.id) + if @activities.any? + @activities.each do |activity| + pdf1.text "Activity Title : #{activity.title}",size: 20,style: :bold + act_img=StringIO.open(activity.image.download) + pdf1.image act_img,fit: [300,300] + pdf1.text "Activity Type : #{activity.activity_type}",size: 15 + pdf1.text "Activity Duration : #{activity.duration}",size: 15, inline_format: true + pdf1.text "Calories Burnt : #{activity.calories}",size: 15, inline_format: true + pdf1.start_new_page + end + else + pdf1.text "No Activity",size: 20,style: :bold + end + + pdf1.text "User Total Statistics\n\n",align: :center ,size: 25,style: :bold + stats + pdf1.text "Total Duration : #{@total_duration}",size: 20,align: :center, inline_format: true + pdf1.text "Calories Burnt : #{@total_calories}",size: 20,align: :center, inline_format: true + send_data(pdf1.render,filename: "#{current_user.email}.pdf",type: 'application/pdf' , disposition: 'inline') + end + # GET /activities/new def new @activity = Activity.new @@ -22,10 +54,10 @@ def edit # POST /activities or /activities.json def create @activity = Activity.new(activity_params) - + @activity.user_id=current_user.id respond_to do |format| if @activity.save - format.html { redirect_to activity_url(@activity), notice: "Activity was successfully created." } + format.html { redirect_to activities_url, notice: "Activity was successfully created." } format.json { render :show, status: :created, location: @activity } else format.html { render :new, status: :unprocessable_entity } @@ -52,7 +84,7 @@ def destroy @activity.destroy respond_to do |format| - format.html { redirect_to activities_url, notice: "Activity was successfully destroyed." } + format.html { redirect_to activities_url,status: :see_other, notice: "Activity was successfully destroyed." } format.json { head :no_content } end end @@ -65,6 +97,6 @@ def set_activity # Only allow a list of trusted parameters through. def activity_params - params.require(:activity).permit(:title, :activity_type, :start, :duration, :calories) + params.require(:activity).permit(:title, :activity_type, :start, :duration, :calories, :image) end end diff --git a/week_5/activity-tracker/app/controllers/application_controller.rb b/week_5/activity-tracker/app/controllers/application_controller.rb index 09705d12..6b4dcfa8 100644 --- a/week_5/activity-tracker/app/controllers/application_controller.rb +++ b/week_5/activity-tracker/app/controllers/application_controller.rb @@ -1,2 +1,3 @@ class ApplicationController < ActionController::Base + before_action :authenticate_user! end diff --git a/week_5/activity-tracker/app/controllers/static_pages_controller.rb b/week_5/activity-tracker/app/controllers/static_pages_controller.rb new file mode 100644 index 00000000..487a0e3f --- /dev/null +++ b/week_5/activity-tracker/app/controllers/static_pages_controller.rb @@ -0,0 +1,8 @@ +class StaticPagesController < ApplicationController + skip_before_action :authenticate_user!, only: %i[index] + def index + end + + def about + end +end diff --git a/week_5/activity-tracker/app/controllers/users/confirmations_controller.rb b/week_5/activity-tracker/app/controllers/users/confirmations_controller.rb new file mode 100644 index 00000000..fa535c0a --- /dev/null +++ b/week_5/activity-tracker/app/controllers/users/confirmations_controller.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class Users::ConfirmationsController < Devise::ConfirmationsController + # GET /resource/confirmation/new + # def new + # super + # end + + # POST /resource/confirmation + # def create + # super + # end + + # GET /resource/confirmation?confirmation_token=abcdef + # def show + # super + # end + + # protected + + # The path used after resending confirmation instructions. + # def after_resending_confirmation_instructions_path_for(resource_name) + # super(resource_name) + # end + + # The path used after confirmation. + # def after_confirmation_path_for(resource_name, resource) + # super(resource_name, resource) + # end +end diff --git a/week_5/activity-tracker/app/controllers/users/omniauth_callbacks_controller.rb b/week_5/activity-tracker/app/controllers/users/omniauth_callbacks_controller.rb new file mode 100644 index 00000000..593f547d --- /dev/null +++ b/week_5/activity-tracker/app/controllers/users/omniauth_callbacks_controller.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController + # You should configure your model like this: + # devise :omniauthable, omniauth_providers: [:twitter] + + # You should also create an action method in this controller like this: + # def twitter + # end + + # More info at: + # https://github.com/heartcombo/devise#omniauth + + # GET|POST /resource/auth/twitter + # def passthru + # super + # end + + # GET|POST /users/auth/twitter/callback + # def failure + # super + # end + + # protected + + # The path used when OmniAuth fails + # def after_omniauth_failure_path_for(scope) + # super(scope) + # end +end diff --git a/week_5/activity-tracker/app/controllers/users/passwords_controller.rb b/week_5/activity-tracker/app/controllers/users/passwords_controller.rb new file mode 100644 index 00000000..259dbb08 --- /dev/null +++ b/week_5/activity-tracker/app/controllers/users/passwords_controller.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +class Users::PasswordsController < Devise::PasswordsController + # GET /resource/password/new + # def new + # super + # end + + # POST /resource/password + # def create + # super + # end + + # GET /resource/password/edit?reset_password_token=abcdef + # def edit + # super + # end + + # PUT /resource/password + # def update + # super + # end + + # protected + + # def after_resetting_password_path_for(resource) + # super(resource) + # end + + # The path used after sending reset password instructions + # def after_sending_reset_password_instructions_path_for(resource_name) + # super(resource_name) + # end +end diff --git a/week_5/activity-tracker/app/controllers/users/registrations_controller.rb b/week_5/activity-tracker/app/controllers/users/registrations_controller.rb new file mode 100644 index 00000000..b9e664fe --- /dev/null +++ b/week_5/activity-tracker/app/controllers/users/registrations_controller.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +class Users::RegistrationsController < Devise::RegistrationsController + # before_action :configure_sign_up_params, only: [:create] + # before_action :configure_account_update_params, only: [:update] + + # GET /resource/sign_up + # def new + # super + # end + + # POST /resource + # def create + # super + # end + + # GET /resource/edit + # def edit + # super + # end + + # PUT /resource + # def update + # super + # end + + # DELETE /resource + # def destroy + # super + # end + + # GET /resource/cancel + # Forces the session data which is usually expired after sign + # in to be expired now. This is useful if the user wants to + # cancel oauth signing in/up in the middle of the process, + # removing all OAuth session data. + # def cancel + # super + # end + + # protected + + # If you have extra params to permit, append them to the sanitizer. + # def configure_sign_up_params + # devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute]) + # end + + # If you have extra params to permit, append them to the sanitizer. + # def configure_account_update_params + # devise_parameter_sanitizer.permit(:account_update, keys: [:attribute]) + # end + + # The path used after sign up. + # def after_sign_up_path_for(resource) + # super(resource) + # end + + # The path used after sign up for inactive accounts. + # def after_inactive_sign_up_path_for(resource) + # super(resource) + # end +end diff --git a/week_5/activity-tracker/app/controllers/users/sessions_controller.rb b/week_5/activity-tracker/app/controllers/users/sessions_controller.rb new file mode 100644 index 00000000..a0f9b48e --- /dev/null +++ b/week_5/activity-tracker/app/controllers/users/sessions_controller.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +class Users::SessionsController < Devise::SessionsController + # before_action :configure_sign_in_params, only: [:create] + + # GET /resource/sign_in + # def new + # super + # end + + # POST /resource/sign_in + # def create + # super + # end + + # DELETE /resource/sign_out + # def destroy + # super + # end + + # protected + + # If you have extra params to permit, append them to the sanitizer. + # def configure_sign_in_params + # devise_parameter_sanitizer.permit(:sign_in, keys: [:attribute]) + # end +end diff --git a/week_5/activity-tracker/app/controllers/users/unlocks_controller.rb b/week_5/activity-tracker/app/controllers/users/unlocks_controller.rb new file mode 100644 index 00000000..2c410dc0 --- /dev/null +++ b/week_5/activity-tracker/app/controllers/users/unlocks_controller.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class Users::UnlocksController < Devise::UnlocksController + # GET /resource/unlock/new + # def new + # super + # end + + # POST /resource/unlock + # def create + # super + # end + + # GET /resource/unlock?unlock_token=abcdef + # def show + # super + # end + + # protected + + # The path used after sending unlock password instructions + # def after_sending_unlock_instructions_path_for(resource) + # super(resource) + # end + + # The path used after unlocking the resource + # def after_unlock_path_for(resource) + # super(resource) + # end +end diff --git a/week_5/activity-tracker/app/helpers/activities_helper.rb b/week_5/activity-tracker/app/helpers/activities_helper.rb index 4e9784cc..08e9a699 100644 --- a/week_5/activity-tracker/app/helpers/activities_helper.rb +++ b/week_5/activity-tracker/app/helpers/activities_helper.rb @@ -1,2 +1,8 @@ module ActivitiesHelper + def flash_class(level) + case level + when :notice then 'alert alert-success' + when :alert then 'alert alert-danger' + end + end end diff --git a/week_5/activity-tracker/app/helpers/static_pages_helper.rb b/week_5/activity-tracker/app/helpers/static_pages_helper.rb new file mode 100644 index 00000000..2d63e79e --- /dev/null +++ b/week_5/activity-tracker/app/helpers/static_pages_helper.rb @@ -0,0 +1,2 @@ +module StaticPagesHelper +end diff --git a/week_5/activity-tracker/app/models/activity.rb b/week_5/activity-tracker/app/models/activity.rb index a99f990d..ff7c92e2 100644 --- a/week_5/activity-tracker/app/models/activity.rb +++ b/week_5/activity-tracker/app/models/activity.rb @@ -1,2 +1,5 @@ class Activity < ApplicationRecord + belongs_to :user + validates :calories, numericality: { only_integer: true } + has_one_attached :image end diff --git a/week_5/activity-tracker/app/models/type.rb b/week_5/activity-tracker/app/models/type.rb new file mode 100644 index 00000000..e17f3568 --- /dev/null +++ b/week_5/activity-tracker/app/models/type.rb @@ -0,0 +1,2 @@ +class Type < ApplicationRecord +end diff --git a/week_5/activity-tracker/app/models/user.rb b/week_5/activity-tracker/app/models/user.rb new file mode 100644 index 00000000..4cf0bb9a --- /dev/null +++ b/week_5/activity-tracker/app/models/user.rb @@ -0,0 +1,8 @@ +class User < ApplicationRecord + # Include default devise modules. Others available are: + # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable + devise :database_authenticatable, :registerable, + :recoverable, :rememberable, :validatable + + has_many :activities +end diff --git a/week_5/activity-tracker/app/views/activities/_activity.html.erb b/week_5/activity-tracker/app/views/activities/_activity.html.erb index aab462e3..14fb4b53 100644 --- a/week_5/activity-tracker/app/views/activities/_activity.html.erb +++ b/week_5/activity-tracker/app/views/activities/_activity.html.erb @@ -1,27 +1,39 @@ -
- Title: - <%= activity.title %> -
- -- Activity type: - <%= activity.activity_type %> -
- -- Start: - <%= activity.start %> -
- -- Duration: - <%= activity.duration %> -
- -- Calories: - <%= activity.calories %> -
+<%= notice %>
+<% if notice %> +- <%= link_to "Show this activity", activity %> -
+<%= notice %>
<%= render @activity %> - -+