Code Monkey home page Code Monkey logo

muncie-events-api's People

Contributors

dependabot[bot] avatar phantomwatson avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

efueger

muncie-events-api's Issues

Add ?withoutTags[] parameter

  • Add an optional parameter to all /v1/events endpoints that allows events with specified tags to be excluded from results.
  • Throw error if a tag is in both the withTags[] and withoutTags[] array

Help Google crawl event data

Search Console has detected that your site contains event information that would benefit from enhanced Google Search results. Google Search supports an Event rich result that provides a richer user experience for events in search results, including event date, time, description, and ticketing information.

Enabling Event rich results on your site is free, and requires only the proper structured data on your website. Early adopters who have implemented Event rich results have boosted site traffic significantly (read a case study).

This events feature experience will be coming to your market soon!

https://developers.google.com/search/docs/data-types/event

Use UTC time fields

Once the CakePHP 3 version of Muncie Events is online and time fields that store UTC time are implemented, the API should read from those fields instead of time_start and time_end, which store non-UTC time without any offset information.

Inject HTML into descriptions

The Muncie Events app does not (currently) add markup to the Events.description field, most notably resulting in line breaks not turning into <br /> tags.

Proposal

If the description field

  • has no HTML tags
  • and has line breaks,
    the API should run that string through nl2br() before saving it.

JSON view not used for errors in initialize()

The exceptions thrown in ApiController::initialize() (for incorrect protocol or invalid/missing API key) render HTML error pages instead of JSON error responses.

Once this is fixed, there should be tests written to assert proper error responses.

Make some endpoints public (stop requiring API key)

The Problem

I'd like to use all of the endpoints of the API to replace redundant backend processing on the main site and redesign it to be more asynchronous. But with all endpoints requiring an API key, that would require either

  • exposing an API key to the public
  • setting up an exception to requiring an API key, like checking for a (spoofable) muncieevents.com referer.

The Solution

  • For all endpoints that correspond to stuff that anonymous users can do on the main site, stop requiring an API key
  • Add tests that assert that API keys are / are not required for each endpoint
  • Give all users their own API key and userToken
  • Use the logged-in user's API key for all access-restricted endpoints
  • Don't bother logging API requests made without API keys (regardless of endpoint)

Accept camel-cased 'apiKey' query string parameter

Currently, the apikey query string parameter is the only multi-word parameter that isn't camel-cased.

  • For backwards-compatibility, continue accepting apikey
  • Start accepting apiKey
  • Only refer to apiKey in the docs

Overhaul edit event series page

  • Asynchronously update event series title
  • Asynchronously update individual event details
  • Asynchronously delete individual events
  • Allow end times to be updated
  • Style events that have already passed differently

Fix mobile usability issues

Google Search console reports this:

Search Console has identified that your site is affected by 3 Mobile Usability issues:
Top Issues
The following issues were found on your site:

  • Text too small to read
  • Clickable elements too close together
  • Viewport not set

Overhaul event accordion pagination

Why it was removed

Event accordion pagination is currently by date range, with the first page starting today and ending at some specified time like two weeks in the future. If the first event in a given category is outside of that range (e.g. three weeks in the future), that category page will first be empty, and the user will have to click 'More events' to see that first event.
Removing pagination from pages other than the front page was an easy solution that seems like it won't result in huge, cumbersome pages for users to load while the numbers of upcoming events are relatively low.

New Pagination Strategy

  • Each page has a minimum number of events, but includes all events in the last date instead of cutting that date off once the minimum is reached
  • So the count of events per day in the future might be collected first, then the query is built that fetches all events in a date range that will meet that minimum

Implementation

  • A EventsTable::findPaginatedStartingOn() method would work (but would oddly have a DB call inside that finder)
  • All pages that use the event accordion would implement this, with some high event minimum like 50

Audit stylesheets

I think that a lot of style rules refer to elements that aren't used in the site anymore. Each selector should be audited, and ones that don't apply to anything anymore should have their rules removed.

Set up user token system

Strategy

  • GET /users/login should accept an email and password and, if they match, return user id, name, email, and token (generating Users.token if it is null)
  • API endpoints that add or edit records should require a userToken parameter

Suggestion for student development team:

  • Have login page send a request to /users/login and store the token that's returned
  • Include userToken in any requests that require it
  • Have the application's logout function simply forget the user information without sending any requests (since the Muncie Events server won't have an actual user session to terminate)

Create locations table

  • Create a locations table with name and address fields
  • Use this table for auto-completing location names
  • Use this table when auto-completing addresses for known locations

Arguments for alternate ways to handle fields in events table

Keep location field

  • Less code needs to be changed

Remove location field

  • Searching for events at a given location by using location <-> event associations might be faster than searching by matching strings in location field
  • It would be easier to mass-edit location names if a venue changes its name (but should old events still use the then-current name of that venue?)

Keep address field

  • Less code needs to be changed in the site and the API
  • Variations for addresses are allowed, in case there's ever a "suite B" edge case
  • Removing the events.address field would mean that either
    • the address can only be inputted when an unrecognized (new) location is being used and is otherwise displayed but disabled (which would be complicated and may confuse users)
    • the address input field is always enabled, allowing any user to update the location's address (potentially wreaking havoc)
    • the address input field is always enabled, but a complicated system of moderating address update suggestions is implemented (doesn't seem to be worth going to all of this trouble)

Remove address field

  • Addresses for location names (pulled from $event->location->address) are all uniform and can be more efficiently corrected

Add endpoint for getting addresses

Add a public endpoint such as GET /address that takes a locationName input and outputs the most recent address associated with that location. In the future, this could be upgraded to use the Google Maps API to determine the canonical address for a location.

// Controller code
    /**
     * Returns the address most recently associated with the provided location name
     *
     * @return void
     */
    public function getAddress()
    {
        $location = (string)$this->request->getData('location');
        $address = $location ? $this->Events->getAddress($location) : false;
        $this->viewBuilder()->setClassName('Json');
        $this->set([
            'address' => $address,
            '_serialize' => ['address']
        ]);
    }

// Table code
    /**
     * Returns the most recently published address for the provided location name or FALSE if none is found
     *
     * @param string|null $location Location name
     * @return string|boolean
     */
    public function getAddress($location)
    {
        if (!$location) {
            return false;
        }

        /** @var Event|null $result */
        $result = $this->find()
            ->select(['Events.address'])
            ->where([
                'Events.published' => true,
                'Events.location' => $location,
                'Events.address NOT' => ''
            ])
            ->orderDesc('Events.created')
            ->first();

        return $result ? $result->address : false;
    }

Charts

Perhaps a fun addition to the 'about' page:

Events Posted (line graph)

  • Number of events submitted (by created field)
  • Number of events taking place (by date field)

Anonymous Posts (line graph)

  • Number of events submitted anonymously
  • Number of events submitted by users with accounts

User Activity (line graph)

  • Number of new user accounts
  • Number of user accounts submitting events

Event Totals (line graph)

  • Total number of all events
  • Total number of events in each category

User Totals (line graph)

  • Total number of user accounts
  • Total number of users who have submitted events

Event Stats (bar charts)

  • Hours of the day, sized by how many events start during that hour
  • Days of the week, sized by how many events start during that day

Tweaks to links in API results / docs

  • /categories results need a $category['links']['events'] value (i.e. /v1/events/category/{categoryId})
  • All $foo['links'] results need to be documented (if intended) or removed from results (if not)
  • 'self' link is documented, but not in results (at least not in /event/{eventID} results)
  • Unneeded pagination links in /event endpoint need removed

Use new_subscriber flag in MailingList

  • Set $subscription->new_subscriber to false if true when sending messages
  • Add a message for new subscribers if new_subscriber is true

Welcome to the Muncie Events mailing list. If you did not mean to subscribe, you can click here to unsubscribe. Your subscription is currently configured to email you every [description of frequency] about upcoming [description of selected categories]. If you would ever like to change this, just click the change settings link at the bottom of any message.

Add example image URLs to docs

Because it's weird that some values have proper examples, and others are just "string".

  • Add example image URLs
  • Add example event URLs

Add second semester endpoints

Endpoints for anonymous users:

  • POST /user/login
  • POST /user/register
  • GET /user/{userId} (returns name and email address)
  • GET /user/{userId}/events
  • GET /event-series/{eventSeriesId}
  • POST /user/forgot-password
  • POST /event

Requires userToken in query string:

  • PATCH /user/profile
  • PATCH /user/password
  • GET /user/images
  • POST /image
  • PATCH /event/{eventId}

Restrict allowed methods

  • Set $this->request->allowMethod('get') in all GET endpoints
  • Add 'method not allowed' errors to docs
  • Add tests
  • Ensure that all endpoints respond with errors if incorrect request methods are used

Add more endpoints

  • DELETE /event/{eventId}
  • DELETE /event-series/{seriesId}
  • Add 'register for mailing list' optional boolean param to /user/register
  • POST /mailing-list/subscribe (optional userToken)
  • GET /mailing-list/subscription (requires userToken)
  • PUT /mailing-list/subscription (requires userToken)
  • DELETE /mailing-list/subscription (requires userToken)
  • GET /tags/autocomplete

Simplest implementation of the mailing list:

  • Users must be logged in to interact with the mailing list table
  • Email is not provided as a parameter, but pulled from the current user's Users.email (so users are no longer able to have different Users.email and MailingList.email values)
  • Users.mailing_list_id gets set for the current user when creating a new record in the MailingList table
  • Users.mailing_list_id gets set for the current user if it's currently null and the user is
    • registering but using an email address already in the MailingList table
    • updating their existing registration

More user-accommodating implementation:

  • Users do not need to be logged in to subscribe
  • Email addresses for new subscriptions matching existing users result in Users.mailing_list_id being set
  • Any new subscriptions with user token provided also result in Users.mailing_list_id being set, even if the email address doesn't match
  • User needs to be logged in and associated with a subscription in order to update it

Allow API access to be canceled

Provide a means for users to cancel their API access (null their API key). Mainly in case we start emailing API users and someone wants to mark themselves as not an API user anymore to effectively unsubscribe from those emails.

Combine API and main site codebases

If the Muncie Events website were to be upgraded to CakePHP 3 or 4 in a separate codebase from the API, that would necessitate a lot of redundant code, especially in the model layer. Ideally, these codebases will be combined into a single application, with the API endpoints being routed through the api. subdomain.

Update favicon

Change the favicon from the CakePHP default to the same one used by the main Muncie Events site.

Update about page

  • The "principles" list is probably unnecessary
  • Add React Native to software credits
  • Add mobile app development team to people credits
  • Add a note about how many events have "currently" been collected, since when, and by how many people

Throw graceful error for malformed time or date strings

Throw graceful errors for

  • Date strings that aren't in YYYY-MM-DD format
  • Date strings that are out of bounds (too far in past or future, or describing days that don't exist)
  • Time strings that fail being translated to FrozenTime objects

Allow auto-linking of URLs to be toggled

In fields that may contain email addresses and URLs (e.g. description and source), add an autolink field that can optionally be included in the request that specifies whether those should be automatically wrapped with links in the response. Note in the API what the default behavior is in the absence of this field.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.