Added ability to set icons on bookmarks. Added hover indicator for apps

This commit is contained in:
unknown 2021-06-09 12:45:55 +02:00
parent 8b87ad92f1
commit 4583ca00e9
11 changed files with 80 additions and 20 deletions

View File

@ -28,3 +28,15 @@
font-size: 0.8em; font-size: 0.8em;
opacity: 1; opacity: 1;
} }
@media (min-width: 500px) {
.AppCard {
padding: 2px;
border-radius: 4px;
transition: all 0.10s;
}
.AppCard:hover {
background-color: rgba(0,0,0,0.2);
}
}

View File

@ -2,6 +2,7 @@ import { Link } from 'react-router-dom';
import classes from './AppCard.module.css'; import classes from './AppCard.module.css';
import Icon from '../../UI/Icons/Icon/Icon'; import Icon from '../../UI/Icons/Icon/Icon';
import { iconParser } from '../../../utility/iconParser';
import { App } from '../../../interfaces'; import { App } from '../../../interfaces';
@ -11,16 +12,6 @@ interface ComponentProps {
} }
const AppCard = (props: ComponentProps): JSX.Element => { const AppCard = (props: ComponentProps): JSX.Element => {
const iconParser = (mdiName: string): string => {
let parsedName = mdiName
.split('-')
.map((word: string) => `${word[0].toUpperCase()}${word.slice(1)}`)
.join('');
parsedName = `mdi${parsedName}`;
return parsedName;
}
const redirectHandler = (url: string): void => { const redirectHandler = (url: string): void => {
window.open(url); window.open(url);
} }

View File

@ -18,9 +18,17 @@
.Bookmarks a { .Bookmarks a {
line-height: 2; line-height: 2;
transition: all 0.25s; transition: all 0.25s;
display: flex;
} }
.BookmarkCard a:hover { .BookmarkCard a:hover {
text-decoration: underline; text-decoration: underline;
padding-left: 10px; padding-left: 10px;
} }
.BookmarkIcon {
width: 20px;
display: flex;
margin-bottom: 1px;
margin-right: 2px;
}

View File

@ -1,6 +1,9 @@
import { Bookmark, Category } from '../../../interfaces'; import { Bookmark, Category } from '../../../interfaces';
import classes from './BookmarkCard.module.css'; import classes from './BookmarkCard.module.css';
import Icon from '../../UI/Icons/Icon/Icon';
import { iconParser } from '../../../utility/iconParser';
interface ComponentProps { interface ComponentProps {
category: Category; category: Category;
} }
@ -15,6 +18,11 @@ const BookmarkCard = (props: ComponentProps): JSX.Element => {
href={`http://${bookmark.url}`} href={`http://${bookmark.url}`}
target='blank' target='blank'
key={`bookmark-${bookmark.id}`}> key={`bookmark-${bookmark.id}`}>
{bookmark.icon && (
<div className={classes.BookmarkIcon}>
<Icon icon={iconParser(bookmark.icon)} />
</div>
)}
{bookmark.name} {bookmark.name}
</a> </a>
))} ))}

View File

@ -29,9 +29,11 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => {
const [formData, setFormData] = useState<NewBookmark>({ const [formData, setFormData] = useState<NewBookmark>({
name: '', name: '',
url: '', url: '',
categoryId: -1 categoryId: -1,
icon: ''
}) })
// Load category data if provided for editing
useEffect(() => { useEffect(() => {
if (props.category) { if (props.category) {
setCategoryName({ name: props.category.name }); setCategoryName({ name: props.category.name });
@ -40,18 +42,21 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => {
} }
}, [props.category]) }, [props.category])
// Load bookmark data if provided for editing
useEffect(() => { useEffect(() => {
if (props.bookmark) { if (props.bookmark) {
setFormData({ setFormData({
name: props.bookmark.name, name: props.bookmark.name,
url: props.bookmark.url, url: props.bookmark.url,
categoryId: props.bookmark.categoryId categoryId: props.bookmark.categoryId,
icon: props.bookmark.icon
}) })
} else { } else {
setFormData({ setFormData({
name: '', name: '',
url: '', url: '',
categoryId: -1 categoryId: -1,
icon: ''
}) })
} }
}, [props.bookmark]) }, [props.bookmark])
@ -79,7 +84,8 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => {
setFormData({ setFormData({
name: '', name: '',
url: '', url: '',
categoryId: formData.categoryId categoryId: formData.categoryId,
icon: ''
}) })
} }
} else { } else {
@ -94,7 +100,8 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => {
setFormData({ setFormData({
name: '', name: '',
url: '', url: '',
categoryId: -1 categoryId: -1,
icon: ''
}) })
} }
@ -201,6 +208,25 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => {
})} })}
</select> </select>
</InputGroup> </InputGroup>
<InputGroup>
<label htmlFor='icon'>Bookmark Icon (optional)</label>
<input
type='text'
name='icon'
id='icon'
placeholder='book-open-outline'
value={formData.icon}
onChange={(e) => inputChangeHandler(e)}
/>
<span>
Use icon name from MDI.
<a
href='https://materialdesignicons.com/'
target='blank'>
{' '}Click here for reference
</a>
</span>
</InputGroup>
</Fragment> </Fragment>
) )
} }

View File

@ -96,6 +96,7 @@ const BookmarkTable = (props: ComponentProps): JSX.Element => {
<Table headers={[ <Table headers={[
'Name', 'Name',
'URL', 'URL',
'Icon',
'Category', 'Category',
'Actions' 'Actions'
]}> ]}>
@ -104,6 +105,7 @@ const BookmarkTable = (props: ComponentProps): JSX.Element => {
<tr key={bookmark.bookmark.id}> <tr key={bookmark.bookmark.id}>
<td>{bookmark.bookmark.name}</td> <td>{bookmark.bookmark.name}</td>
<td>{bookmark.bookmark.url}</td> <td>{bookmark.bookmark.url}</td>
<td>{bookmark.bookmark.icon}</td>
<td>{bookmark.categoryName}</td> <td>{bookmark.categoryName}</td>
<td className={classes.TableActions}> <td className={classes.TableActions}>
<div <div

View File

@ -45,6 +45,7 @@ const Bookmarks = (props: ComponentProps): JSX.Element => {
name: '', name: '',
url: '', url: '',
categoryId: -1, categoryId: -1,
icon: '',
id: -1, id: -1,
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date() updatedAt: new Date()

View File

@ -4,10 +4,12 @@ export interface Bookmark extends Model {
name: string; name: string;
url: string; url: string;
categoryId: number; categoryId: number;
icon: string;
} }
export interface NewBookmark { export interface NewBookmark {
name: string; name: string;
url: string; url: string;
categoryId: number; categoryId: number;
icon: string;
} }

View File

@ -0,0 +1,9 @@
export const iconParser = (mdiName: string): string => {
let parsedName = mdiName
.split('-')
.map((word: string) => `${word[0].toUpperCase()}${word.slice(1)}`)
.join('');
parsedName = `mdi${parsedName}`;
return parsedName;
}

7
db.js
View File

@ -8,13 +8,10 @@ const sequelize = new Sequelize({
const connectDB = async () => { const connectDB = async () => {
try { try {
await sequelize.authenticate({ logging: false }); await sequelize.authenticate();
console.log('Connected to database'); console.log('Connected to database');
await sequelize.sync({ await sequelize.sync({ alter: true });
// alter: true,
logging: false
});
console.log('All models were synced'); console.log('All models were synced');
} catch (error) { } catch (error) {
console.error('Unable to connect to the database:', error); console.error('Unable to connect to the database:', error);

View File

@ -13,6 +13,10 @@ const Bookmark = sequelize.define('Bookmark', {
categoryId: { categoryId: {
type: DataTypes.INTEGER, type: DataTypes.INTEGER,
allowNull: false allowNull: false
},
icon: {
type: DataTypes.STRING,
defaultValue: ''
} }
}, { }, {
tableName: 'bookmarks' tableName: 'bookmarks'