mirror of
https://github.com/pawelmalak/flame.git
synced 2024-12-24 10:42:40 +03:00
Added ability to set icons on bookmarks. Added hover indicator for apps
This commit is contained in:
parent
8b87ad92f1
commit
4583ca00e9
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
@ -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>
|
||||||
))}
|
))}
|
||||||
|
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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;
|
||||||
}
|
}
|
9
client/src/utility/iconParser.ts
Normal file
9
client/src/utility/iconParser.ts
Normal 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
7
db.js
@ -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);
|
||||||
|
@ -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'
|
||||||
|
Loading…
Reference in New Issue
Block a user