@fortawesome/free-brands-svg-icons#fab JavaScript Examples
The following examples show how to use
@fortawesome/free-brands-svg-icons#fab.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: App.js From lrc-staking-dapp with MIT License | 6 votes |
library.add( far, fas, faBookReader, faArrowLeft, faArrowRight, faQuestionCircle, faCopy, faSignOutAlt, faEdit, faAngleDown, faExternalLinkAlt, fab, faEthereum, faTwitter, faDiscord, faUnlink, faSearch, faFortAwesome, faExchangeAlt, faChartPie, faGlobe, faDonate, faDollarSign, );
Example #2
Source File: Icon.js From beautiful-react-ui with MIT License | 5 votes |
// adding fa dependencies
library.add(fas, fab);
Example #3
Source File: FontAwesomeIcon.jsx From tonic-ui with MIT License | 5 votes |
library.add(fab);
Example #4
Source File: App.js From littlelink-server with MIT License | 5 votes |
library.add(fab, fas, far);
Example #5
Source File: Fontawesome.js From gatsby-personal-site-template with MIT License | 5 votes |
library.add(fab, fas)
Example #6
Source File: globalStyle.js From personal-site with MIT License | 5 votes |
library.add(fab, faEnvelope, faPaperclip, faExternalLinkAlt, faFire, faCross)
Example #7
Source File: main.js From minimal-portfolio with GNU General Public License v3.0 | 5 votes |
library.add(fab)
Example #8
Source File: main.js From CursedChrome with MIT License | 5 votes |
library.add(fab)
Example #9
Source File: App.js From dmm-web-app with MIT License | 5 votes |
library.add(fab);
Example #10
Source File: globalStyle.js From bartzalewski.com-v2 with MIT License | 5 votes |
library.add(fab, faEnvelope, faPaperclip, faExternalLinkAlt, faFire, faCross)
Example #11
Source File: index.js From gatsby-markdown-personal-website with MIT License | 5 votes |
/* add any additional icon to the library */
library.add(fab, faLaptopCode, faDrawPolygon, faEdit, faEdit, faBullhorn, faMapMarkerAlt, faPhone, faPaperPlane);
Example #12
Source File: navbar.component.js From hiring-system with GNU General Public License v3.0 | 5 votes |
library.add(fab, faGithub);
Example #13
Source File: icon.js From React-Messenger-App with MIT License | 5 votes |
library.add(fas, fab);
Example #14
Source File: layout.js From blog with Apache License 2.0 | 5 votes |
library.add(fab, fas);
Example #15
Source File: Help.js From gitconvex with Apache License 2.0 | 4 votes |
export default function Help() {
library.add(fas, fab);
const [currentVersion, setCurrentVersion] = useState("");
const [availableUpdate, setAvailableUpdate] = useState("");
const [showUpdatePane, setShowUpdatePane] = useState(false);
const [isLatest, setIsLatest] = useState(false);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
useEffect(() => {
setCurrentVersion(CURRENT_VERSION);
}, []);
function resetStates() {
setShowUpdatePane(false);
setLoading(false);
setError(false);
setAvailableUpdate("");
setIsLatest(false);
}
const supportData = [
{
label: "reach via discord",
link: "https://discord.gg/PSd2Cq9",
icon: ["fab", "discord"],
color: ["bg-indigo-400", "bg-indigo-500"],
},
{
label: "reach via github",
link: "https://github.com/neel1996/gitconvex-package/issues",
icon: ["fab", "github"],
color: ["bg-gray-800", "bg-gray-700"],
},
{
label: "reach via twitter",
link: "https://twitter.com/neeldev96",
icon: ["fab", "twitter"],
color: ["bg-blue-400", "bg-blue-600"],
},
];
const contributionData = [
{
label: "Gitconvex react project",
link: "https://github.com/neel1996/gitconvex-ui",
icon: ["fab", "react"],
color: ["bg-blue-400"],
ind: "",
},
{
label: "Gitconvex Go project",
link: "https://github.com/neel1996/gitconvex-server",
icon: GoLogo,
color: ["bg-gray-700"],
ind: "go",
},
];
function checkUpdateHandler() {
resetStates();
setShowUpdatePane(true);
setLoading(true);
const githubEndpoint =
"https://api.github.com/repos/neel1996/gitconvex/releases/latest";
axios({
url: githubEndpoint,
method: "GET",
headers: {
Accept: "application/json",
},
})
.then((res) => {
const { tag_name } = res.data;
setLoading(false);
if (currentVersion === tag_name) {
setIsLatest(true);
setAvailableUpdate("");
} else {
setAvailableUpdate(tag_name);
}
})
.catch((err) => {
console.log(err);
});
}
return (
<div className="w-full h-auto overflow-auto">
<div className="flex text-5xl text-gray-700 mx-6 my-auto align-middle items-center">
<FontAwesomeIcon icon={["fas", "question-circle"]}></FontAwesomeIcon>
<div className="my-5 mx-5 font-sans">Help and Support</div>
</div>
<div className="my-4 mx-10">
<div className="text-2xl font-sans text-gray-900">
Facing an issue or need any help?
</div>
<span className="text-xl text-gray-500 font-medium my-2">
Before raising an issue, please make sure you have gone through the
</span>
<span className="font-mono text-xl mx-2 text-indigo-500 hover:text-indigo-600 hover:font-semibold cursor-pointer">
<a
href="https://github.com/neel1996/gitconvex/blob/master/DOCUMENTATION.md"
target="_blank"
rel="noopener noreferrer"
>
Documentation
</a>
</span>
</div>
<div className="support-feedback my-10 mx-10">
<div className="text-2xl font-sans font-semibold">
Support and Feedback
</div>
<div className="my-20 flex justify-center gap-10">
{supportData.map((data) => {
return (
<div key={data.label}>
<a href={data.link} target="_blank" rel="noopener noreferrer">
<div
className={`block mx-auto p-6 rounded-lg shadow-md ${data.color[0]} text-white text-center hover:${data.color[1]} hover:shadow-lg`}
>
<FontAwesomeIcon
size="4x"
icon={data.icon}
></FontAwesomeIcon>
<div className="mx-3 font-sans font-semibold">
{data.label}
</div>
</div>
</a>
</div>
);
})}
</div>
</div>
<div className="support-feedback my-10 mx-10">
<div className="text-2xl font-sans font-semibold">Contribution</div>
<div className="font-sans font-light border-b border-dashed text-center text-gray-600 my-5 break-normal">
gitconvex is open source and please visit the repo if you are
interested in contributing to the platform
</div>
</div>
<div className="my-10 flex justify-center gap-10">
{contributionData.map((data) => {
return (
<div key={data.label}>
<a href={data.link} target="_blank" rel="noopener noreferrer">
<div
className={`block mx-auto p-6 rounded-lg shadow-md ${data.color[0]} text-white text-center hover:shadow-xl`}
style={{
width: "250px",
height: "150px",
}}
>
{data.ind !== "go" ? (
<FontAwesomeIcon
size="4x"
icon={data.icon}
></FontAwesomeIcon>
) : (
<img
src={GoLogo}
alt="go-logo"
className="text-center mx-auto items-center flex w-20"
></img>
)}
<div className="mx-3 font-sans font-semibold">
{data.label}
</div>
</div>
</a>
</div>
);
})}
</div>
<div className="fixed bottom-0 right-0 mr-6 mb-6 ">
{showUpdatePane ? (
<div
className="bg-white shadow-md block border rounded-lg p-10 text-xl font-sans font-semibold right-0 bottom-0 fixed mr-5"
style={{
marginBottom: "120px",
}}
>
<div
className="relative text-gray-400 text-xl float-right cursor-pointer"
style={{
marginTop: "-40px",
marginRight: "-25px",
paddingRight: "-15px",
}}
onClick={() => {
resetStates();
}}
>
x
</div>
<div className="text-xl font-sans font-semibold text-gray-800 text-center">
Current Version : {currentVersion}
</div>
{loading ? (
<div className="text-gray-400 font-sans font-light">
checking for updates...
</div>
) : null}
{isLatest ? (
<div className="text-center text-sm font-sans font-light text-gray-600">
You are using the latest version of gitconvex
</div>
) : null}
{error ? (
<div className="text-red-600 font-sans">
Cannot reach update validation server
</div>
) : null}
{availableUpdate ? (
<div className="my-2">
<div className="text-xl text-gray-800 text-left">
New update v{availableUpdate} available.
</div>
<div className="p-4 rounded-lg my-2 text-lg font-sans text-center bg-pink-500 text-white">
<a
href={`https://github.com/neel1996/gitconvex/releases/tag/${availableUpdate}`}
target="_blank"
rel="noopener noreferrer"
>
Get Update
</a>
</div>
</div>
) : null}
</div>
) : null}
<div
className="bg-indigo-400 shadow-lg w-20 h-20 rounded-full text-center cursor-pointer hover:bg-indigo-300 border-8 border-indigo-200"
onClick={() => {
checkUpdateHandler();
}}
>
<div className="flex justify-center items-center align-middle my-auto">
<FontAwesomeIcon
icon={["fas", "sync-alt"]}
className="text-white mt-3"
></FontAwesomeIcon>
</div>
<div className="font-sans font-light text-indigo-100">Update</div>
</div>
</div>
</div>
);
}
Example #16
Source File: GitOperationComponent.js From gitconvex with Apache License 2.0 | 4 votes |
export default function GitOperationComponent(props) {
library.add(fab);
const { repoId } = props;
const { stateChange } = props;
const [gitTrackedFiles, setGitTrackedFiles] = useState([]);
const [gitUntrackedFiles, setGitUntrackedFiles] = useState([]);
const [action, setAction] = useState("");
const [list, setList] = useState([]);
const [viewReload, setViewReload] = useState(0);
const [currentStageItem, setCurrentStageItem] = useState("");
const [stageItems, setStagedItems] = useState([]);
const [unStageFailed, setUnStageFailed] = useState(false);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
setIsLoading(true);
setStagedItems([]);
setCurrentStageItem("");
const cancelToken = axios.CancelToken;
const source = cancelToken.source();
axios({
url: globalAPIEndpoint,
method: "POST",
headers: {
"Content-type": "application/json",
},
cancelToken: source.token,
data: {
query: `
query {
gitChanges(repoId: "${props.repoId}"){
gitUntrackedFiles
gitChangedFiles
gitStagedFiles
}
}
`,
},
})
.then((res) => {
if (res.data.data) {
var apiData = res.data.data.gitChanges;
setGitTrackedFiles([...apiData.gitChangedFiles]);
setGitUntrackedFiles([...apiData.gitUntrackedFiles]);
setStagedItems([...apiData.gitStagedFiles]);
const apiTrackedFiles = [...apiData.gitChangedFiles];
const apiUnTrackedFiles = [...apiData.gitUntrackedFiles];
let componentList = [];
apiTrackedFiles &&
apiTrackedFiles.forEach((item) => {
if (item.split(",").length > 0) {
const trackedItem = item.split(",")[1];
componentList.push(trackedItem);
}
});
apiUnTrackedFiles &&
apiUnTrackedFiles.forEach((item) => {
if (item) {
item = item.replace("NO_DIR", "");
item.split(",")
? componentList.push(item.split(",").join(""))
: componentList.push(item);
}
});
setList([...componentList]);
setIsLoading(false);
}
})
.catch((err) => {
setIsLoading(false);
});
return () => {
source.cancel();
};
}, [props.repoId, viewReload, currentStageItem]);
const actionButtons = [
{
label: "Stage all changes",
border: "border-indigo-300",
text: "text-indigo-700",
bg: "bg-indigo-50",
hoverBg: "hover:bg-indigo-100",
key: "stage",
},
{
label: "Commit Changes",
border: "border-green-300",
text: "text-green-700",
bg: "bg-green-50",
hoverBg: "hover:bg-green-100",
key: "commit",
},
{
label: "Push to remote",
border: "border-pink-300",
text: "text-pink-700",
bg: "bg-pink-50",
hoverBg: "hover:bg-pink-100",
key: "push",
},
];
const tableColumns = ["CHANGES", "FILE STATUS", "ACTION"];
function stageGitComponent(stageItem, event) {
let localViewReload = viewReload + 1;
event.target.innerHTML = "Staging...";
event.target.style.backgroundColor = "gray";
event.target.disabled = true;
axios({
url: globalAPIEndpoint,
method: "POST",
data: {
query: `
mutation {
stageItem(repoId: "${repoId}", item: "${stageItem}")
}
`,
},
})
.then((res) => {
setViewReload(localViewReload);
if (res.data.data && !res.data.error) {
if (res.data.data.stageItem === "ADD_ITEM_SUCCESS") {
setCurrentStageItem(stageItem);
}
}
})
.catch((err) => {
console.log(err);
setViewReload(localViewReload);
});
}
function getTableData() {
let tableDataArray = [];
let statusPill = (status) => {
if (status === "M") {
return (
<div className="rounded w-3/4 mx-auto p-2 text-yellow-600 border-2 border-yellow-200 font-sans font-semibold bg-yellow-50">
MODIFIED
</div>
);
} else if (status === "D") {
return (
<div className="rounded w-3/4 mx-auto p-2 text-red-500 border-2 border-red-200 font-sans font-semibold bg-red-50">
REMOVED
</div>
);
} else {
return (
<div className="rounded w-3/4 mx-auto p-2 text-indigo-600 border-2 border-indigo-200 font-sans font-semibold bg-indigo-50">
UNTRACKED
</div>
);
}
};
let actionButton = (stageItem) => {
return (
<div
className="w-3/4 rounded-md text-white mx-auto cursor-pointer p-2 bg-green-300 text-xl font-sans font-semibold text-center shadow-md hover:bg-green-400 hover:shadow-sm"
onClick={(event) => {
stageGitComponent(stageItem, event);
setUnStageFailed(false);
}}
key={`add-btn-${stageItem}`}
>
ADD
</div>
);
};
gitTrackedFiles &&
gitTrackedFiles.forEach((item) => {
if (item.split(",").length > 0) {
const trackedItem = item.split(",")[1];
tableDataArray.push([
trackedItem,
statusPill(item.split(",")[0]),
actionButton(trackedItem),
]);
}
});
gitUntrackedFiles &&
gitUntrackedFiles.forEach((item) => {
if (item) {
item = item.replace("NO_DIR", "");
item.split(",")
? tableDataArray.push([
item.split(",").join(""),
statusPill("N"),
actionButton(item.split(",").join("")),
])
: tableDataArray.push([item, statusPill("N"), actionButton(item)]);
}
});
return tableDataArray;
}
function getStagedFilesComponent() {
function removeStagedItem(item, event) {
let localViewReload = viewReload + 1;
stateChange();
event.target.innerHTML = "removing...";
event.target.style.backgroundColor = "gray";
event.target.disabled = true;
axios({
url: globalAPIEndpoint,
method: "POST",
data: {
query: `
mutation{
removeStagedItem(repoId: "${repoId}", item: "${item}")
}
`,
},
})
.then((res) => {
setViewReload(localViewReload);
if (res.data.data && !res.data.error) {
if (res.data.data.removeStagedItem === "STAGE_REMOVE_SUCCESS") {
let localStagedItems = stageItems;
localStagedItems = localStagedItems.filter((filterItem) => {
if (filterItem === item) {
return false;
}
return true;
});
setStagedItems([...localStagedItems]);
} else {
setUnStageFailed(true);
}
}
})
.catch((err) => {
console.log(err);
setViewReload(localViewReload);
setUnStageFailed(true);
});
}
function removeAllStagedItems(event) {
let localViewReload = viewReload + 1;
setStagedItems();
stateChange();
event.target.innerHTML = "Removing...";
event.target.style.backgroundColor = "gray";
event.target.disabled = true;
axios({
url: globalAPIEndpoint,
method: "POST",
data: {
query: `
mutation {
removeAllStagedItem(repoId: "${repoId}")
}
`,
},
})
.then((res) => {
setViewReload(localViewReload + 1);
if (res.data.data && !res.data.error) {
if (
res.data.data.removeAllStagedItem === "STAGE_ALL_REMOVE_SUCCESS"
) {
setStagedItems([]);
}
}
})
.catch((err) => {
console.log(err);
setViewReload(localViewReload + 1);
});
}
if (stageItems && stageItems.length > 0) {
return (
<div className="p-3 my-10 w-full mx-auto border border-blue-100 shadow-md rounded-lg">
<div className="flex items-center justify-start my-6 w-full">
<div className="text-4xl font-sans text-gray-800 mx-4">
Staged Files
</div>
<div
className="p-3 rounded-lg bg-red-400 text-white font-sans font-semibold text-xl cursor-pointer hover:bg-red-500"
onClick={(event) => {
removeAllStagedItems(event);
setUnStageFailed(false);
}}
>
Remove All Items
</div>
</div>
{unStageFailed ? (
<div className="my-4 mx-auto text-center shadow-md rounded p-4 border border-red-200 text-red-400 font-sans font-semibold">
Remove item failed. Note that deleted files cannot be removed as a
single entity. Use
<i className="border-b border-gray-600 border-dashed mx-2">
Remove All Items
</i>
to perform a complete git reset
</div>
) : null}
<div className="flex justify-between p-3 bg-indigo-400 rounded my-1 shadow">
<div className="w-3/4 font-sans font-semibold text-xl text-center text-white border-r-2 border-indigo-300">
STAGED FILE
</div>
<div className="w-1/4 font-sans font-semibold text-xl text-center text-white border-r-2 border-indigo-300">
ACTION
</div>
</div>
<div
className="overflow-y-auto w-full my-2"
style={{ height: "450px" }}
>
{stageItems.map((item) => {
if (item) {
return (
<div
className="flex items-center justify-between border-b p-1"
key={item}
>
<div className="w-3/4 pr-6 block px-1 border-r-2 border-gray-300">
<div className="git-changed-item overflow-x-auto w-full font-sans ml-1 text-gray-700">
{item}
</div>
</div>
<div className="w-1/4 mx-auto">
<div
className="rounded text-white cursor-pointer w-3/4 mx-auto p-2 my-1 bg-red-400 text-xl font-sans font-semibold text-center shadow-md hover:bg-red-500 hover:shadow-sm"
onClick={(event) => {
removeStagedItem(item, event);
setUnStageFailed(false);
}}
key={`remove-btn-${item}`}
>
REMOVE
</div>
</div>
</div>
);
}
return null;
})}
</div>
</div>
);
}
}
function actionComponent(action) {
switch (action) {
case "stage":
if (list && list.length > 0) {
return (
<StageComponent
repoId={repoId}
stageComponents={list}
></StageComponent>
);
} else {
return (
<div className="w-1/2 mx-auto my-auto bg-gray-200 p-6 rounded-md">
<div className="bg-white p-6 font-sans text-3xl font-light text-gray-500 border-b-4 border-dashed rounded-lg shadow-lg border-gray-500 text-center">
No Changes for staging...
</div>
</div>
);
}
case "commit":
return <CommitComponent repoId={repoId}></CommitComponent>;
case "push":
return <PushComponent repoId={repoId}></PushComponent>;
default:
return null;
}
}
function noChangesComponent() {
return (
<div className="mx-auto my-4 text-center font-sans font-light text-2xl shadow p-6 bg-pink-50 border-b-4 border-pink-400 rounded-lg text-pink-500 border-dashed">
{!isLoading ? (
<span>No files changes found in the repo.</span>
) : (
<span className="text-gray-600">Fetching results...</span>
)}
</div>
);
}
return (
<>
{action ? (
<div
className="w-full h-full fixed flex mx-auto my-auto overflow-auto top-0 bottom-0 left-0 right-0"
id="operation-backdrop"
style={{ background: "rgba(0,0,0,0.6)", zIndex: "99" }}
onClick={(event) => {
if (event.target.id === "operation-backdrop") {
setAction("");
let closeViewCount = viewReload + 1;
setViewReload(closeViewCount);
setStagedItems([]);
setGitTrackedFiles([]);
setGitUntrackedFiles([]);
setList([]);
}
}}
>
{actionComponent(action)}
<div
className="w-14 h-14 mr-5 mt-6 rounded-full bg-red-500 text-white flex justify-center items-center shadow cursor-pointer fixed right-0 top-0"
onClick={() => {
setAction("");
const localReload = viewReload + 1;
setViewReload(localReload);
}}
>
<FontAwesomeIcon
className="flex text-center text-3xl my-auto"
icon={["fas", "times"]}
></FontAwesomeIcon>
</div>
</div>
) : null}
<div className="flex justify-between w-full mx-auto items-center my-10">
{actionButtons.map((item) => {
const { label, border, text, hoverBg, key, bg } = item;
return (
<div
className={`mx-4 shadow-lg w-1/3 text-center font-sans text-xl font-semibold rounded-lg p-3 border-b-4 rounded-b-xl transition hover:shadow-sm cursor-pointer ${bg} ${border} ${text} ${hoverBg}`}
key={key}
onClick={() => setAction(key)}
>
{label}
</div>
);
})}
</div>
{getTableData() && getTableData().length > 0 ? (
<div className="w-full shadow-md p-2 rounded-lg border border-blue-50 overflow-auto py-4">
<div className="flex items-center p-4 bg-gray-100 rounded">
{tableColumns.map((column, index) => {
return (
<div
key={column}
className={`font-sans font-semibold text-xl text-center text-gray-600 border-r-2 border-white ${
index === 0 ? "w-3/4" : "w-1/4"
}`}
>
{column}
</div>
);
})}
</div>
<div
className="block w-full overflow-auto"
style={{ height: "400px" }}
>
<div>
{isLoading ? (
<div className="text-center font-sans font-light p-4 text-2xl text-gray-600">
Loading modified file items...
</div>
) : (
<>
{getTableData() &&
getTableData().map((tableData, index) => {
return (
<div
className="flex justify-between items-center border-b p-2"
key={`tableItem-${index}`}
>
{tableData.map((data, index) => {
return (
<div
key={`${data}-${index}`}
title={index === 0 ? data : null}
className={`git-changed-item overflow-x-auto mx-auto font-sans text-gray-700 items-center align-middle my-auto border-r-2 border-gray-100 ${
index === 0
? "w-3/4 text-left"
: "w-1/4 text-center"
}`}
>
{data}
</div>
);
})}
</div>
);
})}
</>
)}
</div>
</div>
</div>
) : (
<>{noChangesComponent()}</>
)}
<>{stageItems && !isLoading ? getStagedFilesComponent() : null}</>
</>
);
}
Example #17
Source File: GitTrackedComponent.js From gitconvex with Apache License 2.0 | 4 votes |
export default function GitTrackedComponent(props) {
library.add(fab);
const [gitDiffFilesState, setGitDiffFilesState] = useState([]);
const [gitUntrackedFilesState, setGitUntrackedFilesState] = useState([]);
const [gitStagedFilesState, setGitStagedFilesState] = useState([]);
const [topMenuItemState, setTopMenuItemState] = useState("File View");
const topMenuItems = ["File View", "Git Difference", "Git Operations"];
const [noChangeMarker, setNoChangeMarker] = useState(false);
const [requestStateChange, setRequestChange] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const { dispatch } = useContext(ContextProvider);
const operationStateChangeHandler = () => {
setRequestChange(true);
};
const memoizedGitDiffView = useMemo(() => {
return <GitDiffViewComponent repoId={props.repoId}></GitDiffViewComponent>;
}, [props.repoId]);
const memoizedGitOperationView = useMemo(() => {
return (
<GitOperationComponent
repoId={props.repoId}
stateChange={operationStateChangeHandler}
></GitOperationComponent>
);
}, [props.repoId]);
useEffect(() => {
let apiEndPoint = globalAPIEndpoint;
setRequestChange(false);
setIsLoading(true);
setNoChangeMarker(false);
axios({
url: apiEndPoint,
method: "POST",
headers: {
"Content-type": "application/json",
},
data: {
query: `
query {
gitChanges(repoId: "${props.repoId}"){
gitUntrackedFiles
gitChangedFiles
gitStagedFiles
}
}
`,
},
})
.then((res) => {
if (res.data.data && !res.data.error) {
var apiData = res.data.data.gitChanges;
const {
gitChangedFiles,
gitUntrackedFiles,
gitStagedFiles,
} = apiData;
if (
(gitChangedFiles || gitUntrackedFiles) &&
(gitChangedFiles.length > 0 || gitUntrackedFiles.length > 0)
) {
setGitDiffFilesState([...gitChangedFiles]);
setGitUntrackedFilesState([...gitUntrackedFiles]);
setNoChangeMarker(false);
setIsLoading(false);
dispatch({
type: GIT_TRACKED_FILES,
payload: gitChangedFiles,
});
dispatch({
type: GIT_ACTION_TRACKED_FILES,
payload: [...gitChangedFiles],
});
dispatch({
type: GIT_ACTION_UNTRACKED_FILES,
payload: [...gitUntrackedFiles],
});
} else {
setNoChangeMarker(true);
if (gitStagedFiles.length === 0) {
setIsLoading(false);
}
if (gitStagedFiles.length > 0) {
setIsLoading(false);
setGitStagedFilesState([...gitStagedFiles]);
}
}
} else {
setIsLoading(false);
}
})
.catch((err) => {
console.log(err);
setIsLoading(false);
setNoChangeMarker(true);
});
}, [props.repoId, dispatch, topMenuItemState, requestStateChange]);
function diffPane() {
var deletedArtifacts = [];
var modifiedArtifacts = [];
if (gitDiffFilesState && gitDiffFilesState.length > 0) {
gitDiffFilesState.forEach((diffFile, index) => {
var splitFile = diffFile.split(",");
var flag = splitFile[0];
var name = splitFile[1];
var styleSelector = "p-1 ";
switch (flag) {
case "M":
styleSelector += "text-yellow-900 bg-yellow-100";
modifiedArtifacts.push(
<div
className="flex mx-auto justify-between items-center border-b border-white border-dotted"
key={name}
>
<div
className={`git-changed-item ${styleSelector} w-11/12 p-3 overflow-x-auto`}
title={name}
>
{name}
</div>
<div className="p-2 text-yellow-600 border-2 border-yellow-200 font-sans font-semibold bg-yellow-50 w-1/6 text-center">
MODIFIED
</div>
</div>
);
break;
case "D":
styleSelector += "text-red-900 bg-red-200";
deletedArtifacts.push(
<div
className="flex mx-auto justify-between items-center border-b border-white border-dotted"
key={name}
>
<div
className={`git-changed-item ${styleSelector} w-11/12 overflow-x-auto p-3`}
title={name}
>
{name}
</div>
<div className="p-2 text-red-600 border-2 border-red-200 font-sans font-semibold bg-red-50 w-1/6 text-center">
DELETED
</div>
</div>
);
break;
default:
styleSelector += "text-indigo-900 bg-indigo-200";
break;
}
});
return (
<>
{modifiedArtifacts} {deletedArtifacts}
</>
);
} else {
if (isLoading) {
return (
<div className="mx-auto w-3/4 my-4 p-2 border-b-4 border-dashed border-pink-300 rounded-md text-center font-sans font-semibold text-xl">
<span className="text-gray-400">
Fetching results from the server...
</span>
</div>
);
}
}
}
function untrackedPane() {
let untrackedFiles = [];
untrackedFiles = gitUntrackedFilesState
.map((entry) => entry)
.filter((item) => {
if (item) {
return true;
}
return false;
});
return untrackedFiles.map((entry, index) => {
return (
<div
className="flex items-center border-b border-white border-dotted"
key={`${entry}-${index}`}
>
<div
className="git-changed-item p-3 text-indigo-900 bg-indigo-100 w-11/12 overflow-x-auto"
title={entry}
>
{entry}
</div>
<div className="p-2 text-indigo-600 border-2 border-indigo-200 font-sans font-semibold bg-indigo-50 w-1/6 text-center">
UNTRACKED
</div>
</div>
);
});
}
function menuComponent() {
const FILE_VIEW = "File View";
const GIT_DIFFERENCE = "Git Difference";
const GIT_OPERATIONS = "Git Operations";
switch (topMenuItemState) {
case FILE_VIEW:
if (noChangeMarker && gitStagedFilesState.length) {
return (
<div className="mx-auto bg-yellow-100 w-full my-2 p-3 border-dashed rounded-lg shadow border-b-4 border-yellow-400 text-xl font-sans font-semibold text-center text-yellow-600">
No file changes to display. All changed have been staged
</div>
);
} else if (noChangeMarker) {
return (
<div className="mx-auto bg-pink-100 w-full my-2 p-3 border-dashed rounded-lg shadow border-b-4 border-pink-400 text-xl font-sans font-semibold text-center text-pink-600">
No file changes to display.
</div>
);
} else {
return (
<div className="shadow-md rounded-sm my-2 block justify-center mx-auto border border-gray-100">
{gitDiffFilesState && !isLoading ? (
diffPane()
) : (
<div className="rounded-lg shadow-md text-center text-indigo-700 text-2xl border-b-4 border-dashed border-indigo-300 p-4 font-sans">
Getting file based status...
</div>
)}
{gitUntrackedFilesState && !isLoading ? untrackedPane() : null}
</div>
);
}
case GIT_DIFFERENCE:
if (!noChangeMarker) {
return memoizedGitDiffView;
}
break;
case GIT_OPERATIONS:
return memoizedGitOperationView;
default:
return (
<div className="text-xl text-center"> Invalid Menu Selector! </div>
);
}
}
function presentChangeComponent() {
return (
<>
<div className="flex mx-auto my-4 w-11/12 justify-around font-sans font-semibold rounded-sm shadow-md cursor-pointer">
{topMenuItems.map((item) => {
let styleSelector = "w-full py-3 px-1 text-center border-r";
if (item === topMenuItemState) {
styleSelector = `${styleSelector} bg-blue-100 text-blue-700 border-b border-blue-600`;
} else {
styleSelector = `${styleSelector} bg-blue-500 text-white`;
}
return (
<div
className={`${styleSelector} hover:text-blue-700 hover:bg-blue-100 hover:border-b-2 hover:border-blue-700`}
key={item}
onClick={() => {
setTopMenuItemState(item);
// Resetting branch error in top bar component to prevent the error banner from getting displayed after switching the menu
props.resetBranchError();
}}
>
{item}
</div>
);
})}
</div>
</>
);
}
return (
<>
<style>
{`
.git-changed-item::-webkit-scrollbar {
background: rgba(0, 0, 0, 0);
width: 10px;
height: 1px;
border: solid 1px rgba(0, 0, 0, 0);
}
.git-changed-item::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0);
}
`}
</style>
{noChangeMarker ? (
<>
<div className="w-11/12 mx-auto block my-6">
{memoizedGitOperationView}
</div>
<div className="p-10 rounded-lg border-2 border-gray-100 w-3/4 mx-auto my-20">
<div>
<FontAwesomeIcon
icon={["fab", "creative-commons-zero"]}
className="flex text-7xl text-center text-gray-200 font-bold mx-auto h-full"
></FontAwesomeIcon>
</div>
<div className="block font-sans text-5xl text-gray-200 mx-auto text-center">
"0" changes in repo
</div>
</div>
</>
) : (
<>
{presentChangeComponent()}
<div className="w-11/12 mx-auto block my-6"> {menuComponent()} </div>
</>
)}
</>
);
}
Example #18
Source File: RepoCard.js From gitconvex with Apache License 2.0 | 4 votes |
export default function RepoCard(props) {
library.add(fab, fas);
const { repoData } = props;
const [repoFooterData, setRepoFooterData] = useState("");
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
let repoId = props.repoData.id;
const token = axios.CancelToken;
const source = token.source();
axios({
url: globalAPIEndpoint,
method: "POST",
headers: {
"Content-type": "application/json",
},
cancelToken: source.token,
data: {
query: `
query
{
gitRepoStatus(repoId:"${repoId}"){
gitCurrentBranch
gitTotalCommits
gitTotalTrackedFiles
}
}
`,
},
})
.then((res) => {
setLoading(false);
setRepoFooterData(res.data.data.gitRepoStatus);
})
.catch((err) => {
setLoading(false);
});
return () => {
source.cancel();
};
}, [props.repoData.id]);
const repoName = repoData.repoName;
var avatar = "";
if (repoName) {
if (repoName.split(" ").length > 1) {
let tempName = repoName.split(" ");
avatar = tempName[0].substring(0, 1) + tempName[1].substring(0, 1);
avatar = avatar.toUpperCase();
} else {
avatar = repoName.substring(0, 1).toUpperCase();
}
}
return (
<NavLink
to={`/dashboard/repository/${repoData.id}`}
className="mx-10 xl:w-96 lg:w-96 md:w-1/2 bg-indigo-400 border-gray-300 rounded-lg border cursor-pointer block my-6 p-6 shadow-md text-center hover:shadow-xl"
key={repoData.repoName}
>
<div className="bg-indigo-300 rounded text-5xl my-2 py-5 px-10 shadow text-center text-white">
{avatar}
</div>
<div className="border-indigo-300 border-dashed border-b-2 font-sans text-2xl my-4 pb-2 text-white">
{repoData.repoName}
</div>
<div className="rounded-md flex justify-center my-2 mx-auto shadow-sm text-center align-middle w-full">
{loading || !repoFooterData ? (
<div className="block mx-auto w-full bg-white rounded">
<div className="flex mx-auto my-6 text-center justify-center">
<InfiniteLoader
loadAnimation={loading || !repoFooterData}
></InfiniteLoader>
</div>
</div>
) : (
<>
<div className="bg-white border-indigo-300 flex items-center my-2 p-2 shadow-lg w-1/2 rounded-l-md">
<FontAwesomeIcon
className="my-auto"
icon={["fas", "grip-lines"]}
></FontAwesomeIcon>
<div className="items-center font-sans text-sm mx-2 text-center">
{repoFooterData && repoFooterData.gitTotalCommits ? (
<>{repoFooterData.gitTotalCommits} Commits</>
) : (
<>0 Commits</>
)}
</div>
</div>
<div className="bg-white border-indigo-300 flex items-center my-2 p-2 shadow-lg w-1/2">
<FontAwesomeIcon
className="my-auto"
icon={["fas", "file-alt"]}
></FontAwesomeIcon>
<div className="items-center font-sans text-sm mx-2 text-center">
{repoFooterData && repoFooterData.gitTotalTrackedFiles ? (
<>{repoFooterData.gitTotalTrackedFiles} Tracked Files</>
) : (
<>0 Tracked Files</>
)}
</div>
</div>
<div className="bg-white border-indigo-300 flex items-center my-2 p-2 shadow-lg w-1/2 rounded-r-md">
<FontAwesomeIcon
className="my-auto"
icon={["fas", "code-branch"]}
></FontAwesomeIcon>
<div className="items-center font-sans text-sm mx-2 text-center font-semibold">
{repoFooterData && repoFooterData.gitCurrentBranch ? (
<>{repoFooterData.gitCurrentBranch}</>
) : (
<>No Branches Available</>
)}
</div>
</div>
</>
)}
</div>
</NavLink>
);
}
Example #19
Source File: FileExplorerComponent.js From gitconvex with Apache License 2.0 | 4 votes |
export default function FileExplorerComponent(props) {
library.add(fab, fas);
const [gitRepoFiles, setGitRepoFiles] = useState([]);
const [codeViewToggle, setCodeViewToggle] = useState(false);
const [gitFileBasedCommits, setGitFileBasedCommits] = useState([]);
const [directoryNavigator, setDirectoryNavigator] = useState([]);
const [codeViewItem, setCodeViewItem] = useState("");
const [selectionIndex, setSelectionIndex] = useState(0);
const [isEmpty, setIsEmpty] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [cwd, setCwd] = useState("");
const { repoIdState } = props;
const memoizedCodeFileViewComponent = useMemo(() => {
return (
<CodeFileViewComponent
repoId={repoIdState}
fileItem={codeViewItem}
commitMessage={gitFileBasedCommits[selectionIndex]}
></CodeFileViewComponent>
);
}, [repoIdState, codeViewItem, gitFileBasedCommits, selectionIndex]);
function filterNullCommitEntries(gitTrackedFiles, gitFileBasedCommit) {
let localGitCommits = gitFileBasedCommit;
let localTrackedFiles = gitTrackedFiles.filter((item, index) => {
if (item) {
return true;
} else {
localGitCommits[index] = "";
return false;
}
});
localGitCommits = localGitCommits.filter((commit) => commit);
setGitRepoFiles([...localTrackedFiles]);
setGitFileBasedCommits([...localGitCommits]);
}
useEffect(() => {
const repoId = props.repoIdState;
setIsEmpty(false);
setIsLoading(true);
axios({
url: globalAPIEndpoint,
method: "POST",
headers: {
"Content-type": "application/json",
},
data: {
query: `
query
{
gitFolderContent(repoId:"${repoId}", directoryName: ""){
trackedFiles
fileBasedCommits
}
}
`,
},
})
.then((res) => {
setIsLoading(false);
const {
trackedFiles,
fileBasedCommits,
} = res.data.data.gitFolderContent;
if (trackedFiles.length === 0 || fileBasedCommits.length === 0) {
setIsEmpty(true);
return;
}
if (trackedFiles && fileBasedCommits) {
filterNullCommitEntries(trackedFiles, fileBasedCommits);
}
})
.catch((err) => {
console.log(err);
setIsLoading(false);
});
}, [props]);
function directorySeparatorRemover(directoryPath) {
if (directoryPath.match(/.\/./gi)) {
directoryPath = directoryPath.split("/")[
directoryPath.split("/").length - 1
];
} else if (directoryPath.match(/[^\\]\\[^\\]/gi)) {
directoryPath = directoryPath.split("\\")[
directoryPath.split("\\").length - 1
];
} else if (directoryPath.match(/.\\\\./gi)) {
directoryPath = directoryPath.split("\\\\")[
directoryPath.split("\\\\").length - 1
];
}
return directoryPath;
}
const fetchFolderContent = (
directoryName,
slicePosition,
sliceIndicator,
homeIndicator
) => {
if (repoIdState) {
setGitRepoFiles([]);
setGitFileBasedCommits([]);
let localDirNavigator = directoryNavigator;
if (sliceIndicator) {
let slicedDirectory = localDirNavigator.slice(0, slicePosition);
if (slicedDirectory.length > 0) {
directoryName = slicedDirectory.join("/") + "/" + directoryName;
}
}
setCwd(directoryName);
setIsLoading(true);
axios({
url: globalAPIEndpoint,
method: "POST",
headers: {
"Content-type": "application/json",
},
data: {
query: `
query
{
gitFolderContent(repoId:"${repoIdState}", directoryName: "${directoryName}"){
trackedFiles
fileBasedCommits
}
}
`,
},
})
.then((res) => {
setIsLoading(false);
if (res.data.data && !res.data.error) {
const localFolderContent = res.data.data.gitFolderContent;
filterNullCommitEntries(
localFolderContent.trackedFiles,
localFolderContent.fileBasedCommits
);
directoryName = directorySeparatorRemover(directoryName);
if (homeIndicator) {
setDirectoryNavigator([]);
return;
}
if (directoryNavigator.length === 0) {
setDirectoryNavigator([directoryName]);
} else {
if (
sliceIndicator &&
slicePosition < directoryNavigator.length - 1
) {
const iterator =
directoryNavigator.length - (slicePosition + 1);
for (let i = 0; i < iterator; i++) {
localDirNavigator.pop();
}
setDirectoryNavigator([...localDirNavigator]);
} else {
setDirectoryNavigator([...directoryNavigator, directoryName]);
}
}
} else {
setIsLoading(false);
console.log(
"ERROR: Error occurred while fetching the folder content!"
);
}
})
.catch((err) => {
setIsLoading(false);
if (err) {
console.log(
"ERROR: Error occurred while fetching the folder content!",
err
);
}
});
}
};
const gitTrackedFileComponent = () => {
var fileIcon;
if (gitRepoFiles && gitRepoFiles.length > 0) {
var formattedFiles = [];
var directoryEntry = [];
var fileEntry = [];
gitRepoFiles.forEach(async (entry, index) => {
const splitEntry = entry.split(":");
if (splitEntry[1] && splitEntry[1].includes("directory")) {
let directoryPath = directorySeparatorRemover(splitEntry[0]);
directoryEntry.push(
<div
className="block w-full p-2 border-b border-gray-200"
key={`directory-key-${uuid()}`}
>
<div className="flex cursor-pointer items-center">
<div className="w-1/6">
<FontAwesomeIcon
icon={["fas", "folder"]}
className="font-sans text-xl"
></FontAwesomeIcon>
</div>
<div
className="font-sans w-1/2 text-gray-600 text-xl mx-3 hover:text-indigo-400"
onClick={(event) => {
fetchFolderContent(splitEntry[0], 0, false);
}}
>
{directoryPath}
</div>
<div className="w-3/5 p-2 overflow-hidden truncate rounded-lg mx-auto text-left bg-green-200 text-green-900">
{gitFileBasedCommits[index]}
</div>
</div>
</div>
);
} else if (splitEntry[1] && splitEntry[1].includes("File")) {
if (splitEntry[0] === "LICENSE") {
fileIcon = require("../../../../../assets/icons/file_type_license.svg");
} else {
fileIcon = require("../../../../../assets/icons/" +
getIconForFile(splitEntry[0]));
}
fileEntry.push(
<div
className="block w-full p-2 border-b border-gray-200"
key={`file-key-${uuid()}`}
>
<div className="flex items-center align-middle cursor-pointer">
<div className="w-1/6">
<img
src={fileIcon.default}
style={{
width: "26px",
filter: "grayscale(30%)",
}}
alt={fileIcon.default}
></img>
</div>
<div
className="font-sans w-1/2 text-gray-700 text-xl mx-3 hover:text-indigo-400"
onClick={() => {
setSelectionIndex(index);
if (cwd === "" || cwd === "/") {
setCodeViewItem(splitEntry[0]);
} else {
setCodeViewItem(cwd + "/" + splitEntry[0]);
}
setCodeViewToggle(true);
}}
>
{splitEntry[0]}
</div>
<div className="w-3/5 p-2 overflow-hidden truncate rounded-lg mx-auto text-left bg-indigo-200 text-indigo-900">
{gitFileBasedCommits[index]}
</div>
</div>
</div>
);
}
});
formattedFiles.push(directoryEntry);
formattedFiles.push(fileEntry);
return (
<div
className="block mx-auto justify-center p-2"
style={{
color: "#79b8ff",
}}
key="repo-key"
>
<div className="flex w-full justify-around p-2 mx-auto pb-4 border-b border-blue-400">
<div className="w-1/6"></div>
<div className="w-2/4 font-sans font-semibold">
File / Directory
</div>
<div className="w-2/4 font-sans font-semibold">Latest commit</div>
</div>
{formattedFiles}
</div>
);
}
};
return (
<>
{isLoading ? (
<>
<div className="flex justify-center mx-auto my-2 w-3/4">
<div className="w-full mx-auto text-2xl text-center font-sans font-semibold text-gray-700 border-b-2 border-dashed border-gray-400">
Loading tracked files...
</div>
</div>
<div className="flex mx-auto my-6 text-center justify-center">
<InfiniteLoader
loadAnimation={!gitRepoFiles.length}
></InfiniteLoader>
</div>
</>
) : (
<>
{codeViewToggle ? (
<div
className="fixed flex w-full h-full top-0 left-0 right-0 overflow-auto"
id="code-view__backdrop"
style={{ background: "rgba(0,0,0,0.5)", zIndex: 99 }}
onClick={(event) => {
if (event.target.id === "code-view__backdrop") {
setCodeViewToggle(false);
}
}}
>
<div
className="w-14 h-14 mr-5 mt-6 rounded-full bg-red-500 text-white flex justify-center items-center shadow cursor-pointer fixed right-0 top-0"
onClick={() => {
setCodeViewToggle(false);
}}
>
<FontAwesomeIcon
className="flex text-center text-3xl my-auto"
icon={["fas", "times"]}
></FontAwesomeIcon>
</div>
<div className="w-full h-full mx-auto my-auto flex mt-4 mb-10">
{memoizedCodeFileViewComponent}
</div>
</div>
) : null}
<div>
<div
className="w-1/6 text-gray-600 cursor-pointer border-b-2 border-dashed text-center flex justify-center gap-4 p-3 rounded mx-6 myy-auto items-center align-middle text-xl"
onClick={() => {
fetchFolderContent("", 0, false, true);
}}
>
<div>
<FontAwesomeIcon icon={["fas", "home"]}></FontAwesomeIcon>
</div>
<div>Home</div>
<div className="text-2xl font-sans text-blue-400">./</div>
</div>
{directoryNavigator && gitRepoFiles && gitRepoFiles.length > 0 ? (
<div className="mx-6 p-3 flex font-sans justify-start items-center gap-4">
<div
className="flex p-4 w-3/4 gap-4 items-center break-words overflow-x-auto"
id="repoFolderNavigator"
>
{directoryNavigator.map((item, index) => {
return (
<div
className="flex items-center justify-start gap-2"
key={item + "-" + index}
>
<div
className={`${
index !== directoryNavigator.length - 1
? "text-blue-400 cursor-pointer font-semibold hover:text-blue-500 underline"
: ""
} text-xl`}
onClick={() => {
if (index !== directoryNavigator.length - 1) {
fetchFolderContent(item, index, true);
}
}}
>
{item}
</div>
<div>/</div>
</div>
);
})}
</div>
</div>
) : null}
<div className="block w-11/12 my-6 mx-auto justify-center p-6 rounded-lg bg-white shadow overflow-auto border">
{!isEmpty ? (
gitTrackedFileComponent()
) : (
<div className="flex w-3/4 gap-4 mx-auto items-center align-middle justify-center rounded-lg text-gray-500 text-center border-b-4 text-2xl border-dashed p-1 border-gray-300">
<div>
<FontAwesomeIcon icon={["fas", "unlink"]}></FontAwesomeIcon>
</div>
<div>No Tracked Files in the directory!</div>
</div>
)}
</div>
</div>
</>
)}
</>
);
}
Example #20
Source File: CommitLogComponent.js From gitconvex with Apache License 2.0 | 4 votes |
export default function RepositoryCommitLogComponent(props) {
library.add(fab, fas, far);
const [commitLogs, setCommitLogs] = useState([]);
const [isCommitEmpty, setIsCommitEmpty] = useState(false);
const [skipLimit, setSkipLimit] = useState(0);
const [totalCommitCount, setTotalCommitCount] = useState(0);
const [isLoading, setIsLoading] = useState(false);
const [excessCommit, setExcessCommit] = useState(false);
const [searchKey, setSearchKey] = useState("");
const [viewReload, setViewReload] = useState(0);
const [searchWarning, setSearchWarning] = useState(false);
const [referenceCommitHash, setReferenceCommitHash] = useState("");
const searchRef = useRef();
const searchOptionRef = useRef();
const debouncedSearch = useRef(
debounce(commitSearchHandler, 1500, { maxWait: 2000 })
).current;
const searchOptions = ["Commit Hash", "Commit Message", "User"];
useEffect(() => {
setIsLoading(true);
setSearchWarning(false);
axios({
url: globalAPIEndpoint,
method: "POST",
data: {
query: `
query {
gitCommitLogs(repoId: "${props.repoId}", referenceCommit: "") {
totalCommits
commits{
commitTime
hash
author
commitMessage
commitFilesCount
}
}
}
`,
},
})
.then((res) => {
setIsLoading(false);
if (res.data.data) {
const { commits, totalCommits } = res.data.data.gitCommitLogs;
if (totalCommits <= 10) {
setExcessCommit(false);
} else {
setExcessCommit(true);
}
setTotalCommitCount(totalCommits);
if (commits && commits.length > 0) {
setCommitLogs([...commits]);
const len = commits.length;
setReferenceCommitHash(commits[len - 1].hash);
} else {
setIsCommitEmpty(true);
}
}
})
.catch((err) => {
setIsLoading(false);
if (err) {
setIsCommitEmpty(true);
console.log(err);
}
});
}, [props, viewReload]);
function fetchCommitLogs() {
setIsLoading(true);
setSearchWarning(false);
let localLimit = 0;
localLimit = skipLimit + 10;
setSkipLimit(localLimit);
axios({
url: globalAPIEndpoint,
method: "POST",
data: {
query: `
query{
gitCommitLogs(repoId:"${props.repoId}", referenceCommit: "${referenceCommitHash}"){
totalCommits
commits{
commitTime
hash
author
commitMessage
commitFilesCount
}
}
}
`,
},
})
.then((res) => {
setIsLoading(false);
if (totalCommitCount - localLimit <= 10) {
setExcessCommit(false);
}
if (res.data.data) {
const { commits, totalCommits } = res.data.data.gitCommitLogs;
setTotalCommitCount(totalCommits);
if (commits && commits.length > 0) {
setCommitLogs([...commitLogs, ...commits]);
const len = commits.length;
setReferenceCommitHash(commits[len - 1].hash);
} else {
setIsCommitEmpty(true);
}
}
})
.catch((err) => {
setIsLoading(false);
if (err) {
setIsCommitEmpty(true);
console.log(err);
}
});
}
function fetchCommitFiles(commitHash, arrowTarget) {
const parentDivId = `commitLogCard-${commitHash}`;
const targetDivId = `commitFile-${commitHash}`;
const targetDiv = document.createElement("div");
targetDiv.id = targetDivId;
const parentDiv = document.getElementById(parentDivId);
parentDiv.append(targetDiv);
const unmountHandler = () => {
ReactDOM.unmountComponentAtNode(
document.getElementById("closeBtn-" + commitHash)
);
ReactDOM.unmountComponentAtNode(document.getElementById(targetDivId));
arrowTarget.classList.remove("hidden");
};
ReactDOM.render(
<CommitLogFileCard
repoId={props.repoId}
commitHash={commitHash}
unmountHandler={unmountHandler}
></CommitLogFileCard>,
document.getElementById(targetDivId)
);
const closeArrow = (
<div
className="text-center mx-auto text-3xl font-sans font-light text-gray-600 items-center align-middle cursor-pointer"
onClick={(event) => {
unmountHandler();
}}
>
<FontAwesomeIcon icon={["fas", "angle-up"]}></FontAwesomeIcon>
</div>
);
const closeBtn = document.createElement("div");
const closeBtnId = "closeBtn-" + commitHash;
closeBtn.id = closeBtnId;
parentDiv.append(closeBtn);
ReactDOM.render(closeArrow, document.getElementById(closeBtnId));
}
function commitSearchHandler() {
setIsLoading(true);
setTotalCommitCount(0);
setCommitLogs([]);
const searchQuery = searchRef.current.value;
let searchOption = "";
switch (searchOptionRef.current.value) {
case "Commit Hash":
searchOption = "hash";
break;
case "Commit Message":
searchOption = "message";
break;
case "User":
searchOption = "user";
break;
default:
searchOption = "message";
break;
}
if (searchQuery) {
axios({
url: globalAPIEndpoint,
method: "POST",
data: {
query: `
query{
searchCommitLogs(repoId:"${props.repoId}",searchType:"${searchOption}",searchKey:"${searchQuery}"){
hash
author
commitTime
commitMessage
commitFilesCount
}
}
`,
},
})
.then((res) => {
if (res.data.data) {
const { searchCommitLogs } = res.data.data;
if (searchCommitLogs && searchCommitLogs.length > 0) {
setIsCommitEmpty(false);
setExcessCommit(false);
setCommitLogs([...searchCommitLogs]);
setTotalCommitCount(searchCommitLogs.length);
setIsLoading(false);
} else {
setIsCommitEmpty(true);
setCommitLogs([]);
setTotalCommitCount(0);
setIsLoading(false);
setSearchWarning(true);
}
}
})
.catch((err) => {
console.log(err);
setIsLoading(false);
setCommitLogs([]);
});
} else {
setViewReload(viewReload + 1);
setIsLoading(false);
}
}
function fallBackComponent(message) {
return (
<div className="p-6 rounded-md shadow-sm block justify-center mx-auto my-auto w-3/4 h-full text-center text-2xl text-indigo-500">
<div className="flex w-full h-full mx-auto my-auto">
<div className="block my-auto mx-auto bg-white w-full p-6 rounded-lg shadow">
<div className="text-2xl text-center font-sans font-semibold text-indigo-800 border-b-2 border-dashed border-indigo-500 p-1">
{message}
</div>
{searchWarning ? (
<div className="my-4 mx-auto rounded shadow p-4 text-center font-sans text-yellow-800 font-light bg-yellow-50 border-b-4 border-dashed border-yellow-200 text-md">
Make sure if you are searching with the right category and the
right search query
</div>
) : null}
{isLoading ? (
<div className="flex mx-auto my-6 text-center justify-center">
<InfiniteLoader loadAnimation={isLoading}></InfiniteLoader>
</div>
) : null}
</div>
</div>
</div>
);
}
function searchbarComponent() {
return (
<div className="my-4 w-full rounded-lg bg-white shadow-inner flex gap-4 justify-between items-center">
<select
defaultValue="default-search"
id="searchOption"
ref={searchOptionRef}
className="w-1/4 flex p-4 items-center bg-indigo-400 text-white cursor-pointer rounded-l-md text-lg font-sans font-semibold outline-none"
>
<option value="default-search" hidden disabled>
Search for...
</option>
{searchOptions.map((item) => {
return (
<option key={item} value={item}>
{item}
</option>
);
})}
</select>
<div className="w-3/4 rounded-r-md">
<input
ref={searchRef}
type="text"
className="w-5/6 outline-none text-lg font-light font-sans"
placeholder="What are you looking for?"
value={searchKey}
onChange={(event) => {
setSearchKey(event.target.value);
debouncedSearch();
}}
/>
</div>
<div
className="w-20 bg-gray-200 p-3 mx-auto my-auto text-center rounded-r-lg hover:bg-gray-400 cursor-pointer"
onClick={() => {
commitSearchHandler();
}}
>
<FontAwesomeIcon
icon={["fas", "search"]}
className="text-3xl text-gray-600"
></FontAwesomeIcon>
</div>
</div>
);
}
return (
<>
{searchbarComponent()}
{(isCommitEmpty || !commitLogs || !totalCommitCount) && !isLoading
? fallBackComponent("No Commit Logs found")
: null}
{commitLogs &&
commitLogs.map((commit) => {
const {
hash,
author,
commitTime,
commitMessage,
commitFilesCount,
} = commit;
let commitRelativeTime = relativeCommitTimeCalculator(commitTime);
const formattedCommitTime = format(
new Date(commitTime),
"MMMM dd, yyyy"
);
return (
<div
id={`commitLogCard-${hash}`}
className="p-6 rounded-lg block shadow-md justify-center mx-auto my-4 bg-white w-full border-b-8 border-indigo-400"
key={hash}
>
<div className="flex justify-between text-indigo-400">
<div className="text-2xl font-sans mx-auto">
<FontAwesomeIcon
icon={["fas", "calendar-alt"]}
></FontAwesomeIcon>
<span className="border-b-2 border-dashed mx-2">
{formattedCommitTime}
</span>
</div>
<div className="h-auto p-1 border-r"></div>
<div className="text-2xl font-sans mx-auto">
<FontAwesomeIcon
icon={["fab", "slack-hash"]}
></FontAwesomeIcon>
<span className="border-b-2 border-dashed mx-2">
{hash.substring(0, 7)}
</span>
</div>
<div className="h-auto p-1 border-r"></div>
<div className="text-2xl font-sans mx-auto">
<FontAwesomeIcon
icon={["fas", "user-ninja"]}
></FontAwesomeIcon>
<span className="border-b-2 border-dashed mx-2 truncate">
{author}
</span>
</div>
</div>
<div className="font-sans font-semibold text-2xl my-4 text-gray-500 p-3 flex justify-evenly items-center">
<div className="w-1/8">
<FontAwesomeIcon
icon={["fas", "code"]}
className="text-3xl"
></FontAwesomeIcon>
</div>
<div className="w-5/6 mx-3">{commitMessage}</div>
</div>
<div className="w-11/12 flex justify-between mx-auto mt-4 font-sans text-xl text-gray-500">
<div className="w-1/3 flex justify-center my-auto items-center align-middle">
<div>
<FontAwesomeIcon icon={["far", "clock"]}></FontAwesomeIcon>
</div>
<div className="mx-2 border-dashed border-b-4">
{commitRelativeTime}
</div>
</div>
<div
className="w-1/3 flex justify-around my-auto font-sans text-3xl font-light pt-10 cursor-pointer text-gray-500"
onClick={(event) => {
if (commitFilesCount) {
event.currentTarget.classList.add("hidden");
fetchCommitFiles(hash, event.currentTarget);
}
}}
>
{commitFilesCount ? (
<FontAwesomeIcon
icon={["fas", "angle-down"]}
></FontAwesomeIcon>
) : (
<FontAwesomeIcon
icon={["fas", "dot-circle"]}
className="text-xl text-gray-200"
></FontAwesomeIcon>
)}
</div>
<div className="w-1/3 flex justify-center my-auto items-center align-middle">
<div>
<FontAwesomeIcon
icon={["far", "plus-square"]}
></FontAwesomeIcon>
</div>
<div className="mx-2 border-dashed border-b-4">
{commitFilesCount ? (
`${commitFilesCount} Files`
) : (
<span className="text-gray-500">No Changed Files</span>
)}
</div>
</div>
</div>
</div>
);
})}
{excessCommit ? (
<div
className="fixed flex bottom-0 right-0 w-16 h-16 mx-auto p-6 rounded-full shadow-md text-center bg-indigo-500 text-white text-2xl mb-6 mr-6 cursor-pointer"
title="Click to load commits"
onClick={() => {
if (commitLogs.length > skipLimit) {
fetchCommitLogs();
}
}}
>
<FontAwesomeIcon
icon={["fas", "angle-double-down"]}
></FontAwesomeIcon>
</div>
) : null}
{isLoading && totalCommitCount ? (
<div className="my-4 rounded-lg p-3 bg-gray-100 text-lg font-semibold font-sans text-gray-700 text-center mx-auto">
Loading {totalCommitCount - skipLimit} more commits...
<div className="flex mx-auto my-6 text-center justify-center">
<InfiniteLoader loadAnimation={isLoading}></InfiniteLoader>
</div>
</div>
) : null}
{!isCommitEmpty && commitLogs.length === 0 && isLoading
? fallBackComponent("Loading commits...")
: null}
</>
);
}
Example #21
Source File: RepoLeftPaneComponent.js From gitconvex with Apache License 2.0 | 4 votes |
export default function RepoLeftPaneComponent(props) {
library.add(fab, fas);
let {
gitRemoteHost,
gitRemoteData,
isMultiRemote,
multiRemoteCount,
showCommitLogsView,
actionTrigger,
} = props;
useEffect(() => {}, [props]);
const getRemoteLogo = () => {
let remoteLogo = "";
if (gitRemoteHost.match(/github/i)) {
remoteLogo = (
<FontAwesomeIcon
icon={["fab", "github"]}
className="text-4xl text-center text-pink-500"
></FontAwesomeIcon>
);
} else if (gitRemoteHost.match(/gitlab/i)) {
remoteLogo = (
<FontAwesomeIcon
icon={["fab", "gitlab"]}
className="text-4xl text-center text-pink-400"
></FontAwesomeIcon>
);
} else if (gitRemoteHost.match(/bitbucket/i)) {
remoteLogo = (
<FontAwesomeIcon
icon={["fab", "bitbucket"]}
className="text-4xl text-center text-pink-400"
></FontAwesomeIcon>
);
} else if (gitRemoteHost.match(/codecommit/i)) {
remoteLogo = (
<FontAwesomeIcon
icon={["fab", "aws"]}
className="text-4xl text-center text-pink-400"
></FontAwesomeIcon>
);
} else {
remoteLogo = (
<FontAwesomeIcon
icon={["fab", "git-square"]}
className="text-4xl text-center text-pink-400"
></FontAwesomeIcon>
);
}
return remoteLogo;
};
const remoteUrl = () => {
let remoteData = "";
if (gitRemoteData) {
if (gitRemoteData.match(/(^https)/gi)) {
remoteData = (
<a href={gitRemoteData} target="_blank" rel="noopener noreferrer">
{gitRemoteData}
</a>
);
} else {
remoteData = <>{gitRemoteData}</>;
}
} else {
remoteData = " ";
}
return remoteData;
};
return (
<>
{props.received ? (
<div className="border-gray-300 rounded-md border-dotted border-2 block my-6 mx-auto p-1 shadow-sm w-11/12 xl:w-1/2 lg:w-3/4 md:w-11/12 sm:w-11/12">
<div className="block mx-auto my-6">
<div className="flex items-center justify-evenly">
<div className="text-lg text-gray-600 w-1/4">Remote Host</div>
<div className="flex justify-around items-center align-middle w-1/2">
<div className="w-3/4 shadow rounded-md border-dashed border cursor-pointer flex items-center justify-center my-auto p-4 align-middle">
{gitRemoteHost ? (
<div className="mx-2">{getRemoteLogo()}</div>
) : null}
<div
className={`${
gitRemoteHost !== "No Remote Host Available"
? "text-xl border-gray-300 border-dashed border-b text-center text-gray-800 w-3/4"
: "text-base font-sans font-light text-gray-600 text-center"
}`}
>
{gitRemoteHost}
</div>
</div>
<div className="w-1/4">
<div
id="addRemote"
className="rounded-full cursor-pointer items-center h-10 text-2xl mx-auto shadow text-center text-white align-middle w-10 bg-indigo-400 hover:bg-indigo-500"
onMouseEnter={(event) => {
let popUp = document.createElement("div");
popUp.className =
"text-gray-600 bg-white border-gray-300 p-2 rounded w-40 text-center border text-sm mt-2 mb-2 -ml-10 absolute";
popUp.innerHTML = `Click here to configure remote repo`;
event.currentTarget.insertAdjacentElement(
"afterend",
popUp
);
}}
onMouseLeave={(event) => {
if (event.currentTarget.parentNode.children[1]) {
event.currentTarget.parentNode.children[1].remove();
}
}}
onClick={() => {
actionTrigger(actionType.ADD_REMOTE_REPO);
}}
>
<FontAwesomeIcon
icon={faTools}
className="text-xl text-center text-white"
></FontAwesomeIcon>
</div>
</div>
</div>
</div>
<div className="remote flex justify-evenly my-4">
<div className="text-lg text-gray-600 w-1/4">
{`${gitRemoteHost} URL`}
</div>
<div className="cursor-pointer text-blue-400 break-words w-1/2 hover:text-blue-500">
{remoteUrl()}
</div>
</div>
{isMultiRemote ? (
<div className=" flex justify-evenly my-2">
<div className="font-sans text-gray-800 font-semibold w-1/4 border-dotted border-b-2 border-gray-200">
Entry truncated!
</div>
<div className="w-1/2 border-dotted border-b-2 border-gray-200">
{`Remote repos : ${multiRemoteCount}`}
</div>
</div>
) : null}
</div>
<div className="block my-6 mx-auto">
<div
className="p-3 text-gray-600 text-center w-3/4 mx-auto rounded-md shadow-md bg-yellow-200 text-whtie font-sans font-semibold text-xl hover:bg-yellow-100 hover:shadow-sm cursor-pointer transition"
onClick={(event) => {
showCommitLogsView();
}}
>
SHOW COMMIT LOGS
</div>
</div>
</div>
) : null}
</>
);
}
Example #22
Source File: RepositoryDetails.js From gitconvex with Apache License 2.0 | 4 votes |
export default function RepositoryDetails(props) {
library.add(fab, fas);
const [gitRepoStatus, setGitRepoStatus] = useState({});
const [repoFetchFailed, setRepoFetchFailed] = useState(false);
const [repoIdState, setRepoIdState] = useState("");
const [showCommitLogs, setShowCommitLogs] = useState(false);
const [isMultiRemote, setIsMultiRemote] = useState(false);
const [multiRemoteCount, setMultiRemoteCount] = useState(0);
const [backdropToggle, setBackdropToggle] = useState(false);
const [viewReload, setViewReload] = useState(false);
const [codeViewToggle, setCodeViewToggle] = useState(false);
const [selectedBranch, setSelectedBranch] = useState("");
const [currentBranch, setCurrentBranch] = useState("");
const [action, setAction] = useState("");
const [loading, setLoading] = useState(false);
const closeBackdrop = (toggle) => {
setBackdropToggle(!toggle);
};
const showCommitLogsView = () => {
setShowCommitLogs(true);
};
const actionTrigger = (actionType) => {
setAction(actionType);
setBackdropToggle(true);
};
const memoizedFolderExplorer = useMemo(() => {
return (
<FileExplorerComponent repoIdState={repoIdState}></FileExplorerComponent>
);
}, [repoIdState]);
const memoizedCommitLogComponent = useMemo(() => {
return (
<>
<CommitLogComponent repoId={repoIdState}></CommitLogComponent>
</>
);
}, [repoIdState]);
const memoizedFetchRemoteComponent = useMemo(() => {
return (
<FetchPullActionComponent
repoId={repoIdState}
actionType="fetch"
></FetchPullActionComponent>
);
}, [repoIdState]);
const memoizedPullRemoteComponent = useMemo(() => {
return (
<FetchPullActionComponent
repoId={repoIdState}
actionType="pull"
></FetchPullActionComponent>
);
}, [repoIdState]);
const memoizedSwitchBranchComponent = useMemo(() => {
return (
<SwitchBranchComponent
repoId={repoIdState}
branchName={selectedBranch}
closeBackdrop={closeBackdrop}
switchReloadView={() => {
setViewReload(true);
}}
></SwitchBranchComponent>
);
}, [repoIdState, selectedBranch]);
const memoizedBranchListComponent = useMemo(() => {
return (
<BranchListComponent
repoId={repoIdState}
currentBranch={currentBranch}
></BranchListComponent>
);
}, [repoIdState, currentBranch]);
const memoizedAddRemoteRepoComponent = useMemo(() => {
return (
<AddRemoteRepoComponent repoId={repoIdState}></AddRemoteRepoComponent>
);
}, [repoIdState]);
useEffect(() => {
setViewReload(false);
setCodeViewToggle(false);
setLoading(true);
const endpointURL = globalAPIEndpoint;
if (props.parentProps.location) {
const repoId = props.parentProps.location.pathname.split(
"/repository/"
)[1];
setRepoIdState(repoId);
axios({
url: endpointURL,
method: "POST",
headers: {
"Content-type": "application/json",
},
data: {
query: `
query
{
gitRepoStatus(repoId:"${repoId}"){
gitRemoteData
gitRemoteHost
gitRepoName
gitBranchList
gitCurrentBranch
gitTotalCommits
gitLatestCommit
gitTotalTrackedFiles
}
}
`,
},
})
.then((res) => {
setLoading(false);
if (res.data && res.data.data && !res.data.error) {
const localRepoStatus = res.data.data.gitRepoStatus;
let gitRemoteLocal = localRepoStatus.gitRemoteData;
setCurrentBranch(localRepoStatus.gitCurrentBranch);
if (gitRemoteLocal.includes("||")) {
setIsMultiRemote(true);
localRepoStatus.gitRemoteData = gitRemoteLocal.split("||")[0];
setIsMultiRemote(true);
setMultiRemoteCount(gitRemoteLocal.split("||").length);
} else {
setIsMultiRemote(false);
setMultiRemoteCount(0);
}
setGitRepoStatus(localRepoStatus);
} else {
setRepoFetchFailed(true);
}
})
.catch((err) => {
setLoading(false);
if (err) {
console.log("API GitStatus error occurred : " + err);
setRepoFetchFailed(true);
}
});
}
}, [props.parentProps, viewReload]);
let {
gitRemoteData,
gitRepoName,
gitBranchList,
gitCurrentBranch,
gitRemoteHost,
gitTotalCommits,
gitLatestCommit,
} = gitRepoStatus;
const switchBranchHandler = (branchName) => {
setBackdropToggle(true);
setAction("switchbranch");
setSelectedBranch(branchName);
};
const actionComponentPicker = () => {
switch (action) {
case "fetch":
return memoizedFetchRemoteComponent;
case "pull":
return memoizedPullRemoteComponent;
case "addRemoteRepo":
return memoizedAddRemoteRepoComponent;
case "addBranch":
return <AddBranchComponent repoId={repoIdState}></AddBranchComponent>;
case "switchbranch":
return memoizedSwitchBranchComponent;
case "listBranch":
return memoizedBranchListComponent;
default:
return null;
}
};
return (
<>
{loading ? (
<LoadingHOC
message="Fetching repo details..."
loading={loading}
></LoadingHOC>
) : null}
{showCommitLogs ? (
<>
<div
className="fixed w-full h-full top-0 left-0 right-0 flex overflow-auto"
id="commit-log__backdrop"
style={{ background: "rgba(0,0,0,0.5)", zIndex: 99 }}
onClick={(event) => {
if (event.target.id === "commit-log__backdrop") {
setShowCommitLogs(false);
}
}}
>
<div
id="commit-log__cards"
className="w-full xl:w-3/4 lg:w-5/6 md:w-11/12 sm:w-11/12 h-full block mx-auto my-auto mt-10 mb-10"
>
{memoizedCommitLogComponent}
</div>
<div
className="w-14 h-14 mr-5 mt-6 rounded-full bg-red-500 text-white flex justify-center items-center shadow cursor-pointer fixed right-0 top-0"
onClick={() => {
setShowCommitLogs(false);
}}
>
<FontAwesomeIcon
className="flex text-center text-3xl my-auto"
icon={["fas", "times"]}
></FontAwesomeIcon>
</div>
</div>
</>
) : null}
{backdropToggle || codeViewToggle ? (
<div
className="flex h-full overflow-auto fixed inset-x-0 top-0 w-full z-40"
id="repo-backdrop"
style={{ background: "rgba(0,0,0,0.7)", zIndex: "99" }}
onClick={(event) => {
if (event.target.id === "repo-backdrop") {
setBackdropToggle(false);
setAction("");
}
}}
>
<>{action ? actionComponentPicker() : null}</>
<div
className="w-14 h-14 mr-5 mt-6 rounded-full bg-red-500 text-white flex justify-center items-center shadow cursor-pointer fixed top-0 right-0"
onClick={() => {
setBackdropToggle(false);
setCodeViewToggle(false);
setViewReload(true);
setAction("");
}}
>
<FontAwesomeIcon
className="flex text-center text-3xl my-auto"
icon={["fas", "times"]}
></FontAwesomeIcon>
</div>
</div>
) : null}
<>
{!loading && gitRepoStatus && !repoFetchFailed ? (
<div className="overflow-auto rounded-lg justify-evenly h-full mx-auto p-6 w-full">
<div className="flex px-3 py-2">
{gitRepoStatus ? (
<RepoInfoComponent
gitRepoName={gitRepoName}
gitCurrentBranch={gitCurrentBranch}
></RepoInfoComponent>
) : null}
</div>
<div className="w-full">
<div className="xl:w-11/12 lg:w-full w-full xl:flex lg:block md:block sm:block my-4 mx-auto justify-around">
{gitRepoStatus ? (
<>
<RepoLeftPaneComponent
received={true}
actionTrigger={actionTrigger}
showCommitLogsView={showCommitLogsView}
gitRemoteHost={gitRemoteHost}
gitRemoteData={gitRemoteData}
isMultiRemote={isMultiRemote}
multiRemoteCount={multiRemoteCount}
></RepoLeftPaneComponent>
<RepoRightPaneComponent
received={true}
switchBranchHandler={switchBranchHandler}
actionTrigger={actionTrigger}
gitBranchList={gitBranchList}
gitCurrentBranch={gitCurrentBranch}
gitLatestCommit={gitLatestCommit}
gitTotalCommits={gitTotalCommits}
></RepoRightPaneComponent>
</>
) : null}
</div>
</div>
{!loading && gitRepoStatus && repoIdState
? memoizedFolderExplorer
: null}
</div>
) : !loading ? (
<div className="w-full h-full mx-auto text-center flex justify-center items-center">
<div className="block mx-auto w-11/12">
<div className="rounded-lg shadow border-2 border-dashed border-pink-400 text-red-300 text-3xl font-sans font-semibold p-4">
Unable to fetch repo details
</div>
<div className="font-sans font-light text-xl my-4 text-gray-600">
Please check if the repo is a valid git repo. If it is not a git
repo, delete the entry from "Settings" menu and add the repo
again by checking "Initialize a new repo" option
</div>
<div className="my-10 text-gray-200">
<FontAwesomeIcon
icon={["fas", "unlink"]}
size="10x"
></FontAwesomeIcon>
</div>
</div>
</div>
) : null}
</>
</>
);
}