Compare commits

..

2 commits

Author SHA1 Message Date
af6888a7bb Merge pull request 'bunch of newness' (#2) from feat-input into main
Reviewed-on: #2
2024-09-30 06:32:03 -04:00
26084f3dd2 bunch of newness 2024-09-30 06:30:56 -04:00
11 changed files with 4846 additions and 16 deletions

View file

@ -22,3 +22,5 @@ dist-ssr
*.njsproj *.njsproj
*.sln *.sln
*.sw? *.sw?
__snapshots__/

File diff suppressed because it is too large Load diff

View file

@ -29,6 +29,7 @@
"eslint-plugin-react-hooks": "^5.1.0-rc.0", "eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.9", "eslint-plugin-react-refresh": "^0.4.9",
"globals": "^15.9.0", "globals": "^15.9.0",
"jest": "^29.7.0",
"jsdom": "^25.0.0", "jsdom": "^25.0.0",
"vite": "^5.4.1", "vite": "^5.4.1",
"vitest": "^2.0.5" "vitest": "^2.0.5"

View file

@ -20,29 +20,40 @@ function App() {
); );
} }
// This is just temp data that will get updated later
//
const fakeDate = new Date();
fakeDate.setDate(fakeDate.getDate() - 1);
const fakeDate2 = new Date();
fakeDate2.setDate(fakeDate2.getDate() - 2);
const fakeDate3 = new Date();
fakeDate3.setDate(fakeDate3.getDate() - 3);
const fakeDate4 = new Date();
fakeDate4.setDate(fakeDate4.getDate() - 4);
const tempData = [ const tempData = [
{ {
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vitae nibh velit. Vivamus maximus elit et eleifend hendrerit. Praesent ac metus eget risus accumsan finibus. Cras tempor dignissim dolor, ut tempus tortor interdum non. Sed sit amet fringilla turpis. Sed congue feugiat orci, vel iaculis libero venenatis eu.", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vitae nibh velit. Vivamus maximus elit et eleifend hendrerit. Praesent ac metus eget risus accumsan finibus. Cras tempor dignissim dolor, ut tempus tortor interdum non. Sed sit amet fringilla turpis. Sed congue feugiat orci, vel iaculis libero venenatis eu.",
topics: ["kubernetes", "argocd"], topics: ["#kubernetes", "#argocd"],
date: new Date().toLocaleDateString(), date: fakeDate,
id: 1, id: 1,
}, },
{ {
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vitae nibh velit. Vivamus maximus elit et eleifend hendrerit. Praesent ac metus eget risus accumsan finibus. Cras tempor dignissim dolor, ut tempus tortor interdum non. Sed sit amet fringilla turpis. Sed congue feugiat orci, vel iaculis libero venenatis eu.", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vitae nibh velit. Vivamus maximus elit et eleifend hendrerit. Praesent ac metus eget risus accumsan finibus. Cras tempor dignissim dolor, ut tempus tortor interdum non. Sed sit amet fringilla turpis. Sed congue feugiat orci, vel iaculis libero venenatis eu.",
topics: ["react", "python", "javascript"], topics: ["#react", "#python", "#javascript"],
date: new Date().toLocaleDateString(), date: fakeDate2,
id: 2, id: 2,
}, },
{ {
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vitae nibh velit. Vivamus maximus elit et eleifend hendrerit. Praesent ac metus eget risus accumsan finibus. Cras tempor dignissim dolor, ut tempus tortor interdum non. Sed sit amet fringilla turpis. Sed congue feugiat orci, vel iaculis libero venenatis eu.", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vitae nibh velit. Vivamus maximus elit et eleifend hendrerit. Praesent ac metus eget risus accumsan finibus. Cras tempor dignissim dolor, ut tempus tortor interdum non. Sed sit amet fringilla turpis. Sed congue feugiat orci, vel iaculis libero venenatis eu.",
topics: ["docker", "proxmox"], topics: ["#docker", "#proxmox"],
date: new Date().toLocaleDateString(), date: fakeDate3,
id: 3, id: 3,
}, },
{ {
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vitae nibh velit. Vivamus maximus elit et eleifend hendrerit. Praesent ac metus eget risus accumsan finibus. Cras tempor dignissim dolor, ut tempus tortor interdum non. Sed sit amet fringilla turpis. Sed congue feugiat orci, vel iaculis libero venenatis eu.", body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vitae nibh velit. Vivamus maximus elit et eleifend hendrerit. Praesent ac metus eget risus accumsan finibus. Cras tempor dignissim dolor, ut tempus tortor interdum non. Sed sit amet fringilla turpis. Sed congue feugiat orci, vel iaculis libero venenatis eu.",
topics: ["aws", "github"], topics: ["#aws", "#github"],
date: new Date().toLocaleDateString(), date: fakeDate4,
id: 4, id: 4,
}, },
]; ];

View file

@ -2,33 +2,46 @@ import PropTypes from "prop-types";
import styles from "./changeLogInput.module.css"; import styles from "./changeLogInput.module.css";
const ChangeLogInput = (props) => { const ChangeLogInput = (props) => {
const handleClick = (e) => { const handleClick = () => {
const topics = getTopics(props.logInput);
const newEntry = { const newEntry = {
body: props.logInput, body: props.logInput,
topics: ["test"], topics: topics,
date: new Date().toLocaleDateString(), date: new Date(),
id: crypto.randomUUID(), id: crypto.randomUUID(),
}; };
props.setFeed([newEntry, ...props.feed]); props.setFeed([newEntry, ...props.feed]);
props.setLogInput(""); props.setLogInput("");
}; };
return ( return (
<div className={styles.container}> <div className={styles.container}>
<textarea <textarea
rows="1" rows="1"
placeholder="What did you change..." placeholder="What did you change...?!"
className={styles.input} className={styles.input}
onChange={(e) => props.setLogInput(e.target.value)} onChange={(e) => props.setLogInput(e.target.value)}
value={props.logInput} value={props.logInput}
/> />
<button onClick={handleClick} className={styles.btn}> <button onClick={handleClick} className={styles.btn}>
Submit Log it!
</button> </button>
</div> </div>
); );
}; };
const getTopics = (body) => {
const re = /#\w+/g;
let topics = [];
const matchs = [...body.matchAll(re)];
matchs.forEach((match) => (topics = topics.concat(match[0])));
return topics;
};
ChangeLogInput.propTypes = { ChangeLogInput.propTypes = {
setLogInput: PropTypes.func, setLogInput: PropTypes.func,
logInput: PropTypes.string, logInput: PropTypes.string,

View file

@ -8,6 +8,12 @@
.input { .input {
outline: 1px solid black; outline: 1px solid black;
width: 100%; width: 100%;
field-sizing: content;
/*min-height: 17px;*/
/*border: 1px solid #ccc;*/
/*max-height: 150px;*/
/*overflow-x: hidden;*/
/*overflow-y: auto;*/
} }
.btn { .btn {

View file

@ -1,4 +1,5 @@
import { HashTagLink } from "./links"; import { dateParser } from "../utils/dateParser";
import { HashTagLink } from "../utils/links";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import styles from "./feed.module.css"; import styles from "./feed.module.css";
@ -31,7 +32,7 @@ const LogEntryCard = ({ body, date, topics }) => {
<p>{body}</p> <p>{body}</p>
<div className={styles.cardBottom}> <div className={styles.cardBottom}>
<FeedTopics topics={topics} /> <FeedTopics topics={topics} />
<p>{date}</p> <p>{dateParser(date)}</p>
</div> </div>
</div> </div>
); );
@ -51,4 +52,5 @@ LogEntryCard.propTypes = {
topics: PropTypes.array, topics: PropTypes.array,
}; };
//<p>{date.toLocaleString()}</p>
export default Feed; export default Feed;

View file

@ -0,0 +1,5 @@
const Topic = (props) => {
const entries = props.entries;
const filtered = entries.filter((item) => {});
};

View file

@ -0,0 +1,24 @@
function dateParser(date) {
/* Returns a time/date formatted string
* based on the age of the log entry.
* > 24 hrs return the date
* < 24 hrs > 1 hr return the number of hours
* otherwise return the minutes since the log was entered
*/
const currentTime = new Date();
const difference = Math.floor((currentTime - date) / 1000);
if (difference >= 86400) {
// Return date since entry is older than a day
return date.toLocaleString();
} else if (difference >= 3600) {
// Return hours since log entry
return `${difference / 3600}h`;
} else {
// Reteurn Minutes since log entry
return `${Math.floor(difference / 60)}m`;
}
}
export { dateParser };

View file

@ -0,0 +1,31 @@
import { dateParser } from "./dateParser";
import { describe, it, expect } from "vitest";
describe("Date Parser", () => {
it("should have 0m for new entries", () => {
const currentTime = new Date();
const timeString = dateParser(currentTime);
expect(timeString).toMatch(/0m/);
});
it("Should return (n)m for entries older than 30 minutes", () => {
const currentTime = new Date();
currentTime.setMinutes(currentTime.getMinutes() + 30);
const timeString = dateParser(currentTime);
expect(timeString).toMatch(/30m/);
});
it("should return (n)h for entires aged over an hour", () => {
const currentTime = new Date();
currentTime.setHours(currentTime.getHours() - 2);
const timeString = dateParser(currentTime);
expect(timeString).toMatch(/2h/);
});
it("should return the date for entries older than 24 hours", () => {
const currentTime = new Date();
currentTime.setDate(currentTime.getDate() - 1);
const timeString = dateParser(currentTime);
expect(timeString).toBeTypeOf("string");
});
});

View file

@ -2,7 +2,7 @@ import { Link } from "react-router-dom";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
const HashTagLink = ({ tag }) => { const HashTagLink = ({ tag }) => {
return <a href="#">#{tag}</a>; return <a href="#">{tag}</a>;
}; };
HashTagLink.propTypes = { HashTagLink.propTypes = {