"": "const PageHeader = styled.h2`\\n color: #555555;\\n font-size: 24px;\\n font-style: normal;\\n font-weight: 400;\\n line-height: 120%; /* 28.8px */\\n letter-spacing: -0.24px;\\n\\n width: 100%;\\n padding: 1rem 3.125rem;\\n margin-left: auto;\\n //background: #fff;\\n\\n margin-top: 1.5rem;\\n margin-bottom: 1.5rem;\\n\\n @media screen and (max-width: 786px) {\\n padding: 1rem;\\n }\\n`;\\n\\nconst Section = styled.div`\\n padding: 1.5rem 8rem;\\n display: flex;\\n flex-direction: column;\\n\\n display: flex;\\n flex-direction: column;\\n\\n gap: 2rem;\\n\\n @media screen and (max-width: 786px) {\\n padding: 1rem;\\n }\\n\\n h2 {\\n color: #151515;\\n font-size: 2rem;\\n font-style: normal;\\n font-weight: 700;\\n line-height: 2rem; /* 55.556% */\\n\\n margin: 1rem;\\n margin-left: 0;\\n }\\n\\n p {\\n color: #151515;\\n font-size: 1.25rem;\\n font-style: normal;\\n font-weight: 400;\\n line-height: 150%;\\n margin-bottom: 1rem;\\n }\\n\\n h3 {\\n color: #151515;\\n font-size: 1.5rem;\\n font-style: normal;\\n font-weight: 700;\\n line-height: 120%;\\n\\n margin-top: 1rem;\\n }\\n`;\\n\\nreturn (\\n <>\\n <Widget src={`thomasguntenaar.testnet/widget/devhub.components.island.banner`} />\\n <Section>\\n <h2>\\n What is <span style={{ color: \\\"#00EC97\\\" }}>near</span>/dev/hub?\\n </h2>\\n\\n <div>\\n <p>\\n DevHub brings together individuals, projects, and organizations to\\n build a decentralized NEAR developer ecosystem. We provide social\\n structure and tools to fuel innovation, collaboration, and community\\n within the NEAR ecosystem. Whether you\\u{2019}re a blockchain developer or\\n advocate for the open web, DevHub is your gateway to making a\\n meaningful impact on NEAR and beyond.\\n </p>\\n\\n <h3>Mission</h3>\\n <p>\\n Build a self-sufficient developer community to enable a thriving NEAR\\n ecosystem.\\n </p>\\n\\n <h3>Values</h3>\\n <p>\\n <ul>\\n <li>\\n <b>Decentralized</b>: We are building together.\\n </li>\\n <li>\\n <b>Transparent</b>: All decision making and communication is open.\\n </li>\\n <li>\\n <b>Self-sufficient</b>: We do not critically depend on any single\\n entity.\\n </li>\\n <li>\\n <b>Robust</b>: Any role or team can be duplicated or replaced.\\n </li>\\n <li>\\n <b>High-velocity</b>: We need to move faster than classic OSS.\\n </li>\\n </ul>\\n </p>\\n\\n <h3>Scope</h3>\\n <p>\\n DevHub covers a wide range of areas to support the NEAR developer\\n ecosystem, including:\\n <ul>\\n <li>\\n <b>Developer Tooling</b>: Contributing code to the NEAR Platform\\n (blockchain and devtools) and facilitating technical decisions\\n with recognized experts based on the needs of the community and\\n ecosystem.\\n </li>\\n <li>\\n <b>Developer Relations</b>: Engaging with the community across\\n various social channels, gathering feedback, and improving\\n documentation.\\n </li>\\n <li>\\n <b>Deep-Tech Awareness</b>: Working with marketing partners to\\n create awareness on interesting projects and technology areas.\\n </li>\\n <li>\\n <b>Events and Hackathons</b>: Organizing events and empowering\\n community leaders with resources to grow their local communities.\\n </li>\\n <li>\\n <b>Education</b>: Partnering with universities across the globe to\\n support students and scholars in exploring Web3 technologies\\n </li>\\n <li>\\n <b>Platform</b>: Developing DevHub platform as a product to enable\\n communities to collaborate and support each other.\\n </li>\\n </ul>\\n </p>\\n\\n <h3>Our Contributors</h3>\\n <p>\\n DevHub operates through DevDAO, which provides social structures to\\n support developers. Within DevDAO, we have a dedicated core team of\\n moderators and community contributors who work across the key areas\\n above. We welcome contributions from any community members who want to\\n join us in building our ecosystem and their own skills!\\n </p>\\n\\n <h3>Our Platform</h3>\\n <p>\\n Our main tool for interfacing is the DevHub Platform, where you can\\n connect with others, share ideas and solutions, and access resources\\n and support. You can also find communities working on a variety of\\n areas, from protocol development to tooling and documentation.\\n </p>\\n\\n <h3>Join Us in Shaping NEAR\\u{2019}s Future</h3>\\n <p>\\n Regardless of your background or where you are on your developer\\n journey, we\\u{2019}re happy you\\u{2019}re here! We hope you\\u{2019}ll explore, find your\\n people, and discover paths to contribute that are most gratifying for\\n you.\\n <br />\\n Let\\u{2019}s build the open web together.\\n </p>\\n </div>\\n </Section>\\n </>\\n);\\n"
"": "const Header = styled.div`\\n //background: white;\\n padding: 1rem 3.125rem;\\n width: 100%;\\n margin: 24px;\\n\\n @media screen and (max-width: 768px) {\\n margin: 1rem 0;\\n padding: 1rem;\\n }\\n`;\\n\\nconst PageHeader = styled.h1`\\n color: #555555;\\n font-size: 1.5rem;\\n font-style: normal;\\n font-weight: 500;\\n line-height: 120%; /* 28.8px */\\n letter-spacing: -0.24px;\\n margin: 0;\\n`;\\n\\nconst Lead = styled.h5`\\n color: #151515;\\n font-size: 2.5rem;\\n font-style: normal;\\n font-weight: 700;\\n line-height: 120%; /* 48px */\\n margin: 2.25rem 8rem;\\n margin-top: 0;\\n\\n @media screen and (max-width: 768px) {\\n font-size: 1.75rem;\\n margin: 1rem;\\n margin-top: 0;\\n }\\n`;\\n\\nconst Container = styled.div`\\n padding: 2.25rem 8rem;\\n width: 100%;\\n //background-color: white;\\n\\n @media screen and (max-width: 768px) {\\n padding: 1rem;\\n }\\n`;\\n\\nconst actions = [\\n {\\n title: \\\"Ideate on DevHub\\\",\\n description:\\n \\\"The first step in any NEAR ecosystem project is ideation. It is crucial to have a way to find people to share and explore ideas with, partly because it can save a lot of time based on prior discussions. But also because it can you gauge support from a diversity of stakeholders.\\\",\\n ctaAction: \\\"Learn More \\u{2192}\\\",\\n ctaLink: \\\"/devhub.near/widget/app?page=blog&id=2029\\\",\\n },\\n {\\n title: \\\"Post a Proposal\\\",\\n description:\\n \\\"If you have already nurtured and refined your idea, you\\\'re ready to draft and post your funding proposal.This guide is here to help you craft a compelling, convincing, and concise proposal that will capture the interest of potential funders.\\\",\\n ctaAction: \\\"Learn More \\u{2192}\\\",\\n ctaLink: \\\"/devhub.near/widget/app?page=blog&id=2035\\\",\\n },\\n {\\n title: \\\"Host an Event\\\",\\n description:\\n \\\"We are always on the lookout for events that align with our mission and provide value to the NEAR ecosystem. If you are organizing such an event, we would love to hear from you! Below is a guide on how to submit a sponsorship proposal to us.\\\",\\n ctaAction: \\\"Learn More \\u{2192}\\\",\\n ctaLink: \\\"/devhub.near/widget/app?page=community&handle=hacks&tab=wiki-202\\\",\\n },\\n {\\n title: \\\"Improve NEAR Docs\\\",\\n description:\\n \\\"NEAR documentation is an open source repository that anyone can fork, extend and contribute to by creating pull requests. To get started, head over to our github repository and checkout how you can make your first contribution. \\\",\\n ctaAction: \\\"Learn More \\u{2192}\\\",\\n ctaLink: \\\"https://github.com/near/docs\\\",\\n },\\n {\\n title: \\\"Join the Fellowship\\\",\\n description:\\n \\\"As the NEAR ecosystem grows rapidly, there is an increasing need to improve developer productivity. The DevDAO NEAR Platform Fellowship Program aims to solve this issue by providing guidance to new contributors from experienced developers.\\\",\\n ctaAction: \\\"Learn More \\u{2192}\\\",\\n ctaLink:\\n \\\"/devhub.near/widget/app?page=community&handle=fellowship&tab=wiki-1\\\",\\n },\\n {\\n title: \\\"Join NEAR Campus\\\",\\n description:\\n \\\"DevHub\\u{2019}s NEAR Campus supports existing student clubs, researchers, and faculties in blockchain technologies, enhancing both curricular and extracurricular activities. We aim to merge blockchain education with mainstream academics.\\\",\\n ctaAction: \\\"Learn More \\u{2192}\\\",\\n ctaLink: \\\"/devhub.near/widget/app?page=community&handle=near-campus\\\",\\n },\\n {\\n title: \\\"Dive into Hackbox\\\",\\n description:\\n \\\"Hackbox is a revolutionary plug-and-play solution designed to empower local leads and community stewards in hosting hackathons easily and efficiently.\\\",\\n ctaAction: \\\"Learn More \\u{2192}\\\",\\n ctaLink: \\\"/hackbox.near/widget/home\\\",\\n },\\n];\\n\\nconst Card = styled.div`\\n display: flex;\\n flex-direction: column;\\n gap: 0.5rem;\\n\\n h5 {\\n color: #151515;\\n font-size: 1.75rem;\\n font-style: normal;\\n font-weight: 400;\\n line-height: 120%; /* 43.2px */\\n\\n display: flex;\\n align-items: center;\\n }\\n\\n p {\\n color: #000;\\n font-size: 1rem;\\n font-style: normal;\\n font-weight: 400;\\n line-height: 120%; /* 28.8px */\\n }\\n\\n a {\\n color: #f4f4f4;\\n font-size: 1rem;\\n font-style: normal;\\n font-weight: 700;\\n line-height: 120%; /* 28.8px */\\n letter-spacing: -0.48px;\\n\\n display: flex;\\n padding: 0.5rem 1rem;\\n align-items: center;\\n gap: 8px;\\n\\n border-radius: 0.5rem;\\n background: #00ec97;\\n\\n width: max-content;\\n }\\n`;\\nconst ActionCard = ({ action, index }) => {\\n return (\\n <Card>\\n <h5>\\n <span\\n style={{\\n color: \\\"#151515\\\",\\n border: \\\"2px #151515 solid\\\",\\n fontSize: 12,\\n padding: 4,\\n width: 22,\\n height: 22,\\n }}\\n className=\\\"rounded-circle d-flex align-items-center justify-content-center me-1\\\"\\n >\\n {index + 1}\\n </span>\\n {action.title}\\n </h5>\\n <p>{action.description}</p>\\n <a href={action.ctaLink} target=\\\"no_blank\\\">\\n {action.ctaAction}\\n </a>\\n </Card>\\n );\\n};\\n\\nconst ActionContainer = styled.div`\\n display: grid;\\n grid-template-columns: repeat(2, 1fr);\\n justify-content: center;\\n column-gap: 1rem;\\n row-gap: 2rem;\\n\\n width: 100%;\\n\\n @media screen and (max-width: 768px) {\\n display: flex;\\n flex-direction: column;\\n }\\n`;\\n\\nreturn (\\n <>\\n <Widget src={`thomasguntenaar.testnet/widget/devhub.components.island.banner`} />\\n <Header>\\n <PageHeader>Contribute</PageHeader>\\n </Header>\\n <Lead>\\n There are many ways to start your contribution journey. You can:\\n </Lead>\\n <Container>\\n <ActionContainer>\\n {actions.map((action, index) => (\\n <ActionCard action={action} index={index} />\\n ))}\\n </ActionContainer>\\n </Container>\\n </>\\n);\\n"
},
"devhub.entity.post.List": {
"": "// This component implementation was forked from [IndexFeed], but it does not fully implement lazy loading.\\n// While this component uses InfiniteScroll, it still loads the whole list of Post IDs in one view call.\\n// The contract will need to be extended with pagination support, yet, even in the current state the page loads much faster.\\n// [IndexFeed]: https://near.social/#/mob.near/widget/WidgetSource?src=mob.near/widget/IndexFeed\\n\\nconst { href } = VM.require(\\\"thomasguntenaar.testnet/widget/core.lib.url\\\");\\n\\nconst { draftState, onDraftStateChange } = VM.require(\\n \\\"thomasguntenaar.testnet/widget/devhub.entity.post.draft\\\"\\n);\\n\\nif (!href) {\\n return <p>Loading modules...</p>;\\n}\\n\\nconst QUERYAPI_ENDPOINT = `https://near-queryapi.api.pagoda.co/v1/graphql/`;\\n\\nconst queryName =\\n props.queryName ?? `bo_near_devhub_v38_posts_with_latest_snapshot`;\\nconst totalQueryName =\\n props.totalQueryName ??\\n \\\"bo_near_devhub_v38_posts_with_latest_snapshot_aggregate\\\";\\nconst query = `query DevhubPostsQuery($limit: Int = 100, $offset: Int = 0, $where: ${queryName}_bool_exp = {}) {\\n ${queryName}(\\n limit: $limit\\n offset: $offset\\n order_by: {ts: desc}\\n where: $where\\n ) {\\n post_id\\n }\\n }\\n`;\\n\\nconst totalQuery = `query DevhubTotalPostsQuery($where: ${queryName}_bool_exp = {}) {\\n ${totalQueryName}(\\n where: $where\\n ) {\\n aggregate {\\n count\\n }\\n }\\n }\\n`;\\n\\nfunction fetchGraphQL(operationsDoc, operationName, variables) {\\n return asyncFetch(QUERYAPI_ENDPOINT, {\\n method: \\\"POST\\\",\\n headers: { \\\"x-hasura-role\\\": `bo_near` },\\n body: JSON.stringify({\\n query: operationsDoc,\\n variables: variables,\\n operationName: operationName,\\n }),\\n });\\n}\\n\\nfunction searchConditionChanged() {\\n return (\\n props.author != state.author ||\\n props.term != state.term ||\\n props.tag != state.tag ||\\n props.recency != state.recency\\n );\\n}\\n\\nfunction updateSearchCondition() {\\n State.update({\\n author: props.author,\\n term: props.term,\\n tag: props.tag,\\n recency: props.recency,\\n loading: true,\\n });\\n}\\n\\nconst initialRenderLimit = props.initialRenderLimit ?? 3;\\nconst addDisplayCount = props.nextLimit ?? initialRenderLimit;\\n\\nState.init({\\n period: \\\"week\\\",\\n totalItems: 0,\\n displayCount: initialRenderLimit,\\n});\\n\\nfunction getPostIds(tag, offset) {\\n if (searchConditionChanged()) {\\n updateSearchCondition();\\n }\\n let where = {};\\n let authorId = props.author;\\n let label = tag || props.tag;\\n if (authorId) {\\n where = { author_id: { _eq: authorId }, ...where };\\n }\\n if (props.term) {\\n where = { description: { _ilike: `%${props.term}%` }, ...where };\\n }\\n if (label) {\\n if (typeof label === \\\"string\\\") {\\n // Handle a single label\\n where = { labels: { _contains: label }, ...where };\\n } else if (Array.isArray(label)) {\\n // Handle an array of labels\\n where = {\\n labels: {\\n _containsAny: label,\\n },\\n ...where,\\n };\\n }\\n }\\n if (!props.recency) {\\n // show only top level posts\\n where = { parent_id: { _is_null: true }, ...where };\\n }\\n\\n // Don\\\'t show blog and devhub-test posts\\n where = {\\n _and: [\\n {\\n _not: {\\n labels: { _contains: \\\"blog\\\" },\\n parent_id: { _is_null: true },\\n post_type: { _eq: \\\"Comment\\\" },\\n },\\n },\\n {\\n _not: {\\n labels: { _contains: \\\"devhub-test\\\" },\\n },\\n },\\n ],\\n ...where,\\n };\\n\\n if (!offset) {\\n fetchGraphQL(totalQuery, \\\"DevhubTotalPostsQuery\\\", {\\n where,\\n }).then((result) => {\\n const data = result.body.data[totalQueryName];\\n State.update({\\n totalItems: data.aggregate.count,\\n });\\n });\\n }\\n\\n fetchGraphQL(query, \\\"DevhubPostsQuery\\\", {\\n limit: 50,\\n offset: offset ?? 0,\\n where,\\n }).then((result) => {\\n if (result.status === 200) {\\n if (result.body.data) {\\n const data = result.body.data[queryName];\\n if (offset) {\\n State.update({\\n postIds: state.postIds.concat(data.map((p) => p.post_id)),\\n loading: false,\\n });\\n } else {\\n State.update({\\n postIds: data.map((p) => p.post_id),\\n loading: false,\\n });\\n }\\n }\\n } else {\\n State.update({ loading: false });\\n }\\n });\\n}\\n\\nif (!state.items || searchConditionChanged()) {\\n getPostIds();\\n}\\n\\nfunction defaultRenderItem(postId, additionalProps) {\\n if (!additionalProps) {\\n additionalProps = {};\\n }\\n // It is important to have a non-zero-height element as otherwise InfiniteScroll loads too many items on initial load\\n return (\\n <div className=\\\"py-2\\\" style={{ minHeight: \\\"150px\\\" }}>\\n <Widget\\n src={\\\"thomasguntenaar.testnet/widget/devhub.entity.post.Post\\\"}\\n props={{\\n id: postId,\\n expandable: true,\\n defaultExpanded: false,\\n isInList: true,\\n draftState,\\n isPreview: false,\\n onDraftStateChange,\\n ...additionalProps,\\n referral: postId,\\n updateTagInParent: (tag) => {\\n if (typeof props.updateTagInput === \\\"function\\\") {\\n props.updateTagInput(tag);\\n }\\n getPostIds(tag);\\n },\\n transactionHashes: props.transactionHashes,\\n }}\\n />\\n </div>\\n );\\n}\\n\\nconst renderItem = props.renderItem ?? defaultRenderItem;\\n\\nconst cachedRenderItem = (item, i) => {\\n if (props.term) {\\n return renderItem(item, {\\n searchKeywords: [props.term],\\n });\\n }\\n\\n const key = JSON.stringify(item);\\n\\n if (!(key in state.cachedItems)) {\\n state.cachedItems[key] = renderItem(item);\\n State.update();\\n }\\n return state.cachedItems[key];\\n};\\n\\nconst ONE_DAY = 60 * 60 * 24 * 1000;\\nconst ONE_WEEK = 60 * 60 * 24 * 1000 * 7;\\nconst ONE_MONTH = 60 * 60 * 24 * 1000 * 30;\\n\\nfunction getHotnessScore(post) {\\n //post.id - shows the age of the post, should grow exponentially, since newer posts are more important\\n //post.likes.length - linear value\\n const age = Math.pow(post.id, 5);\\n const comments = post.comments;\\n const commentAge = comments.reduce((sum, age) => sum + Math.pow(age, 5), 0);\\n const totalAge = age + commentAge;\\n //use log functions to make likes score and exponentially big age score close to each other\\n return Math.log10(post.likes.length) + Math.log(Math.log10(totalAge));\\n}\\n\\nconst getPeriodText = (period) => {\\n let text = \\\"Last 24 hours\\\";\\n if (period === \\\"week\\\") {\\n text = \\\"Last week\\\";\\n }\\n if (period === \\\"month\\\") {\\n text = \\\"Last month\\\";\\n }\\n return text;\\n};\\n\\nlet postIds = state.postIds ?? null;\\n\\nconst loader = (\\n <div className=\\\"loader\\\" key={\\\"loader\\\"}>\\n <span\\n className=\\\"spinner-grow spinner-grow-sm me-1\\\"\\n role=\\\"status\\\"\\n aria-hidden=\\\"true\\\"\\n />\\n Loading ...\\n </div>\\n);\\n\\nif (postIds === null) {\\n return loader;\\n}\\nconst initialItems = postIds;\\n\\nconst jInitialItems = JSON.stringify(initialItems);\\nif (state.jInitialItems !== jInitialItems) {\\n // const jIndex = JSON.stringify(index);\\n // if (jIndex !== state.jIndex) {\\n State.update({\\n jIndex,\\n jInitialItems,\\n items: initialItems,\\n cachedItems: {},\\n });\\n}\\n\\nconst makeMoreItems = () => {\\n State.update({\\n displayCount: state.displayCount + addDisplayCount,\\n });\\n if (\\n state.items.length - state.displayCount < addDisplayCount * 5 &&\\n !state.loading\\n ) {\\n State.update({ loading: true });\\n getPostIds(null, state.items.length);\\n }\\n};\\n\\nconst items = state.items ? state.items.slice(0, state.displayCount) : [];\\nconst renderedItems = items.map(cachedRenderItem);\\n\\nconst Head =\\n props.recency == \\\"hot\\\" ? (\\n <div class=\\\"row\\\">\\n <div class=\\\"fs-5 col-6 align-self-center\\\">\\n <i class=\\\"bi-fire\\\"></i>\\n <span>Hottest Posts</span>\\n </div>\\n <div class=\\\"col-6 dropdown d-flex justify-content-end\\\">\\n <a\\n class=\\\"btn btn-secondary dropdown-toggle\\\"\\n href=\\\"#\\\"\\n role=\\\"button\\\"\\n id=\\\"dropdownMenuLink\\\"\\n data-bs-toggle=\\\"dropdown\\\"\\n aria-expanded=\\\"false\\\"\\n >\\n {getPeriodText(state.period)}\\n </a>\\n\\n <ul class=\\\"dropdown-menu\\\" aria-labelledby=\\\"dropdownMenuLink\\\">\\n <li>\\n <button\\n class=\\\"dropdown-item\\\"\\n onClick={() => {\\n State.update({ period: \\\"day\\\" });\\n }}\\n >\\n {getPeriodText(\\\"day\\\")}\\n </button>\\n </li>\\n <li>\\n <button\\n class=\\\"dropdown-item\\\"\\n onClick={() => {\\n State.update({ period: \\\"week\\\" });\\n }}\\n >\\n {getPeriodText(\\\"week\\\")}\\n </button>\\n </li>\\n <li>\\n <button\\n class=\\\"dropdown-item\\\"\\n onClick={() => {\\n State.update({ period: \\\"month\\\" });\\n }}\\n >\\n {getPeriodText(\\\"month\\\")}\\n </button>\\n </li>\\n </ul>\\n </div>\\n </div>\\n ) : (\\n <></>\\n );\\n\\nreturn (\\n <>\\n {Head}\\n {state.loading ? loader : null}\\n {is_edit_or_add_post_transaction ? (\\n <p class=\\\"text-secondary mt-4\\\">\\n Post {transaction_method_name == \\\"edit_post\\\" ? \\\"edited\\\" : \\\"added\\\"}{\\\" \\\"}\\n successfully. Back to{\\\" \\\"}\\n <Link\\n style={{\\n color: \\\"#3252A6\\\",\\n }}\\n className=\\\"fw-bold\\\"\\n to={href({\\n widgetSrc: \\\"thomasguntenaar.testnet/widget/app\\\",\\n params: { page: \\\"feed\\\" },\\n })}\\n >\\n feed\\n </Link>\\n </p>\\n ) : state.items.length > 0 ? (\\n <div style={{ overflow: \\\"auto\\\", height: \\\"60vh\\\" }}>\\n <InfiniteScroll\\n pageStart={0}\\n loadMore={makeMoreItems}\\n hasMore={state.totalItems > state.items.length}\\n loader={loader}\\n useWindow={false}\\n >\\n {renderedItems}\\n </InfiniteScroll>\\n </div>\\n ) : (\\n <p class=\\\"text-secondary\\\">\\n No posts{\\\" \\\"}\\n {props.term || props.tag || props.author ? \\\"matches search\\\" : \\\"\\\"}\\n {props.recency === \\\"hot\\\"\\n ? \\\" in \\\" + getPeriodText(state.period).toLowerCase()\\n : \\\"\\\"}\\n </p>\\n )}\\n </>\\n);\\n"