Deprecated. Visit the Mark II repository for the successor to this project.
OneMark is a responsive, image-based bookmark organizer featuring a gallery view, comprehensive search engine, and tagging system.
-
Make sure to install the Add-On extension for Chrome to automatically generate bookmarks with URL, title, and screenshot in 1 click.
-
Check out demo videos on my portfolio!
- Final changelog update. OneMark will continue to be updated in my free time for personal use; however, I will no longer be documenting development.
- Fixed infinite loop in bookmark creator modal caused by
TagInput
component receiving a non-primitive default value (empty array []) for theinitValue
prop after refactoring to Hooks in (Version 2.11) - Updated
Tabs
component to conditionally use theSideScroller
component for horizontal scrolling in row mode - Moved
AlertButton
component intoAlert
component
- Completed refactoring to React Hooks
- Added
utils/hooks.js
for common custom hooks - Added
components/articles/link.jsx
to handle opening links in new tabs with proper referrer attributes - Minor SCSS updates
- Redesigned login page
- Started refactoring components to React Hooks
- Fixed old warnings / bugs relating to deprecation
- Fixed certain valid URLs being rejected due to weak RegEx
- Updated SCSS structuring and some design elements
- Updated
TagInput
to clear input field after adding / deleting entered tag - Fixed bookmark advanced search algorithim not properly forming regexes and conditionals when toggling
"Match all terms"
option- Added
compareLogic
utility function to facilitate conditional generation of logical operators - Reorganized and reformatted code for greater clarity
- Added
- Fixed redux store not properly resetting when switching from one account to another within the same browser session
- Fixed issue with lazy-loading algorithim preventing client-side updates to bookmark images after they've been modified
- Fixed
ImageInput
not actually clearing when clicking "Remove Image" despite visually seeming to- File input now controlled via
ref
- File input now controlled via
- Fixed and simplified
No-Image
detection- Replaced filename stored in database with simple string
"none"
- Replaced regex test with simple string comparison
- Replaced filename stored in database with simple string
- Removed autocompletion from forms
- Moved
client/src/views
folder toclient/src/components
- Miscellaneous code cleanup and optimizations
- Fixed searchbar-induced crash by escaping individual terms
- Refactored import and export patterns
- Added
Banner
component to display across the bottom of the screen - Added banner prompting to install the add-on Chrome extension on first visit to homepage
- Hidden permanently (via localStorage) after clicking the link to the extension page or the banner close button
- Added "No bookmarks found" display when the bookmark container is empty
- Converted several raster images to vectors for improved scaling and reduced media footprint
- Updates to SCSS color usage and naming schema
- Fixed
undefined
being returned by the server when no bookmarks are found on homepage load
- Added 'Delete' action to multi-select bar
- Added 'Alert' component
- Improved SASS variable system
- Added classes for text and background color for each new color variable
- Further refactoring / code cleanup
- Abstracted react components further and restructured files and folders
- Converted multiple class components to functional components
- Further code improvements in redux files
- Updated imports and exports to remove extensions for easier future development
- Fixed bookmark search issue involving negated terms
- Fixed scrolling behavior on Privacy Policy page
- Fixed document title behavior
- Fixed minor issues in CSS
- Fixed miscellaneous code styling inconsistencies
- Removed unused images
- Added multi-select functionality to bookmarks
- A checkbox will now appear on hovering over the top-left of a bookmark
- Clicking the checkbox will bring up the multi-select bar at the bottom of the screen
- Updated checkbox component to support additional functionality and prevent click-through behavior
- Current options are "Edit Tags", which will bring up the new multi-tag editor ("tagger") and "Unselect All"
- A checkbox will now appear on hovering over the top-left of a bookmark
- Abstracted error handling on server and fixed existing related helper functions
- Added new utility functions for client and server
- Minor fixes to SCSS classes
- Minor reorganization of reducer and action files for clarity
- Fixed date-related inconsistencies between client and server
- Fixed duplicate toasts on bookmark creation
- Fixed missing image size data after editing bookmark
- Added custom 404 page
- Fixed controlled inputs jumping to end of line on input
- Re-added ability to open bookmark on middle-click / scroll-wheel click
- Official release of the React (Create-React-App) / Node (Express) edition of OneMark. See the OneMark-Original-Public repository for the original version of OneMark (last revision 1.02) built using vanilla HTML5, CSS3, JavaScript, and PHP. The existing changelog has been appended below for consolidated reference.
- Toast system changed to use the React-Toastify library
- InlineMessage functionality replaced with toasts
- Removed debouncing on searchbar due to complexity of integration with React (the debounce function of Lodash works more seamlessly; however, the additional footprint of the library is not worth this sole purpose)
- Fixed incomplete query in
updateProfile(...)
indb-functions.php
causing updates to all rows
- Compressed repetitive variable assignment in
searchBookmarks()
even further using destructuring and mapping - Fixed typo in function call on register page throwing fatal error
- Restructured global objects and references
- Redesigned various UI elements
- Homepage changed to dark mode (light mode will return as an alternative at a later date)
- Modals updated with cleaner designs
- Transparent input style with animated label moved from default styling on inputs to its own classes (currently no longer used on homepage, only on login page)
- 'Upload Image' button on bookmark create / edit modals now changes to 'Remove Image' if an image is uploaded or already exists
- Removed 'Remove Image' button
- Bookmark edit modal now checks if the bookmark has an image and updates the 'Upload Image' button on modal open
- Button now takes up full available space at all viewport dimensions
- Removed
fileUpload()
andremoveUpload()
and restructured functionality intouploadFile()
andupdateFileInput()
- Bookmark create / edit modals now convert from a row structure to a column structure on mobile
- Bookmarks now have a minimal semi-transparent black border to better differentiate between bookmarks with similar images
- Changed bookmark outer and title elements from
div
tofigure
andfigcaption
elements for improved semantics - Changed buttons using
a
tags on 'login' / 'register' tospan
tags for improved semantics
- Fixed issues resulting from incorrect ordering on some
querySelectorAll
destructuring combinations - Updated 'Account' modal with ability to change username and email
- Added supporting functionality to
update-profile.php
(formerlyupdate-pass.php
) anddb-functions.php
to change username, email, or password - Changed
updatePassword()
toupdateProfile()
inhome.js
and merged former functionality with new username and email functionality - Updated
modalAccount()
inhome.js
to only callphp/account-info.php
and store it in the global object if it's not already stored, which reduces needless server calls every time the modal is opened
- Added supporting functionality to
- Overhauled bookmark search
- Added 'Advanced Search' dropdown UI
- Can add terms in the form of [Anything || Title || URL || Tag] + [contains || does not contain]
- Match words in either AND or OR form
- Match partial words or whole words only
- Collapses to column view on mobile
- Added
addSearchTerm()
tohome.js
to add terms to searchbar and then callsearchBookmarks()
- Updated
searchBookmarks()
- revised regular expression creation and testing to allow for negated searches and more complex combinations
- Added 'Advanced Search' dropdown UI
- Merged
hideTags(...)
andshowTags(...)
intodisplayTags(...)
inhome.js
- Added
emptyContainer(...)
tocommon.js
for emptying container elements of their children - Added
closeMenu(...)
tocommon.js
to close a specific menu - Added
selectDropdown()
tocommon.js
to support custom-styled dropdown menus (replacement forselect
andoption
html tags) - Renamed
printDate(...)
toformatDate(...)
incommon.js
- Updated
closeMenus(...)
andtoggleMenu(...)
to allow prevention of parent menu closure when opening child menus, such as the dropdowns on the 'Advanced Search' menu
- Updated
.htaccess
to hide file extensions and useDirectoryIndex
index.php
renamed tohome.php
- Created
common.css
by extracting elements common to different pages / projects- Each page now has a specific stylesheet, i.e.
home.css
andlogin.css
- Each page now has a specific stylesheet, i.e.
- Updated all JavaScript files to use ES6 consistently, cleanup functions and global scope, and extract common functions
- Functions and object properties reordered lexicographically
- Global variables all placed into single file-specific global
const
- Replaced all uses of
var
keyword withlet
andconst
- Shortened frequently used and unncessarily long variable names while expanding more specific names to make their purpose clearer
home.js
functionsregexEscape(...)
,formatBytes(...)
,closeMenus()
,toggleMenu()
,modalClose(...)
, andcreateAlert(...)
extracted tocommon.js
module
- Updates to
home.js
sortBookmarks()
now persists sort method using localStorage- Removed
activeBookmarks
variable and references to it as it was proactively created in an early version for a potential feature that no longer requires it - Abstracted part of
bookmarksEmpty(...)
to newcheckEmpty(...)
incommon.js
module - Bookmarks can now additionally be opened by clicking the scrollwheel
- Updates to
common.js
- Added
capitalize(...)
,checkEmpty(...)
,leadZeros(...)
, andprintDate(...)
functions - Renamed
insertInlineMessage(...)
toinlineMessage(...)
- Added
- Fixed registration bug associated with AuthTokens
- Removed
php/restricted/db-steup.php
- Created privacy policy page to comply with Chrome Web Store requirement for listing OneMark extension
- Tidied up some elements of
stylesheet.css
(in-progress; will extract common elements to acommon.css
stylesheet and create page-specific stylesheets)
- Added supporting API files and functions for the new OneMark extension
- Added
ext-add-bookmark.php
, a custom version ofadd-bookmark.php
for extension requests - Added
ext-login.php
, a custom version oflogin.php
for extension requests - Added
bookmarkExists(...)
function todb-functions.php
for server-side validation - Updated
.htaccess
to allow origin requests from extension andAuthorization
headers
- Added
- Replaced unicode characters with their codes for improved reliability
- Updated
async / await
statements to reduce from 2 lines to 1 line perfetch
call- Bookmark info content abstracted from
createBookmark()
togetBookmarkInfo(...)
- Bookmark info content abstracted from
- Updated
insertInlineMessage(...)
function ofCommon
module to be simpler and support more options- Can now set a duration for messages to be deleted after
- Updated constraints on
title
andpageURL
fields for bookmarks- Updated validity checks in
isValid(...)
function ofCommon
module - Updated validity checks in
add-bookmark.php
andedit-bookmark.php
- Updated validity checks in
- Updated AuthToken duration from 14 days to 30 days
- Fixed error in info modals for bookmarks not updating without refreshing page
- Fixed pathing issue in
logging.php
when included from a different directory - Fixed bookmarks with no image not receiving the new
ImageSize
property inupload.php
- Fixed AuthToken bug caused by cookie being set to directory instead of domain
- Fixed mobile-responsiveness of modals, font-sizes, and scrollable menus
- Fixed incorrect URL validation RegEx by replacing with AngularJS's RegEx
- Fixes for undesired behavior involving tag search visual displays
- Fixed tag search button incorrect resizing on different screen sizes and variance in text-width
- Tag search label has been removed and the placeholder on the search input has been re-enabled
- Search field is now cleared when the tag search button is activated upon adding or removing a tag
- Fixed tag search button incorrect resizing on different screen sizes and variance in text-width
- Fixed bugs in
searchBookmarks()
function
- Hotfix of critical errors in
modalClose()
function - Converted fat-arrow notation for anonymous functions requiring an
event
orthis
reference back to original notation - Updated sort-menu buttons
- Order changed to reflect most likely desired sorting attributes in descending order
- Changed default query sort in
getAllBookmarks()
function indb-functions.php
to 'DateModified' descending - Added indicator of currently selected sort
- Added 'Image Size' sort option
- Added
ImageSize
column toImages
db-table
- Added
- Added dynamic alert modals with
createAlert()
- The minimum required to deliver a proper front-end experience has been implemented with aspects hard-coded as necessary to prevent excessive focus on recreating a feature with several established, extensive libaries that can be implemented in prodctuion
- 'Info' option added to bookmark dropdown menus to display metadata info (Date Created, Date Modified, View Count, Image Size)
- Added
formatBytes()
function tohome.js
to pretty-print 'Image Size'
- Added
- Updated
modalClose()
function to support optional deletion of modal
- Added 'Account' option, which opens a dynamic tabbed modal, to side-menu
- Account info tab currently contains username, email, date account created, and account type
- Created
account-info.php
and added associated functions todb-functions.php
- Created
- Password tab allows updating current password
- Created
update-pass.php
and added associated functions todb-functions.php
- Added
updatePassword()
function tohome.js
- Updated
isValid()
function to support comparison of current password to new password
- Created
- Moved
switchPanel()
function fromlogin.js
tocommon.js
- Added
swtichTab()
function tocommon.js
to support tabbed-panels
- Account info tab currently contains username, email, date account created, and account type
- Fixed undesired behavior of input title and error labels when not using reversed column order
- Fixed AuthToken login bug caused by previous change from fetching full
login.php
in JS to in-line php session check - Fixed
randomizeTheme()
bug causing same theme to be picked consecutively- Added
getRandomInt()
function tocommon.js
module to facilitate recursive random integer generation
- Added
- Consolidated global variables in
common.js
andlogin.js
into singular global objects- Renamed
Globals
object inhome.js
toIdxGlobals
and added similar prefixes to the new globals to prevent naming clashes
- Renamed
- Renamed JavaScript and HTML/PHP files to make the 'main' page the index page
- The former
index.php
(containing the login page) is nowlogin.php
- The former
main.php
(containing the main site) is nowindex.php
, andmain.js
is nowhome.js
- The former
- Merged upload- and edit-bookmark modals into one dynamic modal
- Removed several extraneous element attributes related to differentiating between elements on edit and upload modals
- Modified functions, event listeners, and global variables associated with previous configuration to now directly reference the unique elements on the bookmark-modal instead of dynamically creating IDs
- Fixed
IntersectionObserver
implementation, which only observed images created at window load and not newly created bookmarks- Observer is now created as a global variable and bookmark images are observed upon creation in
createBookmark()
instead of all at once on window load
- Observer is now created as a global variable and bookmark images are observed upon creation in
- Consolidated global variables (excluding
lazyObserver
) into single global objectGlobals
- Rewrote
addListeners()
function incommon.js
to simplify structure, consolidate repeated code, and add support for classes as identifiers - Updated
common.js
to use string literals - Added bookmark sorting functionality
- Sort options include Title, Views, Date Created, and Date Modified with an ascending and descending option for each
- Added
Views
column (default = 0) toBookmarks
db-table to support new sort type - Added
add-view.php
file for asynchronus incrementation of bookmark view count - Updated navbar HTML structure and CSS styling to support new 'Sort' menu
- Moved
db-functions.php
andlogging.php
to restricted folders as they should not be directly accessible by users
- Added 'Remove Image' button to edit- and upload-bookmark modals
- Added lazy-loading of bookmark images using the
IntersectionObserver
API - Revised ID and class naming schemes in HTML and CSS to shorten repetitive lengthy names
- Revised image folder structure on account of previous changes to separation of static and dynamic images
- Updated favicon to new custom OneMark logo
- Updated
insertInlineMessage()
to fade-in over 1 second - Fixed portions of mobile-responsive CSS (requires further testing)
- Relegated unused images and design files to subfolders ignored in
.gitignore
- Replaced
page-load.js
module andpage-load.php
with in-line PHP to remove noticeable delay- Changed
index.html
andmain.html
all references in JS and PHP files to use.php
extensions - Use PHP
header()
instead of JSwindow.location.href
to redirect immediately without executing following code
- Changed
- Modified
get-bookmarks.php
to reduce page loading lag- Moved assignment of bookmark-tags to
getAllBookmarks()
function - Replaced foreach loop calling
getBookmarkTag()
on each bookmark ingetAllBookmarks()
to get all bookmark-tags for selected user at once- Looped through all tags retrieved to check if
BookmarkID
matches and add tags toTags
field of returned bookmarks array - Script execution reduced from average of
(measured on local environment; production enviroment down from~160ms
to~90ms
~90ms
to~40ms
)
- Looped through all tags retrieved to check if
- Moved assignment of bookmark-tags to
- Replaced
window.onload
withDOMContentLoaded
event listener inindex.php
andmain.php
- Added monitoring plug-in to Heroku to keep dyno active 24/7
- Achieved with NewRelic Synthetics ping option at an interval of 15 minutes
- Fixed critical error in
createTag()
caused byquerySelector
processing speed- Switched
querySelector
call togetElementById
for proper sequential declaration - Updated tag HTML structure to include another ID for the
getElementById
call
- Switched
- Modified
createBookmark
to replacecreateElement
s with ES6 string literal for improved readability and updating- Contextual fragment used to add event listeners
- Updated
main.js
andlogin.js
to use string literals instead of concatenation - Fixed error in
RegExp
creation insearchBookmarks()
causing bookmarks with spaces in any of their properties to be incorrectly displayed at all times - Updated
searchBookmarks()
to use ES6 destructuring assignment andmap()
array function in place of repetitive code where applicable - Updated
db-connect.php
to use environment variables instead of hardcoded database credentials - Updated
main.js
andlogin.js
to use string literals instead of concatenation
- Created
page-load.js
to solve issue of page flicker between login and main pages- Script runs before loading DOM using
defer
tag and checks for user status via PHP - Flickering has not been fixed
- Priority assigned to Completed; however, the task is essentially assigned the lowest priority for revision
- Flickering of bookmarks now occurs due to delay introduced by having to use AWS S3 instead of the local filesystem; however, impact is negligible due to memory caching
- Highest impact on page load times now reassigned to
get-bookmarks.php
andlogin.php
- Script runs before loading DOM using
- Due to the nature of Heroku's ephemeral file storage system, the storage of uploaded images needed to be switched to a persistent storage server
- The free tier of Amazon S3 is being used for 5GB of image storage
- IAM user given
*list
,*read
,*write
, andPutObjectACL
permissions
- IAM user given
- Load AWS SDK
- AWS SDK installed using
composer.json
- Bucket name and S3 credentials stored in and retrieved from Heroku configuration variables
- AWS SDK installed using
- Update
upload.php
file to use Amazon S3 bucket instead of local filesystem- Image paths and urls modified to use quasi-directories to account for flat architecture
- The free tier of Amazon S3 is being used for 5GB of image storage
- Hotfix of incorrect commit resulting in old files not being removed
- Partial rewrite of database to isolate images to their own table with a relationship to the
Bookmark
table - Store image hashes from PHP in database
Images
table with a unique index constraint to search for duplicate images on upload and set image paths to existing images instead of reuploading or overwriting them - Extensive rewrite of PHP files to abstract all database-related functions and merge with the AuthTokens module to create the
db-functions.php
file for one comprehensiveinclude
- Removed
.menu-toggle
sub-elements to replace with pseudo-elements- Updated design definitions to more standard practices
- Updated modal-close buttons to follow the same design practices
- Access to sensitive PHP files restricted to server-only via .htaccess configuration
- Abstraction of common functions to
common.js
module usingimport
andexport
API - Form validation / restrictions via HTML, JS, and PHP for forms on login and main pages
- Temporary toasts replaced with new error labels adjacent to form fields
- Align minimum and maximum values for JS / PHP input with values in database
- Search bookmarks using regular expressions
- Filter by title, url, and tags using the form
[type]:
for prefixes- Toggle AND/OR for terms
- Toggle full-word for terms
- Associated helper functions for removing, hiding, and showing bookmarks
- General debouncing function to limit search calculations
- Filter by title, url, and tags using the form
- Bookmark tagging system implemented and completed
- Many-to-many relationship between
Bookmark
andTag
tables usingBookmarkTag
bridge table - On bookmark upload / edit, tags are compared to existing tags and added or removed from the
BookmarkTag
table. Tags are added to theTag
table if they do not exist - Upload and edit modals redesigned to include a tags container
- Search field with inline-button that shows as "x" when the tag is in the list and "+" otherwise
- Box below search with rows listing tags with "x" buttons next to them
- Many-to-many relationship between
- Cleaned up and updated JS code to use more ES6 elements (arrow functions, ternary and spread operators, destructuring assignment, etc.)
- Added
AccessLevel
column toUser
database table for potential future uses- Check when requesting access to restricted files and functions
- Add
Standard
andAdmin
for development; addPremium
in production
- Updated bookmark image hover animation to move along both dimensions
- To account for jittering introduced by minimal movements on the x-axis, the duration has been reduced from
5s
to2s
and the timing function has been changed tolinear
- To return the animation to the center without modifying the
keyframes
definition ofmovePosition
, the iteration count has been increased from2
to2.5
- To account for jittering introduced by minimal movements on the x-axis, the duration has been reduced from
- Transferral of To-Do-List from
main.js
toreadme.md
- Consolidation of To-Do-List and GitHub commit changelogs into one entity
- Retroactive updates to To-Do-List and changelogs to improve information granularity, consistency, and formatting
- Hotfix for graphical issues caused by improper commit
- Complete visual redesign to a consistent, material design
- Mobile responsiveness added where relevant (not including touch features)
- Navigation bar added to contain miscellaneous buttons and future features
- Updates of JS and PHP corresponding with redesign
- Authentication tokens / "Remember Me" functionality fully implemented
- Code cleanup and optimization
- Improved to-do-list organization
- Token authentication and persistent login system added
- Logging system added (primarily for development debugging)
- Cleaned up interactions between JS and PHP to show users appropriate messages and redirect to the correct locations
- New functions added in PHP and JS along with optimizations and code cleanup
- Creation of Database and PHP Scripts
- Updates to HTML Structure
- Minor modifications to CSS
- Sweeping shanges to Javascript core functions and introduction of new functions in correspondance with introduction of PHP scripts
- Initial commits of existing files