@fortawesome/free-solid-svg-icons#fas JavaScript Examples
The following examples show how to use
@fortawesome/free-solid-svg-icons#fas.
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: CommitLogCardComponent.js From gitconvex with Apache License 2.0 | 6 votes |
export default function CommitLogCardComponent(props) {
library.add(fas);
const { item, setCommitType } = props;
return (
<div
className="flex p-3 justify-between items-center mx-auto border-b w-full cursor-pointer hover:bg-gray-100"
key={item.hash}
onClick={() => {
setCommitType(item.hash);
}}
>
<div className="block p-2 font-sans font-light text-gray-800">
<div className="my-2 font-sans text-xl font-light text-blue-600 border-b border-dashed">
{item.commitTime.split(" ")[0]}
</div>
<div className="w-3/4">{item.commitMessage}</div>
<div className="flex items-center gap-4 my-2 align-middle">
<div>
<FontAwesomeIcon
icon={["fas", "user-alt"]}
className="text-indigo-500"
></FontAwesomeIcon>
</div>
<div className="font-semibold font-sans">{item.author}</div>
</div>
</div>
<div className="block">
<div className="shadow border rounded text-sm p-2 bg-indigo-100 font-mono font-semibold text-indigo-800">
#{item.hash.substring(0, 7)}
</div>
<div className="my-2 shadow border rounded text-sm p-2 bg-yellow-50 font-sans font-semibold">
{relativeCommitTimeCalculator(item.commitTime)}
</div>
</div>
</div>
);
}
Example #3
Source File: layout.js From blog with Apache License 2.0 | 5 votes |
library.add(fab, fas);
Example #4
Source File: FontAwesomeIcon.jsx From tonic-ui with MIT License | 5 votes |
library.add(fas);
Example #5
Source File: App.js From littlelink-server with MIT License | 5 votes |
library.add(fab, fas, far);
Example #6
Source File: Fontawesome.js From gatsby-personal-site-template with MIT License | 5 votes |
library.add(fab, fas)
Example #7
Source File: welcome.test.js From portal with GNU General Public License v3.0 | 5 votes |
library.add(fas);
Example #8
Source File: provider-item.test.js From portal with GNU General Public License v3.0 | 5 votes |
library.add(fas);
Example #9
Source File: App.js From portal with GNU General Public License v3.0 | 5 votes |
library.add(fas);
Example #10
Source File: main.js From minimal-portfolio with GNU General Public License v3.0 | 5 votes |
library.add(fas)
Example #11
Source File: CompareSelectionHint.js From gitconvex with Apache License 2.0 | 5 votes |
export default function CompareSelectionHint() {
library.add(fas);
const selectionHints = [
{
message: (
<div className="my-10 font-sans text-xl font-semibold">
Select
<span className="mx-2 p-1 rounded-lg text-center text-white bg-gray-400">
Branch Compare
</span>
for comparing two branches
</div>
),
icon: "code-branch",
},
{
message: "",
icon: "",
},
{
message: (
<div className="my-10 font-sans text-xl font-semibold">
Select
<span className="mx-2 p-1 rounded-lg text-center text-white bg-gray-400">
Commit Compare
</span>
for comparing two selected commits
</div>
),
icon: "hashtag",
},
];
return (
<div className="flex justify-around my-6 mx-auto text-gray-300 gap-10 w-11/12">
{selectionHints.map((hint, index) => {
if (hint.message) {
return (
<div className="w-1/3 block text-center" key={`hint-${index}`}>
<div>
<FontAwesomeIcon
icon={["fas", hint.icon]}
size="10x"
></FontAwesomeIcon>
</div>
{hint.message}
</div>
);
} else {
return (
<div
className="block p-1 border-r-4 boreder-dashed"
key={`hint-${index}`}
></div>
);
}
})}
</div>
);
}
Example #12
Source File: index.js From ActiveLearningStudio-react-client with GNU Affero General Public License v3.0 | 5 votes |
library.add(fas);
Example #13
Source File: App.js From viade_es2a with BSD 2-Clause "Simplified" License | 5 votes |
library.add(fas);
Example #14
Source File: provider-item.test.js From viade_es2a with BSD 2-Clause "Simplified" License | 5 votes |
library.add(fas);
Example #15
Source File: welcome.test.js From viade_es2a with BSD 2-Clause "Simplified" License | 5 votes |
library.add(fas);
Example #16
Source File: app.jsx From jitsi-party with MIT License | 5 votes |
// Allow arbitrary icons to be used without importing them
library.add(fas)
Example #17
Source File: Icon.js From beautiful-react-ui with MIT License | 5 votes |
// adding fa dependencies
library.add(fas, fab);
Example #18
Source File: icon.js From React-Messenger-App with MIT License | 5 votes |
library.add(fas, fab);
Example #19
Source File: main.js From FreeTube-Vue with GNU Affero General Public License v3.0 | 5 votes |
library.add(fas)
Example #20
Source File: main.js From CursedChrome with MIT License | 5 votes |
library.add(fas)
Example #21
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 #22
Source File: RepositoryAction.js From gitconvex with Apache License 2.0 | 4 votes |
export default function RepositoryAction() {
library.add(fas);
const { state, dispatch } = useContext(ContextProvider);
const { presentRepo } = state;
const [loading, setLoading] = useState(false);
const [selectedFlag, setSelectedFlag] = useState(false);
const [defaultRepo, setDefaultRepo] = useState({});
const [availableRepos, setAvailableRepos] = useState([]);
const [activeBranch, setActiveBranch] = useState("");
const [selectedRepoDetails, setSelectedRepoDetails] = useState({
gitBranchList: "",
gitCurrentBranch: "",
gitTotalCommits: 0,
gitTotalTrackedFiles: 0,
});
const [branchError, setBranchError] = useState(false);
const [toggleSearchSelect, setToggleSearchSelect] = useState(false);
const [searchBranchValue, setSearchBranchValue] = useState("");
const [filteredBranchList, setFilteredBranchList] = useState([]);
const [viewReload, setViewReload] = useState(0);
const memoizedGitTracker = useMemo(() => {
if (defaultRepo && defaultRepo.id) {
return (
<GitTrackedComponent
repoId={defaultRepo.id}
resetBranchError={() => {
setBranchError(false);
}}
></GitTrackedComponent>
);
}
}, [defaultRepo]);
useEffect(() => {
const token = axios.CancelToken;
const source = token.source();
function fetchSelectedRepoStatus() {
const repoId = defaultRepo && defaultRepo.id;
if (repoId) {
setLoading(true);
axios({
url: globalAPIEndpoint,
method: "POST",
headers: {
"Content-type": "application/json",
},
cancelToken: source.token,
data: {
query: `
query
{
gitRepoStatus(repoId: "${repoId}") {
gitBranchList
gitCurrentBranch
gitTotalCommits
gitTotalTrackedFiles
}
}
`,
},
})
.then((res) => {
setLoading(false);
setSelectedRepoDetails(res.data.data.gitRepoStatus);
setActiveBranch(res.data.data.gitRepoStatus.gitCurrentBranch);
})
.catch((err) => {
setLoading(false);
if (err) {
console.log("API GitStatus error occurred : " + err);
}
});
}
}
//Effect dep function
async function invokeRepoFetchAPI() {
setLoading(true);
return await axios({
url: globalAPIEndpoint,
method: "POST",
cancelToken: source.token,
data: {
query: `
query {
fetchRepo{
repoId
repoName
repoPath
}
}
`,
},
}).then((res) => {
setLoading(false);
const apiResponse = res.data.data.fetchRepo;
if (apiResponse) {
const repoContent = apiResponse.repoId.map((entry, index) => {
return {
id: apiResponse.repoId[index],
repoName: apiResponse.repoName[index],
repoPath: apiResponse.repoPath[index],
};
});
dispatch({
type: PRESENT_REPO,
payload: [...repoContent],
});
setDefaultRepo(repoContent[0]);
setAvailableRepos(repoContent);
return repoContent;
}
});
}
if (presentRepo && presentRepo[0]) {
setAvailableRepos(presentRepo[0]);
fetchSelectedRepoStatus();
} else {
invokeRepoFetchAPI();
fetchSelectedRepoStatus();
}
return () => {
source.cancel();
};
}, [defaultRepo, viewReload, presentRepo, dispatch, branchError]);
function setTrackingBranch(branchName, event) {
setLoading(true);
setToggleSearchSelect(!toggleSearchSelect);
axios({
url: globalAPIEndpoint,
method: "POST",
data: {
query: `
mutation{
checkoutBranch(repoId: "${defaultRepo.id}", branchName: "${branchName}")
}
`,
},
})
.then((res) => {
setLoading(false);
if (res.data.data && !res.data.error) {
setSearchBranchValue("");
setFilteredBranchList([]);
handleScreenEvents();
setActiveBranch(branchName);
setViewReload(viewReload + 1);
}
})
.catch((err) => {
setLoading(false);
if (err) {
setBranchError(true);
event.target.innerText = activeBranch;
}
});
}
const handleScreenEvents = () => {
if (!toggleSearchSelect) {
document
.getElementById("repository-action")
.addEventListener("scroll", () => {
setToggleSearchSelect(false);
});
} else {
document
.getElementById("repository-action")
.removeEventListener("scroll", () => {});
}
};
const searchBranchHandler = (e) => {
const searchBranch = e.target.value;
setSearchBranchValue(searchBranch);
if (
searchBranch !== "" &&
selectedRepoDetails &&
selectedRepoDetails.gitBranchList
) {
const { gitBranchList } = selectedRepoDetails;
const filteredBranches = gitBranchList.filter((branchName) =>
branchName.toLowerCase().includes(searchBranch)
);
setFilteredBranchList(filteredBranches);
} else {
setFilteredBranchList([]);
}
};
const cancelSearchBranch = () => {
setSearchBranchValue("");
setFilteredBranchList([]);
};
function activeRepoPane() {
return (
<div className="flex items-center justify-around my-4 mx-auto align-middle">
<div className="flex items-center">
<div className="font-sans font-semibold my-1 text-gray-900">
Choose saved repository
</div>
<select
className="cursor-pointer rounded-lg border-dashed border-b-2 font-sans font-light text-xl mx-4 outline-none p-2 shadow bg-green-50 text-green-700 border-green-400"
defaultValue={"checked"}
onClick={() => {
setBranchError(false);
}}
onChange={(event) => {
if (event.currentTarget.value !== defaultRepo.repoName) {
setActiveBranch("...");
setSelectedRepoDetails({
...selectedRepoDetails,
gitCurrentBranch: "",
gitBranchList: ["..."],
});
}
setSelectedFlag(true);
availableRepos.length &&
availableRepos.forEach((elm) => {
if (event.target.value === elm.repoName) {
setDefaultRepo(elm);
dispatch({ type: GIT_GLOBAL_REPOID, payload: elm.id });
}
});
}}
>
<option defaultChecked value="checked" hidden disabled>
Select a repo
</option>
{availableRepos.length &&
availableRepos.map((entry) => {
return (
<option value={entry.repoName} key={entry.repoName}>
{entry.repoName}
</option>
);
})}
</select>
</div>
{selectedFlag ? (
<div className="flex items-center gap-4">
<div className="font-sans font-semibold my-1 text-gray-900">
Branch
</div>
<div className="flex-1 flex flex-col justify-center">
<div
className="flex-auto cursor-pointer inline-flex items-center justify-center px-4 py-2 shadow-md bg-indigo-50 border-indigo-400 text-indigo-700 border-dashed border-b-2 truncate"
onClick={(e) => {
let target = e.currentTarget;
if (!toggleSearchSelect) {
target.style.width = "17.5rem";
} else {
target.style.width = "auto";
}
setToggleSearchSelect(!toggleSearchSelect);
handleScreenEvents();
}}
>
<span className="mr-2">{activeBranch}</span>
<FontAwesomeIcon
className="text-sm m-1"
icon={["fas", "chevron-down"]}
></FontAwesomeIcon>
</div>
{toggleSearchSelect ? (
<div className="flex-auto flex flex-row justify-center">
<div className="bg-white border-indigo-300 text-indigo-700 px-4 py-4 shadow-md rounded-md z-20 absolute">
<div className="flex flex-row mt-1 mb-3">
<div className="b-1 text-center px-2 py-1 text-white bg-blue-400 rounded-l-md">
<FontAwesomeIcon
icon={["fas", "search"]}
></FontAwesomeIcon>
</div>
<input
id="branchSearchInput"
type="text"
placeholder="Search..."
className="px-2 py-1 bg-indigo-100 text-indigo-700 shadow-sm rounded-sm focus:outline-none outline-none"
onChange={searchBranchHandler}
value={searchBranchValue}
></input>
<div
className="b-1 text-center px-2 py-1 text-white cursor-pointer bg-red-400 rounded-r-md"
onClick={cancelSearchBranch}
>
<FontAwesomeIcon
icon={["fas", "times"]}
></FontAwesomeIcon>
</div>
</div>
{availableBranch()}
</div>
</div>
) : null}
</div>
</div>
) : null}
</div>
);
}
function getTopPaneComponent(icon, value) {
return (
<>
<div className="border-indigo-400 border-dashed border-b-2 flex justify-between font-sans text-lg mx-2 p-2 text-gray-600">
<div className="mx-2">
<FontAwesomeIcon icon={["fas", icon]}></FontAwesomeIcon>
</div>
<div className="mx-2">{value}</div>
</div>
</>
);
}
const branchCardComponent = (branch) => {
return (
<div
key={branch}
value={branch}
className="cursor-pointer text-sm border-b border-dotted p-2 mt-1 mb-1"
onClick={(event) => {
event.persist();
setActiveBranch("...");
setTrackingBranch(event.target.innerText, event);
}}
>
{branch}
</div>
);
};
function availableBranch() {
if (selectedRepoDetails && selectedRepoDetails.gitBranchList) {
const { gitBranchList } = selectedRepoDetails;
if (searchBranchValue !== "") {
if (filteredBranchList && filteredBranchList.length > 0) {
return filteredBranchList.map((branch) => {
if (branch !== "NO_BRANCH") {
return branchCardComponent(branch);
}
return null;
});
} else {
return (
<div className="text-center font-sans font-light text-base my-2 text-indigo-800 border-b border-dotted">
<span className="mx-1 font-semibold border-b border-dashed">
{searchBranchValue}
</span>
branch is not available!
</div>
);
}
} else {
return gitBranchList.map((branch) => {
if (branch !== "NO_BRANCH") {
return branchCardComponent(branch);
}
return null;
});
}
}
}
return (
<div
className="block justify-center mx-auto overflow-x-hidden w-full"
id="repository-action"
>
{availableRepos ? (
<div>
<div className="w-11/12 border-gray-200 rounded border my-6 mx-auto shadow">
{activeRepoPane()}
{selectedRepoDetails && selectedFlag ? (
<div className="my-auto flex justify-around p-3 mx-auto">
{loading ? (
<div className="text-center font-sans font-semibold text-gray-600 text-xl">
Loading repo details...
</div>
) : (
<>
{getTopPaneComponent(
"code-branch",
selectedRepoDetails.gitBranchList &&
selectedRepoDetails.gitBranchList.length > 0 &&
!selectedRepoDetails.gitBranchList[0].match(
/NO_BRANCH/gi
) ? (
<>
{selectedRepoDetails.gitBranchList.length === 1
? 1 + " branch"
: selectedRepoDetails.gitBranchList.length +
" branches"}
</>
) : (
"No Branches"
)
)}
{getTopPaneComponent(
"sort-amount-up",
selectedRepoDetails.gitTotalCommits + " Commits"
)}
{getTopPaneComponent(
"archive",
selectedRepoDetails.gitTotalTrackedFiles +
" Tracked Files"
)}
</>
)}
</div>
) : null}
</div>
{!selectedFlag ? (
<>
<div className="text-center mx-auto font-sans p-10 text-2xl bg-yellow-100 w-11/12 font-light rounded-lg shadow border-dashed border-2 border-yellow-200">
Select a configured repo from the dropdown to perform git
related operations
</div>
<div className="w-3/4 border-gray-100 rounded-lg border-2 block my-20 mx-auto p-6">
<div>
<FontAwesomeIcon
icon={["fas", "mouse-pointer"]}
className="flex font-bold h-full text-6xl m-auto text-center text-gray-300 w-full"
></FontAwesomeIcon>
</div>
<div className="block my-4 mx-auto text-center text-gray-200 xl:text-6xl lg:text-3xl md:text-2xl">
No repositories selected
</div>
</div>
</>
) : null}
<div>
{branchError ? (
<div className="bg-red-100 rounded font-sans my-2 mx-auto p-2 text-center text-red-700">
Branch switching failed.Commit your changes and try again
</div>
) : null}
{selectedRepoDetails && selectedFlag && defaultRepo.id
? memoizedGitTracker
: null}
</div>
</div>
) : null}
</div>
);
}
Example #23
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}
</>
</>
);
}
Example #24
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 #25
Source File: FetchPullActionComponent.js From gitconvex with Apache License 2.0 | 4 votes |
export default function FetchFromRemoteComponent(props) {
library.add(fas);
const { repoId, actionType } = props;
const [remoteData, setRemoteData] = useState();
const [isRemoteSet, setIsRemoteSet] = useState(false);
const [isBranchSet, setIsBranchSet] = useState(false);
const [result, setResult] = useState([]);
const [loading, setLoading] = useState(false);
const remoteRef = useRef();
const branchRef = useRef();
useEffect(() => {
const cancelToken = axios.CancelToken;
const source = cancelToken.source();
axios({
url: globalAPIEndpoint,
method: "POST",
cancelToken: source.token,
headers: {
"Content-type": "application/json",
},
data: {
query: `
query
{
gitRepoStatus(repoId:"${props.repoId}") {
gitRemoteData
gitCurrentBranch
gitRemoteHost
gitBranchList
}
}
`,
},
})
.then((res) => {
const repoDetails = res.data.data.gitRepoStatus;
setRemoteData(repoDetails);
})
.catch((err) => {
setLoading(false);
});
return () => {
return source.cancel();
};
}, [props]);
function remoteHostGenerator() {
if (remoteData) {
const { gitRemoteData } = remoteData;
if (gitRemoteData.includes("||")) {
return gitRemoteData.split("||").map((item) => {
return (
<option value={item} key={item}>
{item}
</option>
);
});
} else {
return <option>{gitRemoteData}</option>;
}
}
}
function branchListGenerator() {
if (remoteData) {
const { gitBranchList } = remoteData;
return gitBranchList.map((branch) => {
if (branch !== "NO_BRANCH") {
return (
<option value={branch} key={branch}>
{branch}
</option>
);
}
return null;
});
}
}
function actionHandler(remote = "", branch = "") {
setLoading(true);
setResult([]);
const getAxiosRequestBody = (remote, branch) => {
let gqlQuery = "";
if (actionType === "fetch") {
gqlQuery = `mutation {
fetchFromRemote(repoId: "${repoId}", remoteUrl: "${remote}", remoteBranch: "${branch}"){
status
fetchedItems
}
}
`;
} else {
gqlQuery = `mutation {
pullFromRemote(repoId: "${repoId}", remoteUrl: "${remote}", remoteBranch: "${branch}"){
status
pulledItems
}
}
`;
}
return gqlQuery;
};
axios({
url: globalAPIEndpoint,
method: "POST",
data: {
query: getAxiosRequestBody(remote, branch),
},
})
.then((res) => {
setLoading(false);
if (res.data.data && !res.data.error) {
let actionResponse = {};
if (actionType === "fetch") {
actionResponse = res.data.data.fetchFromRemote;
} else {
actionResponse = res.data.data.pullFromRemote;
}
if (actionResponse.status.match(/ABSENT/gi)) {
setResult([
<div className="text-xl text-center border-2 border-dashed border-gray-800 p-2 text-gray-700 font-semibold">
No changes to {actionType === "fetch" ? "Fetch" : "Pull"} from
remote
</div>,
]);
} else if (actionResponse.status.match(/ERROR/gi)) {
setResult([
<div className="text-xl p-2 text-pink-800 border border-pink-200 shadow rounded font-semibold">
Error while {actionType === "fetch" ? "Fetching" : "Pulling"}{" "}
from remote!
</div>,
]);
} else {
let resArray = [];
if (actionType === "fetch") {
resArray = actionResponse.fetchedItems;
} else {
resArray = actionResponse.pulledItems;
}
setResult([
<div className="text-xl text-center border-2 border-dashed border-green-600 p-2 text-green-700 bg-green-200 font-semibold rounded shadow">
{resArray[0]}
</div>,
]);
}
}
})
.catch((err) => {
setLoading(false);
console.error(err);
setResult([
<div className="text-xl p-2 text-red-500 border border-pink-200 shadow rounded font-semibold">
Error while {actionType === "fetch" ? "Fetching" : "Pulling"} from
remote!
</div>,
]);
});
}
return (
<>
<div className="w-3/4 mx-auto my-auto shadow rounded-lg bg-white pt-4">
{actionType === "fetch" ? (
<div>
<div className="text-center font-sans font-semibold mx-auto w-full p-3 text-2xl border-b-2 border-dashed text-gray-800">
Fetch from Remote
</div>
</div>
) : null}
{actionType === "pull" ? (
<div className="text-center font-sans font-semibold mx-auto w-full p-3 text-2xl border-b-2 border-dashed text-gray-800">
Pull from Remote
</div>
) : null}
<div className="flex flex-wrap w-3/4 mx-auto my-4 justify-around items-center align-middle gap-4">
<div className="w-full font-sans text-xl font-semibold text-gray-600">
Available remotes
</div>
<div className="w-full mb-6">
<select
className="border p-3 text-lg rounded shadow font-sans outline-none"
defaultValue="checked"
disabled={remoteData ? false : true}
onChange={() => {
setIsRemoteSet(true);
}}
onClick={() => {
setResult([]);
}}
ref={remoteRef}
>
<option disabled hidden value="checked">
{remoteData
? "Select the remote repo"
: "Loading available remotes..."}
</option>
{remoteData ? remoteHostGenerator() : null}
</select>
</div>
</div>
{isRemoteSet ? (
<div className="flex flex-wrap w-3/4 mx-auto my-4 justify-around items-center align-middle gap-4">
<div className="w-full font-sans text-xl font-semibold text-gray-600">
Available Branches
</div>
<div className="w-full mb-6">
<select
className="border p-3 text-lg rounded shadow font-sans outline-none"
defaultValue="checked"
onChange={() => {
setIsBranchSet(true);
}}
onClick={() => {
setResult([]);
}}
ref={branchRef}
>
<option disabled hidden value="checked">
Select upstream branch
</option>
{remoteData ? branchListGenerator() : null}
</select>
</div>
</div>
) : null}
{isRemoteSet && isBranchSet && !loading ? (
<div
className="text-center font-semibold text-xl p-4 mx-auto cursor-pointer bg-indigo-400 text-white mt-10 rounded-b hover:bg-indigo-500"
onClick={(event) => {
const remoteHost = remoteRef.current.value;
const branchName = branchRef.current.value;
if (remoteHost && branchName) {
actionHandler(remoteHost, branchName);
} else {
event.target.style.display = "none";
}
}}
>
{actionType === "pull" ? "PULL FROM REMOTE" : null}
{actionType === "fetch" ? "FETCH FROM REMOTE" : null}
</div>
) : null}
<div>
{loading ? (
<>
<div className="my-4 text-center border-2 border-dashed border-gray-500 font-light font-sans text-xl p-2 mx-auto text-gray-500 bg-gray-50 shadow rounded-md">
{actionType === "pull" ? "Pulling changes" : "Fetching"} from
remote...
</div>
<div className="flex mx-auto my-6 text-center justify-center">
<InfiniteLoader loadAnimation={loading}></InfiniteLoader>
</div>
</>
) : null}
</div>
{true || (!loading && result && result.length > 0) ? (
<>
{result.map((result) => {
return (
<div
className="border-dashed border-gray-200 text-center text-xl font-sans shadow bg-red-200 rounded w-full"
key={result + `-${uuid()}`}
>
{result}
</div>
);
})}
</>
) : null}
</div>
</>
);
}
Example #26
Source File: CommitLogFileCard.js From gitconvex with Apache License 2.0 | 4 votes |
export default function CommitLogFileCard({
repoId,
commitHash,
unmountHandler,
}) {
library.add(far, fas);
const [commitFiles, setCommitFiles] = useState([]);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
setIsLoading(true);
const token = axios.CancelToken;
const source = token.source();
axios({
url: globalAPIEndpoint,
method: "POST",
cancelToken: source.token,
data: {
query: `
query
{
gitCommitFiles(repoId: "${repoId}", commitHash: "${commitHash}"){
type
fileName
}
}
`,
},
})
.then((res) => {
setIsLoading(false);
if (res.data.data && !res.data.err) {
setCommitFiles([...res.data.data.gitCommitFiles]);
}
})
.catch((err) => {
console.log(err);
setIsLoading(false);
});
}, [repoId, commitHash]);
return (
<div className="w-11/12 p-6 rounded-lg shadow block mx-auto my-6 bg-blue-50">
<div
className="font-sans font-light float-right right-0 cursor-pointer mx-auto text-2xl text-blue-400 mb-0"
style={{ marginTop: "-20px" }}
onClick={() => {
setCommitFiles([]);
unmountHandler();
}}
>
x
</div>
{isLoading ? (
<div className="mx-4 text-2xl font-sans font-light text-gray-600 text-center">
Fetching changed files...
</div>
) : null}
{!isLoading && commitFiles ? (
<div className="mx-4 text-2xl font-sans font-light text-gray-600">{`${commitFiles.length} Files changed`}</div>
) : null}
<div className="block w-3/4 mx-10 my-4">
{commitFiles &&
commitFiles.map(({ type, fileName }) => {
let iconSelector = "";
let colorSelector = "";
switch (type) {
case "M":
iconSelector = "plus-square";
colorSelector = "text-yellow-400";
break;
case "A":
iconSelector = "plus-square";
colorSelector = "text-green-500";
break;
case "D":
iconSelector = "minus-square";
colorSelector = "text-red-500";
break;
default:
iconSelector = "plus-square";
colorSelector = "text-gray-500";
break;
}
return (
<div
className="flex justify-evenly items-center align-middle my-auto"
key={fileName + commitHash}
>
<div className={`w-1/4 text-2xl ${colorSelector}`}>
<FontAwesomeIcon
icon={["far", iconSelector]}
></FontAwesomeIcon>
</div>
<div
className="truncate w-3/4 font-medium text-sm text-gray-600"
title={fileName}
>
{fileName}
</div>
</div>
);
})}
</div>
</div>
);
}
Example #27
Source File: BranchCompareComponent.js From gitconvex with Apache License 2.0 | 4 votes |
export default function BranchCompareComponent(props) {
library.add(fas);
const [branchList, setBranchList] = useState([]);
const [currentBranch, setCurrentBranch] = useState("");
const [compareBranch, setCompareBranch] = useState("");
const [baseBranch, setBaseBranch] = useState("");
const [errState, setErrState] = useState(false);
const memoizedBranchCommitLogChangesComponent = useMemo(() => {
return (
<BranchCommitLogChanges
repoId={props.repoId}
baseBranch={baseBranch}
compareBranch={compareBranch}
></BranchCommitLogChanges>
);
}, [props.repoId, baseBranch, compareBranch]);
useEffect(() => {
const token = axios.CancelToken;
const source = token.source();
setErrState(false);
axios({
url: globalAPIEndpoint,
method: "POST",
cancelToken: source.token,
data: {
query: `
query
{
gitRepoStatus(repoId: "${props.repoId}") {
gitBranchList
gitCurrentBranch
}
}
`,
},
})
.then((res) => {
let { gitBranchList, gitCurrentBranch } = res.data.data.gitRepoStatus;
if (gitBranchList.length <= 0 || gitCurrentBranch === "") {
setErrState(true);
}
gitBranchList =
gitBranchList &&
gitBranchList.map((branch) => {
return branch.trim();
});
if (gitBranchList.length > 1) {
setCompareBranch(gitBranchList[1].trim());
}
setBranchList(gitBranchList);
setCurrentBranch(gitCurrentBranch.trim());
setBaseBranch(gitCurrentBranch.trim());
})
.catch((err) => {
console.log(err);
setErrState(true);
});
return () => {
return source.cancel;
};
}, [props.repoId]);
function noBranchToCompare() {
return (
<div className="w-full mx-auto my-auto text-center block">
<FontAwesomeIcon
icon={["fas", "puzzle-piece"]}
className="font-sans text-center text-gray-300 my-20"
size="10x"
></FontAwesomeIcon>
<div className="text-2xl text-gray-300">
Only one branch is available, hence can't be set for comparison
</div>
</div>
);
}
function compareBranchSelectPane() {
return (
<div className="w-11/12 p-3 flex mx-auto items-center align-middle rounded-lg shadow-md border-2 justify-around">
<div className="flex gap-6 justify-between items-center">
<div className="text-xl text-center font-sans font-semibold border-b-2 border-dashed border-gray-400">
Base branch
</div>
<div>
<select
defaultValue={currentBranch}
className="outline-none p-2 shadow border-2 bg-white rounded-lg"
onChange={(e) => {
setBaseBranch(e.currentTarget.value.trim());
}}
>
<option value={currentBranch}>{currentBranch}</option>
{branchList.map((branch) => {
if (branch !== currentBranch) {
return (
<option value={branch} key={branch}>
{branch}
</option>
);
}
return null;
})}
</select>
</div>
</div>
<div className="flex gap-6 justify-between items-center">
<div className="text-xl text-center font-sans font-semibold border-b-2 border-dashed border-gray-400">
Compare branch
</div>
<div>
<select
className="outline-none p-2 shadow border-2 bg-white rounded-lg"
onChange={(e) => {
setCompareBranch(e.currentTarget.value);
}}
>
{branchList.map((branch, index) => {
if (baseBranch && baseBranch !== branch) {
return (
<option value={branch} key={branch}>
{branch}
</option>
);
} else {
return index === 0 ? null : (
<option value={branch} key={branch}>
{branch}
</option>
);
}
})}
</select>
</div>
</div>
</div>
);
}
return (
<div>
{branchList.length === 1 ? (
noBranchToCompare()
) : branchList.length === 0 && !errState ? (
<div className="mx-auto my-20 text-center flex justify-center text-4xl font-sans text-gray-300">
Loading Branch Info...
</div>
) : !errState ? (
compareBranchSelectPane()
) : null}
{baseBranch && compareBranch && !errState
? memoizedBranchCommitLogChangesComponent
: null}
{errState ? (
<div className="mx-auto text-center text-2xl text-gray-500 font-sans font-semibold p-4 border-b border-dashed border-gray-400">
Error occurred while fetching results. Please verify if the repo has
valid branches
</div>
) : null}
</div>
);
}
Example #28
Source File: BranchListComponent.js From gitconvex with Apache License 2.0 | 4 votes |
export default function BranchListComponent({ repoId }) {
library.add(fas);
const [branchList, setBranchList] = useState([]);
const [listError, setListError] = useState(false);
const [switchError, setSwitchError] = useState(false);
const [switchedBranch, setSwitchedBranch] = useState("");
const [errorBranch, setErrorBranch] = useState("");
const [deleteError, setDeleteError] = useState(false);
const [loading, setLoading] = useState(false);
const [branchSearchTerm, setBranchSearchTerm] = useState("");
const [filteredBranchList, setFilteredBranchList] = useState([]);
function resetStates() {
setListError(false);
setSwitchError(false);
setSwitchedBranch("");
setErrorBranch("");
setDeleteError(false);
setBranchSearchTerm("");
setFilteredBranchList([]);
}
useEffect(() => {
const token = axios.CancelToken;
const source = token.source();
setLoading(true);
setBranchList([]);
setSwitchedBranch("");
axios({
url: globalAPIEndpoint,
method: "POST",
cancelToken: source.token,
data: {
query: `
query
{
gitRepoStatus(repoId:"${repoId}"){
gitAllBranchList
gitCurrentBranch
}
}
`,
},
})
.then((res) => {
setLoading(false);
if (res.data.data && !res.data.error) {
let {
gitAllBranchList,
gitCurrentBranch,
} = res.data.data.gitRepoStatus;
if (gitCurrentBranch === "Repo HEAD is nil") {
setBranchList([]);
setListError(true);
return;
}
gitAllBranchList = gitAllBranchList.map((branch) => {
if (branch === gitCurrentBranch) {
return "*" + branch;
}
return branch;
});
setBranchList([...gitAllBranchList]);
} else {
setListError(true);
}
})
.catch((err) => {
setLoading(false);
if (err) {
console.log("API error occurred : " + err);
setListError(true);
}
});
return () => source.cancel;
}, [repoId, switchedBranch]);
function switchBranchHandler(branchName) {
resetStates();
setLoading(true);
setBranchList([]);
axios({
url: globalAPIEndpoint,
method: "POST",
data: {
query: `
mutation{
checkoutBranch(repoId: "${repoId}", branchName: "${branchName}")
}
`,
},
})
.then((res) => {
setLoading(false);
if (res.data.data && !res.data.error) {
const checkoutStatus = res.data.data.checkoutBranch;
if (checkoutStatus === "CHECKOUT_FAILED") {
setErrorBranch(branchName);
setSwitchError(true);
return;
} else {
setSwitchedBranch(branchName);
}
} else {
setSwitchError(true);
setErrorBranch(branchName);
}
})
.catch((err) => {
setLoading(false);
if (err) {
setSwitchError(true);
setErrorBranch(branchName);
}
});
}
function deleteBranchHandler(branchName, forceFlag) {
resetStates();
setLoading(true);
axios({
url: globalAPIEndpoint,
method: "POST",
data: {
query: `
mutation{
deleteBranch(repoId: "${repoId}", branchName: "${branchName}", forceFlag: ${forceFlag}){
status
}
}
`,
},
})
.then((res) => {
setLoading(false);
if (res.data.data && !res.data.error) {
if (res.data.data.deleteBranch.status === "BRANCH_DELETE_SUCCESS") {
setSwitchedBranch(branchName);
} else {
setDeleteError(true);
setErrorBranch(branchName);
}
}
})
.catch((err) => {
setLoading(false);
if (err) {
setDeleteError(true);
setErrorBranch(branchName);
}
});
}
function errorComponent(errorString, branchError = false) {
return (
<div className="text-center p-4 rounded bg-red-300 text-xl font-sans mt-10">
{errorString}
{branchError ? (
<span className="font-semibold border-b border-dashed mx-2">
{errorBranch}
</span>
) : null}
</div>
);
}
const searchBranchFromList = (event) => {
const searchBranch = event.target.value;
setBranchSearchTerm(searchBranch);
if (searchBranch !== "") {
const filteredBranches = branchList.filter((branchName) =>
branchName.toLowerCase().includes(searchBranch)
);
setFilteredBranchList(filteredBranches);
} else {
setFilteredBranchList([]);
}
};
const cancelSearchBranchFromList = () => {
setBranchSearchTerm("");
setFilteredBranchList([]);
};
const renderBranchListComponent = (branch) => {
const branchPickerComponent = (icon, branchType, branchName) => {
let activeSwitchStyle = "";
let activeBranchFlag = false;
if (branchName.includes("*")) {
activeBranchFlag = true;
branchName = branchName.replace("*", "");
}
if (activeBranchFlag) {
activeSwitchStyle = "border-dashed border-b-2 text-indigo-700 text-2xl";
}
return (
<div
className="flex items-center justify-center px-14 py-4 mx-auto border-dashed border-b"
key={branchType + branchName}
>
<div
className={
icon === "wifi"
? "mx-2 text-2xl text-blue-500 ml-0"
: "mx-2 text-2xl text-blue-500"
}
>
<FontAwesomeIcon icon={["fas", icon]}></FontAwesomeIcon>
</div>
<div className="xl:block lg:block md:block sm:hidden w-1/3 font-sans text-lg font-semibold text-center text-indigo-500">
{branchType}
</div>
<div
className={`w-1/2 font-sans font-semibold text-lg text-left cursor-pointer overflow-hidden text-gray-500 hover:text-blue-800 ${activeSwitchStyle}`}
title={branchName}
onClick={() => {
if (!activeBranchFlag) {
if (branchType !== "Local Branch") {
switchBranchHandler(branch);
} else {
switchBranchHandler(branchName);
}
}
}}
>
{branchName}
</div>
{!activeBranchFlag && branchType === "Local Branch" ? (
<div className="flex mx-4 justify-between my-auto text-center items-center w-1/4 px-2">
<div
className="w-1/2 block mx-auto my-auto text-center px-2 justify-center bg-red-500 p-2 rounded-lg shadow-md cursor-pointer text-white font-sans font-semibold hover:bg-red-600"
title="Will delete the branch forcefully.Be careful!"
onClick={() => {
if (!activeBranchFlag) {
deleteBranchHandler(branchName, true);
}
}}
>
<div>
<FontAwesomeIcon
icon={["fas", "trash-alt"]}
></FontAwesomeIcon>
</div>
<div>DELETE</div>
</div>
</div>
) : (
<>
{activeBranchFlag ? (
<div className="w-1/4 font-sans mx-4 text-sm px-2 font-light border border-dashed p-1 rounded-full text-center bg-blue-100 border-blue-800">
Active
</div>
) : (
<div className="w-1/4 font-sans mx-4 text-sm px-2 font-light border border-dashed p-1 rounded-full text-center bg-yellow-100 border-yellow-700">
Remote
</div>
)}
</>
)}
</div>
);
};
if (!branch.includes("remotes/")) {
return branchPickerComponent("code-branch", "Local Branch", branch);
} else {
const splitBranch = branch.split("/");
if (splitBranch.length <= 2) {
return null;
}
const remoteName = splitBranch[1];
const remoteBranch = splitBranch.slice(2, splitBranch.length).join("/");
return branchPickerComponent("wifi", remoteName, remoteBranch);
}
};
return (
<div className="bg-gray-50 p-6 mx-auto my-auto items-center rounded-lg w-11/12 xl:w-3/4 lg:w-3/4 md:w-11/12 sm:w-11/12">
<div className="text-4xl my-4 font-sans font-semibold text-gray-600">
Available Branches
</div>
<div className="flex justify-start items-center font-sans text-sm font-semibold text-red-500">
<div>
<FontAwesomeIcon
icon={["fas", "exclamation-circle"]}
></FontAwesomeIcon>
</div>
<div className="mx-2 font-sans font-semibold">
Note that this section also lets you delete the branches, so be
cautious!
</div>
</div>
<div className="italic font-sans font-semibold text-lg my-2 border-b-2 border-dashed border-gray-300 text-gray-300">
Click on a branch to checkout to that branch
</div>
<div
className="w-full mx-auto my-6 overflow-y-auto overflow-x-hidden"
style={{ height: "400px" }}
>
{loading ? (
<div className="text-center font-sans font-light text-xl my-2 text-gray-600 border-b border-dotted">
Collecting branch list...
</div>
) : null}
{!loading ? (
<div className="flex flex-row mx-8 shadow-md rounded-md my-4">
<div className="b-1 text-center p-4 text-white bg-blue-500 rounded-l-md">
<FontAwesomeIcon icon={["fas", "search"]}></FontAwesomeIcon>
</div>
<div className="w-full">
<input
id="branchListSearchInput"
type="text"
placeholder="Search For Branch Name"
className="border-0 outline-none w-full p-4 focus:outline-none"
onChange={searchBranchFromList}
value={branchSearchTerm}
></input>
</div>
<div
className="b-1 text-center p-4 text-gray-500 cursor-pointer bg-white rounded-r-md"
onClick={cancelSearchBranchFromList}
>
<FontAwesomeIcon icon={["fas", "times"]}></FontAwesomeIcon>
</div>
</div>
) : null}
{!listError && branchList && branchSearchTerm !== "" ? (
filteredBranchList.length > 0 ? (
filteredBranchList.map((branch) => {
return renderBranchListComponent(branch);
})
) : (
<div className="text-center font-sans font-light text-xl my-2 text-gray-600 border-b border-dotted">
<span className="mx-2 font-semibold border-b border-dashed">
{branchSearchTerm}
</span>
branch is not available!
</div>
)
) : (
branchList.map((branch) => {
return renderBranchListComponent(branch);
})
)}
</div>
{listError
? errorComponent("Error occurred while listing branches!")
: null}
{switchError
? errorComponent("Error occurred while switching to", true)
: null}
{switchedBranch && switchedBranch.length > 0 && deleteError
? errorComponent("Branch deletion failed for", true)
: null}
</div>
);
}
Example #29
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>
</>
)}
</>
);
}