mirror of
https://github.com/dkhamsing/open-source-ios-apps.git
synced 2025-02-01 19:16:48 +01:00
Remove website (#1057)
This commit is contained in:
parent
63365b5c4b
commit
3597bc06ce
@ -1,10 +0,0 @@
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
@ -1,5 +0,0 @@
|
||||
.cache
|
||||
package.json
|
||||
package-lock.json
|
||||
public
|
||||
node_modules
|
@ -1,40 +0,0 @@
|
||||
{
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2020,
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier/@typescript-eslint",
|
||||
"prettier"
|
||||
],
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
"react",
|
||||
"react-hooks",
|
||||
"prettier"
|
||||
],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"react/prop-types": 0,
|
||||
"import/prefer-default-export": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off"
|
||||
}
|
||||
}
|
69
gatsby/.gitignore
vendored
69
gatsby/.gitignore
vendored
@ -1,69 +0,0 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Typescript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# dotenv environment variable files
|
||||
.env*
|
||||
|
||||
# gatsby files
|
||||
.cache/
|
||||
public
|
||||
|
||||
# Mac files
|
||||
.DS_Store
|
||||
|
||||
# Yarn
|
||||
yarn-error.log
|
||||
.pnp/
|
||||
.pnp.js
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
@ -1 +0,0 @@
|
||||
lts/erbium
|
@ -1,5 +0,0 @@
|
||||
.cache
|
||||
package.json
|
||||
package-lock.json
|
||||
public
|
||||
node_modules
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"arrowParens": "avoid",
|
||||
"semi": false,
|
||||
"printWidth": 80,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "all"
|
||||
}
|
53
gatsby/.vscode/settings.json
vendored
53
gatsby/.vscode/settings.json
vendored
@ -1,53 +0,0 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"files.encoding": "utf8",
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"files.insertFinalNewline": true,
|
||||
"search.exclude": {
|
||||
"public/**": true,
|
||||
"node_modules/**": true
|
||||
},
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"typescript",
|
||||
"typescriptreact"
|
||||
],
|
||||
"files.exclude": {
|
||||
"**/logs": true,
|
||||
"**/*.log": true,
|
||||
"**/npm-debug.log*": true,
|
||||
"**/yarn-debug.log*": true,
|
||||
"**/yarn-error.log*": true,
|
||||
"**/pids": true,
|
||||
"**/*.pid": true,
|
||||
"**/*.seed": true,
|
||||
"**/*.pid.lock": true,
|
||||
"**/lib-cov": true,
|
||||
"**/coverage": true,
|
||||
"**/.nyc_output": true,
|
||||
"**/.grunt": true,
|
||||
"**/bower_components": true,
|
||||
"**/.lock-wscript": true,
|
||||
"build/Release": true,
|
||||
"**/node_modules/": true,
|
||||
"**/jspm_packages/": true,
|
||||
"**/typings/": true,
|
||||
"**/.npm": true,
|
||||
"**/.eslintcache": true,
|
||||
"**/.node_repl_history": true,
|
||||
"**/*.tgz": true,
|
||||
"**/.env*": true,
|
||||
"**/.cache/": true,
|
||||
"**/public": true,
|
||||
"**/.DS_Store": true,
|
||||
"**/yarn-error.log": true,
|
||||
"**/.pnp/": true,
|
||||
"**/.pnp.js": true,
|
||||
"**/.yarn-integrity": true
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true,
|
||||
"source.fixAll": true
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 junscuzzy
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
117
gatsby/README.md
117
gatsby/README.md
@ -1,117 +0,0 @@
|
||||
# Gatsby's Typescript + Material-ui starter
|
||||
|
||||
[![Netlify Status](https://api.netlify.com/api/v1/badges/1b625068-4ac6-42d5-87fb-902d9077bbef/deploy-status)](https://app.netlify.com/sites/gatsby-material-typescript-starter/deploys)
|
||||
|
||||
Kick off your project with this [Material-ui](https://material-ui.com/) boilerplate. This starter ships with the main Gatsby configuration files you might need to get up and running blazing fast with the blazing fast app generator for React.
|
||||
It includes support for Typescript in front-side and node-side and uses Eslint & Prettier.
|
||||
|
||||
This starter don't have any source or style supports, it's your choice.
|
||||
|
||||
_Have another more specific idea? You may want to check out our vibrant collection of [official and community-created starters](https://www.gatsbyjs.org/docs/gatsby-starters/)._
|
||||
|
||||
## 🚀 Quick start
|
||||
|
||||
1. **Create a Gatsby site.**
|
||||
|
||||
Use the Gatsby CLI to create a new site, specifying the default starter.
|
||||
|
||||
```shell
|
||||
# create a new Gatsby site using the starter
|
||||
gatsby new gatsby-material-typescript-starter https://github.com/Junscuzzy/gatsby-material-typescript-starter
|
||||
```
|
||||
|
||||
1. **Start developing.**
|
||||
|
||||
Navigate into your new site’s directory and start it up.
|
||||
|
||||
```shell
|
||||
cd gatsby-material-typescript-starter/
|
||||
yarn develop
|
||||
```
|
||||
|
||||
1. **Open the source code and start editing!**
|
||||
|
||||
Your site is now running at `http://localhost:8000`!
|
||||
|
||||
_Note: You'll also see a second link: _`http://localhost:8000/___graphql`_. This is a tool you can use to experiment with querying your data. Learn more about using this tool in the [Gatsby tutorial](https://www.gatsbyjs.org/tutorial/part-five/#introducing-graphiql)._
|
||||
|
||||
Open the `gatsby-material-typescript-starter` directory in your code editor of choice and edit `src/pages/index.tsx`. Save your changes and the browser will update in real time!
|
||||
|
||||
1. **Bonus**: Check all linters using
|
||||
|
||||
```shell
|
||||
yarn lint
|
||||
```
|
||||
|
||||
Will execute Prettier, Eslint and Typescript checking
|
||||
|
||||
All the commands are in your `package.json > scripts`.
|
||||
|
||||
## 🧐 What's inside?
|
||||
|
||||
A quick look at the top-level files and directories you'll see in a Gatsby project.
|
||||
|
||||
.
|
||||
├── .vscode/
|
||||
├── node_modules/
|
||||
├── src/
|
||||
├── static/
|
||||
├── .editorconfig
|
||||
├── .eslintrc
|
||||
├── .gitignore
|
||||
├── .prettierrc
|
||||
├── gatsby-browser.js
|
||||
├── gatsby-config.js
|
||||
├── gatsby-node.js
|
||||
├── gatsby-ssr.js
|
||||
├── LICENSE
|
||||
├── package.json
|
||||
├── README.md
|
||||
├── tsconfig.json
|
||||
└── yarn.lock
|
||||
|
||||
1. **`/.vscode`**: VSCode projects settings.
|
||||
|
||||
1. **`/node_modules`**: This directory contains all of the modules of code that your project depends on (npm packages) are automatically installed.
|
||||
|
||||
1. **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for “source code”.
|
||||
|
||||
1. **`/static`**: Static files like `robots.txt` or `favicon.ico`.
|
||||
|
||||
1. **`.editorconfig`**: EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs.
|
||||
|
||||
1. **`.eslintrc`**: This is a configuration file for [Eslint](https://eslint.org/). Find and fix problems in your JavaScript code
|
||||
|
||||
1. **`.gitignore`**: This file tells git which files it should not track / not maintain a version history for.
|
||||
|
||||
1. **`.prettierrc`**: This is a configuration file for [Prettier](https://prettier.io/). Prettier is a tool to help keep the formatting of your code consistent.
|
||||
|
||||
1. **`gatsby-browser.js`**: This file is where Gatsby expects to find any usage of the [Gatsby browser APIs](https://www.gatsbyjs.org/docs/browser-apis/) (if any). These allow customization/extension of default Gatsby settings affecting the browser.
|
||||
|
||||
1. **`gatsby-config.js`**: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins you’d like to include, etc. (Check out the [config docs](https://www.gatsbyjs.org/docs/gatsby-config/) for more detail).
|
||||
|
||||
1. **`gatsby-node.js`**: This file is where Gatsby expects to find any usage of the [Gatsby Node APIs](https://www.gatsbyjs.org/docs/node-apis/) (if any). These allow customization/extension of default Gatsby settings affecting pieces of the site build process.
|
||||
|
||||
1. **`gatsby-ssr.js`**: This file is where Gatsby expects to find any usage of the [Gatsby server-side rendering APIs](https://www.gatsbyjs.org/docs/ssr-apis/) (if any). These allow customization of default Gatsby settings affecting server-side rendering.
|
||||
|
||||
1. **`LICENSE`**: Gatsby is licensed under the MIT license.
|
||||
|
||||
1. **`package.json`**: A manifest file for Node.js projects, which includes things like metadata (the project’s name, author, etc). This manifest is how npm knows which packages to install for your project.
|
||||
|
||||
1. **`README.md`**: A text file containing useful reference information about your project.
|
||||
|
||||
1. **`tsconfig.json`**: This is a configuration file for [Typescript](https://www.typescriptlang.org/). TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
|
||||
|
||||
1. **`yarn.lock`** (See `package.json` below, first). This is an automatically generated file based on the exact versions of your npm dependencies that were installed for your project. **(You won’t change this file directly).**
|
||||
|
||||
## 🎓 Learning Gatsby
|
||||
|
||||
Looking for more guidance? Full documentation for Gatsby lives [on the website](https://www.gatsbyjs.org/). Here are some places to start:
|
||||
|
||||
- **For most developers, we recommend starting with our [in-depth tutorial for creating a site with Gatsby](https://www.gatsbyjs.org/tutorial/).** It starts with zero assumptions about your level of ability and walks through every step of the process.
|
||||
|
||||
- **To dive straight into code samples, head [to our documentation](https://www.gatsbyjs.org/docs/).** In particular, check out the _Guides_, _API Reference_, and _Advanced Tutorials_ sections in the sidebar.
|
||||
|
||||
## 💫 Deploy
|
||||
|
||||
As a static generated website, you can deploy it on [Netlify](https://www.netlify.com), [Github Page](https://pages.github.com/) or [ZEIT Now](https://zeit.co/)
|
Binary file not shown.
Before Width: | Height: | Size: 21 KiB |
@ -1,8 +0,0 @@
|
||||
/**
|
||||
* Implement Gatsby's Browser APIs in this file.
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/browser-apis/
|
||||
*/
|
||||
|
||||
export { default as wrapRootElement } from './src/libs/wrapRootElement'
|
||||
export { default as wrapPageElement } from './src/libs/wrapPageElement'
|
@ -1,64 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const join = require('path').join
|
||||
|
||||
module.exports = {
|
||||
pathPrefix: '/open-source-ios/',
|
||||
siteMetadata: {
|
||||
title: `Open-Source iOS Apps`,
|
||||
description: `A collaborative list of open-source iOS, watchOS and tvOS apps.`,
|
||||
},
|
||||
plugins: [
|
||||
`gatsby-plugin-typescript`,
|
||||
`gatsby-plugin-react-helmet`,
|
||||
{
|
||||
resolve: 'gatsby-plugin-material-ui',
|
||||
// If you want to use styled components you should change the injection order.
|
||||
options: {
|
||||
// stylesProvider: {
|
||||
// injectFirst: true,
|
||||
// },
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-plugin-manifest`,
|
||||
options: {
|
||||
name: `open-source-ios-apps`,
|
||||
short_name: `os-ios-apps`,
|
||||
start_url: `/`,
|
||||
background_color: `#663399`,
|
||||
theme_color: `#3E3F3A`,
|
||||
display: `minimal-ui`,
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-transformer-json`,
|
||||
options: {
|
||||
// NOTE: Without this setting, the JSON types are named based on the
|
||||
// folder name. In the case of `content.json`, that depends on what the
|
||||
// directory name of the repo is. In netlify's case, that's `repo`.
|
||||
typeName: `jsonFile`,
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
name: `apps`,
|
||||
path: join(__dirname, `../`),
|
||||
// This aims to ignore everything EXCEPT the `contents.json` file at the
|
||||
// root of the repo
|
||||
ignore: [
|
||||
`**/.*`,
|
||||
`**/.*/**`,
|
||||
`**/gatsby/**`,
|
||||
`**/*.md`,
|
||||
`**/*.toml`,
|
||||
`**/LICENSE`,
|
||||
`**/Dangerfile`,
|
||||
],
|
||||
},
|
||||
},
|
||||
// this (optional) plugin enables Progressive Web App + Offline functionality
|
||||
// To learn more, visit: https://gatsby.dev/offline
|
||||
// `gatsby-plugin-offline`,
|
||||
],
|
||||
}
|
@ -1,199 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const path = require('path')
|
||||
const crypto = require('crypto')
|
||||
const Bluebird = require('bluebird')
|
||||
const util = require('util')
|
||||
|
||||
// Set this to true to enable more logging in this file
|
||||
const DEBUG = false
|
||||
const isDev = process.env.NODE_ENV === 'development'
|
||||
|
||||
const jsonTypeName = `jsonFile`
|
||||
|
||||
/**
|
||||
* Implement Gatsby's Node APIs in this file.
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/node-apis/
|
||||
*/
|
||||
|
||||
// You can delete this file if you're not using it
|
||||
|
||||
exports.onCreateNode = async ({ node, actions }) => {
|
||||
const { createNode } = actions
|
||||
|
||||
if (node.internal.type === jsonTypeName) {
|
||||
const { categories, projects } = node
|
||||
|
||||
if (DEBUG) console.error('Found the json node #QE5PnL')
|
||||
|
||||
let createdCategoryCount = 0
|
||||
let createdProjectCount = 0
|
||||
|
||||
await Bluebird.each(categories, async category => {
|
||||
if (typeof category.id !== 'string' || category.id.length < 1) {
|
||||
console.error('Invalid category #veJYyW', category)
|
||||
return
|
||||
}
|
||||
|
||||
// Count how many projects are in each category. We can't easily do this
|
||||
// in Gatsby's GraphQL API.
|
||||
const projectCount = projects.filter(project =>
|
||||
project['category-ids'].includes(category.id),
|
||||
).length
|
||||
|
||||
await createNode({
|
||||
...category,
|
||||
slug: category.id,
|
||||
parentSlug: category.parent,
|
||||
projectCount,
|
||||
id: `Category__${category.id}`,
|
||||
parent: node.id,
|
||||
internal: {
|
||||
type: `AppCategory`,
|
||||
contentDigest: crypto
|
||||
.createHash(`md5`)
|
||||
.update(JSON.stringify(category))
|
||||
.digest(`hex`),
|
||||
content: JSON.stringify(category),
|
||||
},
|
||||
})
|
||||
|
||||
createdCategoryCount++
|
||||
})
|
||||
|
||||
await Bluebird.each(projects, async project => {
|
||||
const contentDigest = crypto
|
||||
.createHash(`md5`)
|
||||
.update(JSON.stringify(project))
|
||||
.digest(`hex`)
|
||||
const id = `Project__${contentDigest}`
|
||||
|
||||
const projectNode = {
|
||||
...project,
|
||||
parent: node.id,
|
||||
id,
|
||||
internal: {
|
||||
type: `AppProject`,
|
||||
contentDigest,
|
||||
content: JSON.stringify(project),
|
||||
},
|
||||
}
|
||||
|
||||
await createNode(projectNode)
|
||||
|
||||
createdProjectCount++
|
||||
})
|
||||
|
||||
console.error(
|
||||
'Created counts #WVIeFH',
|
||||
createdCategoryCount,
|
||||
createdProjectCount,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
exports.createPages = async ({ actions, graphql, getNodesByType }) => {
|
||||
const { createPage } = actions
|
||||
|
||||
if (DEBUG) {
|
||||
const jsonNodes = getNodesByType(jsonTypeName)
|
||||
const fileNodes = getNodesByType(`File`)
|
||||
console.error(
|
||||
'START createPages() #IMKm8p',
|
||||
jsonNodes.length,
|
||||
fileNodes.length,
|
||||
)
|
||||
|
||||
const debugResult = await graphql(`
|
||||
query Debugging {
|
||||
allFile {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
internal {
|
||||
type
|
||||
}
|
||||
relativePath
|
||||
children {
|
||||
id
|
||||
internal {
|
||||
type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
console.error(
|
||||
'File nodes #bIMtXP',
|
||||
util.inspect(debugResult.data, { depth: null }),
|
||||
)
|
||||
}
|
||||
|
||||
const categoryTemplate = path.resolve('src/templates/category.tsx')
|
||||
const tagTemplate = path.resolve('src/templates/tag.tsx')
|
||||
|
||||
const categoryResult = await graphql(`
|
||||
query Categories {
|
||||
allAppCategory {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
title
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
const categories = categoryResult.data.allAppCategory.edges
|
||||
|
||||
categories.forEach(({ node: category }) => {
|
||||
createPage({
|
||||
path: `/category/${category.slug}/`,
|
||||
component: categoryTemplate,
|
||||
context: {
|
||||
id: category.id,
|
||||
slug: category.slug,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
const projectResult = await graphql(`
|
||||
query Projects {
|
||||
allAppProject {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
tags
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
const projects = projectResult.data.allAppProject.edges
|
||||
const tags = new Set()
|
||||
|
||||
projects.forEach(({ node: project }) => {
|
||||
if (project.tags && project.tags.length > 0) {
|
||||
project.tags.forEach(tag => {
|
||||
tags.add(tag)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
tags.forEach(tag => {
|
||||
createPage({
|
||||
path: `/tag/${tag}/`,
|
||||
component: tagTemplate,
|
||||
context: {
|
||||
tag,
|
||||
slug: tag,
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
/**
|
||||
* Implement Gatsby's SSR (Server Side Rendering) APIs in this file.
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/ssr-apis/
|
||||
*/
|
||||
|
||||
export { default as wrapRootElement } from './src/libs/wrapRootElement'
|
||||
export { default as wrapPageElement } from './src/libs/wrapPageElement'
|
@ -1,7 +0,0 @@
|
||||
[[plugins]]
|
||||
package = "netlify-plugin-gatsby-cache"
|
||||
|
||||
[build]
|
||||
ignore = "git diff —quiet HEAD^ HEAD . ../contents.json"
|
||||
publish = "public/"
|
||||
command = "head -n 2 ../contents.json && yarn run build"
|
@ -1,76 +0,0 @@
|
||||
{
|
||||
"name": "gatsby-material-typescript-starter",
|
||||
"private": true,
|
||||
"description": "A simple starter using Typescript & Material-ui",
|
||||
"version": "0.1.0",
|
||||
"author": "Julien CARON <juliencaron@protonmail.com>",
|
||||
"keywords": [
|
||||
"gatsby",
|
||||
"typescript",
|
||||
"eslint",
|
||||
"prettier",
|
||||
"material-ui"
|
||||
],
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "NODE_ENV=production gatsby build",
|
||||
"develop": "gatsby develop",
|
||||
"deploy-gh": "yarn build --prefix-paths && yarn gh-pages -d public",
|
||||
"start": "yarn develop",
|
||||
"serve": "gatsby serve",
|
||||
"clean": "gatsby clean",
|
||||
"lint": "run-p lint:**",
|
||||
"lint:prettier": "prettier --write \"**/*.{js,jsx,json,md}\"",
|
||||
"lint:eslint": "eslint 'src/**/*.{ts,tsx}'",
|
||||
"lint:typescript": "tsc",
|
||||
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/styles": "^4.10.0",
|
||||
"@reduxjs/toolkit": "^1.4.0",
|
||||
"bluebird": "^3.7.2",
|
||||
"deepmerge": "^4.2.2",
|
||||
"gatsby": "^2.24.56",
|
||||
"gatsby-plugin-manifest": "^2.4.28",
|
||||
"gatsby-plugin-material-ui": "^2.1.10",
|
||||
"gatsby-plugin-offline": "^3.2.27",
|
||||
"gatsby-plugin-react-helmet": "^3.3.10",
|
||||
"gatsby-plugin-typescript": "^2.4.19",
|
||||
"gatsby-source-filesystem": "^2.3.29",
|
||||
"gatsby-transformer-json": "^2.4.11",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-image-lightbox": "^5.1.1",
|
||||
"react-redux": "^7.2.1",
|
||||
"redux": "^4.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.6.4",
|
||||
"@types/react": "^16.9.49",
|
||||
"@types/react-dom": "^16.9.8",
|
||||
"@types/react-helmet": "^6.1.0",
|
||||
"@types/react-redux": "^7.1.9",
|
||||
"@types/redux": "^3.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.1.0",
|
||||
"@typescript-eslint/parser": "^4.1.0",
|
||||
"eslint": "^7.8.1",
|
||||
"eslint-config-prettier": "^6.11.0",
|
||||
"eslint-plugin-prettier": "^3.1.4",
|
||||
"eslint-plugin-react": "^7.20.6",
|
||||
"eslint-plugin-react-hooks": "^4.1.0",
|
||||
"gh-pages": "^3.1.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^2.1.1",
|
||||
"typescript": "^4.0.2"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Junscuzzy/gatsby-material-typescript-starter"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Junscuzzy/gatsby-material-typescript-starter/issues"
|
||||
}
|
||||
}
|
@ -1,209 +0,0 @@
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
createStyles,
|
||||
Divider,
|
||||
GridList,
|
||||
GridListTile,
|
||||
makeStyles,
|
||||
Theme,
|
||||
Typography,
|
||||
} from '@material-ui/core'
|
||||
import Star from '@material-ui/icons/Star'
|
||||
import { graphql, Link } from 'gatsby'
|
||||
import React, { useState } from 'react'
|
||||
import Lightbox from 'react-image-lightbox'
|
||||
import 'react-image-lightbox/style.css'
|
||||
import { Project } from '../types'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
description: {
|
||||
marginTop: theme.spacing(1),
|
||||
marginBottom: theme.spacing(1),
|
||||
fontSize: '1.2em',
|
||||
},
|
||||
tag: {
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
const urlToReaddable = (url: string) => {
|
||||
if (url.indexOf('https://github.com/') === 0) {
|
||||
return `@${url.substr('https://github.com/'.length)}`
|
||||
} else if (url.indexOf('http://github.com/') === 0) {
|
||||
return `@${url.substr('http://github.com/'.length)}`
|
||||
} else return url
|
||||
}
|
||||
|
||||
const starCountToIconCount = (githubStars: number): number => {
|
||||
if (githubStars > 2000) {
|
||||
return 5
|
||||
} else if (githubStars > 1000) {
|
||||
return 4
|
||||
} else if (githubStars > 500) {
|
||||
return 3
|
||||
} else if (githubStars > 200) {
|
||||
return 2
|
||||
} else if (githubStars > 100) {
|
||||
return 1
|
||||
} else return 0
|
||||
}
|
||||
|
||||
const RepeatingStars = ({ count }: { count: number }) => {
|
||||
return (
|
||||
<span>
|
||||
{Array.from({ length: count }).map((_, i) => (
|
||||
<Star key={i} />
|
||||
))}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
const ProjectCard = ({ project }: { project: Project }) => {
|
||||
const classes = useStyles()
|
||||
const [isLightboxOpen, setIsLightboxOpen] = useState(false)
|
||||
const [lightboxSlide, setLightboxSlide] = useState(0)
|
||||
|
||||
const showStarCount = starCountToIconCount(project.stars)
|
||||
const screenshotSources = project.screenshots || []
|
||||
const tags = project.tags || []
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Typography variant="h4" component="h2">
|
||||
{project.title}
|
||||
</Typography>
|
||||
{showStarCount > 0 ? <RepeatingStars count={showStarCount} /> : null}
|
||||
<Typography className={classes.description}>
|
||||
{project.description}
|
||||
</Typography>
|
||||
<Divider />
|
||||
<Typography>Language: {project.lang || 'en'}</Typography>
|
||||
<Typography>Added: {project.date_added || 'n/a'}</Typography>
|
||||
<Typography>GitHub Stars: {project.stars}</Typography>
|
||||
<Typography>
|
||||
Code:{' '}
|
||||
{project.source ? (
|
||||
<a href={project.source} target="_blank" rel="noreferrer">
|
||||
{urlToReaddable(project.source)}
|
||||
</a>
|
||||
) : (
|
||||
'n/a'
|
||||
)}
|
||||
</Typography>
|
||||
<Typography>
|
||||
License:{' '}
|
||||
{project.license ? (
|
||||
<a
|
||||
href={`https://choosealicense.com/licenses/${project.license}/`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{project.license}
|
||||
</a>
|
||||
) : (
|
||||
'n/a'
|
||||
)}
|
||||
</Typography>
|
||||
<Typography>
|
||||
App Store:{' '}
|
||||
{project.itunes ? (
|
||||
<a href={project.itunes} target="_blank" rel="noreferrer">
|
||||
{project.itunes}
|
||||
</a>
|
||||
) : (
|
||||
'n/a'
|
||||
)}
|
||||
</Typography>
|
||||
<Typography>
|
||||
Homepage:{' '}
|
||||
{project.homepage ? (
|
||||
<a href={project.homepage} target="_blank" rel="noreferrer">
|
||||
{project.homepage}
|
||||
</a>
|
||||
) : (
|
||||
'n/a'
|
||||
)}
|
||||
</Typography>
|
||||
<Typography>
|
||||
Tags:{' '}
|
||||
{tags.map(tag => {
|
||||
return (
|
||||
<Link key={tag} to={`/tag/${tag}/`} className={classes.tag}>
|
||||
#{tag}
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</Typography>
|
||||
{screenshotSources.length === 0 ? null : (
|
||||
<>
|
||||
<GridList cellHeight={160} cols={4}>
|
||||
{screenshotSources.map((url, i) => {
|
||||
return (
|
||||
<GridListTile key={i} cols={1}>
|
||||
<a
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
onClick={event => {
|
||||
event.preventDefault()
|
||||
setLightboxSlide(i)
|
||||
setIsLightboxOpen(true)
|
||||
}}
|
||||
>
|
||||
<img src={url} width="120" height="160" />
|
||||
</a>
|
||||
</GridListTile>
|
||||
)
|
||||
})}
|
||||
</GridList>
|
||||
{!isLightboxOpen ? null : (
|
||||
<Lightbox
|
||||
mainSrc={screenshotSources[lightboxSlide]}
|
||||
nextSrc={screenshotSources[lightboxSlide + 1]}
|
||||
prevSrc={screenshotSources[lightboxSlide - 1]}
|
||||
onCloseRequest={() => setIsLightboxOpen(false)}
|
||||
onMoveNextRequest={() => {
|
||||
setLightboxSlide(
|
||||
(lightboxSlide + screenshotSources.length + 1) %
|
||||
screenshotSources.length,
|
||||
)
|
||||
}}
|
||||
onMovePrevRequest={() => {
|
||||
setLightboxSlide(
|
||||
(lightboxSlide + screenshotSources.length - 1) %
|
||||
screenshotSources.length,
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProjectCard
|
||||
|
||||
export const projectCardFragment = graphql`
|
||||
fragment ProjectCardFields on AppProject {
|
||||
category_ids
|
||||
date_added
|
||||
description
|
||||
homepage
|
||||
id
|
||||
itunes
|
||||
lang
|
||||
license
|
||||
screenshots
|
||||
source
|
||||
stars
|
||||
suggested_by
|
||||
tags
|
||||
title
|
||||
}
|
||||
`
|
@ -1,40 +0,0 @@
|
||||
import React, { FC } from 'react'
|
||||
import { makeStyles } from '@material-ui/styles'
|
||||
import { Typography, Container, Theme } from '@material-ui/core'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
heroContent: {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
padding: theme.spacing(8, 0, 6),
|
||||
},
|
||||
}))
|
||||
|
||||
export interface HeroProps {
|
||||
title: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
const Hero: FC<HeroProps> = ({ title, description = '', children }) => {
|
||||
const classes = useStyles()
|
||||
return (
|
||||
<div className={classes.heroContent}>
|
||||
<Container maxWidth="md">
|
||||
<Typography
|
||||
component="h1"
|
||||
variant="h2"
|
||||
align="center"
|
||||
color="textPrimary"
|
||||
gutterBottom
|
||||
>
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography variant="h5" align="center" color="textSecondary" paragraph>
|
||||
{description}
|
||||
</Typography>
|
||||
{children}
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Hero
|
@ -1,93 +0,0 @@
|
||||
/**
|
||||
* SEO component that queries for data with
|
||||
* Gatsby's useStaticQuery React hook
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/use-static-query/
|
||||
*/
|
||||
|
||||
import React, { FC } from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useStaticQuery, graphql } from 'gatsby'
|
||||
|
||||
interface MetaProperty {
|
||||
property: string
|
||||
content: string
|
||||
}
|
||||
|
||||
interface MetaName {
|
||||
name: string
|
||||
content: string
|
||||
}
|
||||
|
||||
type Meta = MetaName | MetaProperty
|
||||
|
||||
export interface SEOProps {
|
||||
title: string
|
||||
description?: string
|
||||
lang?: string
|
||||
meta?: Meta[]
|
||||
}
|
||||
|
||||
const SEO: FC<SEOProps> = ({
|
||||
description = '',
|
||||
lang = 'en',
|
||||
meta = [],
|
||||
title,
|
||||
}) => {
|
||||
const { site } = useStaticQuery(
|
||||
graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
)
|
||||
|
||||
const metaDescription = description || site.siteMetadata.description
|
||||
|
||||
return (
|
||||
<Helmet
|
||||
htmlAttributes={{
|
||||
lang,
|
||||
}}
|
||||
title={title}
|
||||
titleTemplate={`%s | ${site.siteMetadata.title}`}
|
||||
meta={[
|
||||
{
|
||||
name: `description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: `og:title`,
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
property: `og:description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: `og:type`,
|
||||
content: `website`,
|
||||
},
|
||||
{
|
||||
name: `twitter:card`,
|
||||
content: `summary`,
|
||||
},
|
||||
{
|
||||
name: `twitter:title`,
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
name: `twitter:description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
].concat(meta)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default SEO
|
@ -1,21 +0,0 @@
|
||||
import { graphql, useStaticQuery } from 'gatsby'
|
||||
|
||||
export interface SiteMetadata {
|
||||
title: string
|
||||
description: string
|
||||
}
|
||||
|
||||
export default (): SiteMetadata => {
|
||||
const data = useStaticQuery(graphql`
|
||||
{
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
return data.site.siteMetadata
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 21 KiB |
@ -1,34 +0,0 @@
|
||||
import React, { FC } from 'react'
|
||||
|
||||
import { makeStyles } from '@material-ui/styles'
|
||||
import { Container, Typography, Theme, Link } from '@material-ui/core'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
footer: {
|
||||
padding: theme.spacing(3, 2),
|
||||
marginTop: theme.spacing(4),
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
}))
|
||||
|
||||
const Footer: FC = () => {
|
||||
const classes = useStyles()
|
||||
return (
|
||||
<footer className={classes.footer}>
|
||||
<Container maxWidth="md">
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
Built with the data from{' '}
|
||||
<Link
|
||||
href="https://github.com/dkhamsing/open-source-ios-apps"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
@dkhamsing/open-source-ios-apps
|
||||
</Link>
|
||||
</Typography>
|
||||
</Container>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
|
||||
export default Footer
|
@ -1,50 +0,0 @@
|
||||
import { AppBar, Button, Link, Toolbar, Typography } from '@material-ui/core'
|
||||
import { makeStyles } from '@material-ui/styles'
|
||||
import { Link as GatsbyLink } from 'gatsby'
|
||||
import React, { FC } from 'react'
|
||||
|
||||
const useStyles = makeStyles({
|
||||
toolbar: {},
|
||||
title: {
|
||||
flexGrow: 1,
|
||||
},
|
||||
link: {
|
||||
textDecoration: 'none',
|
||||
},
|
||||
})
|
||||
|
||||
export interface HeaderProps {
|
||||
siteTitle?: string
|
||||
}
|
||||
|
||||
const Header: FC<HeaderProps> = ({ siteTitle = '' }) => {
|
||||
const classes = useStyles()
|
||||
|
||||
return (
|
||||
<AppBar component="header" position="static">
|
||||
<Toolbar className={classes.toolbar}>
|
||||
<Typography variant="h6" className={classes.title}>
|
||||
<Link
|
||||
to="/"
|
||||
component={GatsbyLink}
|
||||
color="inherit"
|
||||
className={classes.link}
|
||||
>
|
||||
{siteTitle}
|
||||
</Link>
|
||||
</Typography>
|
||||
<Button
|
||||
color="inherit"
|
||||
component="a"
|
||||
href="https://github.com/dkhamsing/open-source-ios-apps"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
GitHub
|
||||
</Button>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
)
|
||||
}
|
||||
|
||||
export default Header
|
@ -1,46 +0,0 @@
|
||||
import React, { FC } from 'react'
|
||||
import { makeStyles, ThemeProvider } from '@material-ui/styles'
|
||||
import { Theme } from '@material-ui/core'
|
||||
import { useSelector } from 'react-redux'
|
||||
|
||||
import Header from './header'
|
||||
import Footer from './footer'
|
||||
import themes from '../theme'
|
||||
import useSiteMetadata from '../hooks/useSiteMetadata'
|
||||
import { RootState } from '../redux/store'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
root: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
minHeight: '100vh',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
},
|
||||
main: {
|
||||
backgroundColor: theme.palette.background.default,
|
||||
},
|
||||
}))
|
||||
|
||||
const LayoutComponent: FC = ({ children }) => {
|
||||
const classes = useStyles()
|
||||
const { title } = useSiteMetadata()
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<Header siteTitle={title} />
|
||||
<main className={classes.main}>{children}</main>
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Layout: FC = ({ children }) => {
|
||||
const { theme } = useSelector((state: RootState) => state.app)
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={themes[theme]}>
|
||||
<LayoutComponent>{children}</LayoutComponent>
|
||||
</ThemeProvider>
|
||||
)
|
||||
}
|
||||
|
||||
export default Layout
|
@ -1,17 +0,0 @@
|
||||
import React, { ReactNode } from 'react'
|
||||
import { ThemeProvider } from '@material-ui/styles'
|
||||
import { CssBaseline } from '@material-ui/core'
|
||||
|
||||
import themes from '../theme'
|
||||
import Layout from '../layout'
|
||||
|
||||
const wrapPageElement = ({ element }: { element: ReactNode }) => {
|
||||
return (
|
||||
<ThemeProvider theme={themes['light']}>
|
||||
<CssBaseline />
|
||||
<Layout>{element}</Layout>
|
||||
</ThemeProvider>
|
||||
)
|
||||
}
|
||||
|
||||
export default wrapPageElement
|
@ -1,10 +0,0 @@
|
||||
import React, { ReactNode } from 'react'
|
||||
import { Provider } from 'react-redux'
|
||||
|
||||
import store from '../redux/store'
|
||||
|
||||
const wrapRootElement = ({ element }: { element: ReactNode }) => {
|
||||
return <Provider store={store}>{element}</Provider>
|
||||
}
|
||||
|
||||
export default wrapRootElement
|
@ -1,30 +0,0 @@
|
||||
import React, { FC } from 'react'
|
||||
import { makeStyles } from '@material-ui/styles'
|
||||
import { Theme } from '@material-ui/core'
|
||||
|
||||
import SEO from '../components/seo'
|
||||
import { Typography, Container } from '@material-ui/core'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
root: {
|
||||
marginTop: theme.spacing(8),
|
||||
marginBottom: theme.spacing(2),
|
||||
},
|
||||
}))
|
||||
|
||||
const NotFoundPage: FC = () => {
|
||||
const classes = useStyles()
|
||||
return (
|
||||
<Container maxWidth="md" className={classes.root}>
|
||||
<SEO title="404: Not found" />
|
||||
<Typography variant="h2" gutterBottom component="h1">
|
||||
NOT FOUND
|
||||
</Typography>
|
||||
<Typography variant="body1">
|
||||
You just hit a route that doesn't exist... the sadness.
|
||||
</Typography>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default NotFoundPage
|
@ -1,158 +0,0 @@
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
CardContent,
|
||||
Grid,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemText,
|
||||
Theme,
|
||||
Typography,
|
||||
} from '@material-ui/core'
|
||||
import { makeStyles } from '@material-ui/styles'
|
||||
import { graphql, Link } from 'gatsby'
|
||||
import React, { FC } from 'react'
|
||||
import Hero from '../components/hero'
|
||||
import SEO from '../components/seo'
|
||||
import { Category } from '../types'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
wrapper: {
|
||||
paddingLeft: theme.spacing(2),
|
||||
paddingRight: theme.spacing(2),
|
||||
},
|
||||
button: {
|
||||
marginTop: theme.spacing(2),
|
||||
marginBottom: theme.spacing(2),
|
||||
},
|
||||
}))
|
||||
|
||||
const CategoryItem = ({
|
||||
category,
|
||||
categories,
|
||||
}: {
|
||||
category: Category
|
||||
categories: Category[]
|
||||
}) => {
|
||||
const classes = useStyles()
|
||||
|
||||
const childCategories = categories.filter(
|
||||
cat => cat.parentSlug === category.slug,
|
||||
)
|
||||
|
||||
return (
|
||||
<Grid item xs={12} sm={6} md={4}>
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Typography variant="h3">{category.title}</Typography>
|
||||
<Typography>{category.description}</Typography>
|
||||
<Typography>{category.projectCount} projects</Typography>
|
||||
<Button
|
||||
variant="contained"
|
||||
component={Link}
|
||||
fullWidth
|
||||
to={`/category/${category.slug}/`}
|
||||
className={classes.button}
|
||||
>
|
||||
Browse {category.title}
|
||||
</Button>
|
||||
|
||||
{childCategories.length === 0 ? null : (
|
||||
<>
|
||||
<Typography variant="h5" component="h4">
|
||||
Child categories:
|
||||
</Typography>
|
||||
<List>
|
||||
{childCategories.map(childCategory => {
|
||||
return (
|
||||
<ListItem
|
||||
button
|
||||
key={childCategory.id}
|
||||
component={Link}
|
||||
to={`/category/${childCategory.slug}/`}
|
||||
>
|
||||
<ListItemText
|
||||
primary={`${childCategory.title} (${childCategory.projectCount} projects)`}
|
||||
/>
|
||||
</ListItem>
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
</>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
type IndexPageProps = {
|
||||
data: {
|
||||
allAppCategory: {
|
||||
edges: {
|
||||
node: Category
|
||||
}[]
|
||||
}
|
||||
allAppProject: {
|
||||
totalCount: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const IndexPage: FC<IndexPageProps> = props => {
|
||||
const classes = useStyles()
|
||||
|
||||
const { edges: categoryEdges } = props.data.allAppCategory
|
||||
const projectCount = props.data.allAppProject.totalCount
|
||||
|
||||
const categories = categoryEdges.map(e => e.node)
|
||||
|
||||
const topLevelCategories = categories.filter(category => {
|
||||
return category.parentSlug === null
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<SEO title="Home" />
|
||||
<Hero
|
||||
title="Open-Source iOS Apps"
|
||||
description={`A community curated set of ${projectCount} open-source iOS apps.`}
|
||||
/>
|
||||
<div className={classes.wrapper}>
|
||||
<Grid container spacing={2}>
|
||||
{topLevelCategories.map(cat => {
|
||||
return (
|
||||
<CategoryItem
|
||||
key={cat.id}
|
||||
category={cat}
|
||||
categories={categories}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Grid>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const pageQuery = graphql`
|
||||
query IndexPageQuery {
|
||||
allAppCategory {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
slug
|
||||
parentSlug
|
||||
projectCount
|
||||
description
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
allAppProject {
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default IndexPage
|
@ -1,24 +0,0 @@
|
||||
import { createSlice } from '@reduxjs/toolkit'
|
||||
|
||||
export interface AppState {
|
||||
theme: 'light' | 'dark'
|
||||
}
|
||||
|
||||
const initialState: AppState = {
|
||||
theme: 'light',
|
||||
}
|
||||
|
||||
const app = createSlice({
|
||||
name: 'app',
|
||||
initialState,
|
||||
reducers: {
|
||||
toggleTheme(state) {
|
||||
const newTheme = state.theme === 'light' ? 'dark' : 'light'
|
||||
state.theme = newTheme
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const { toggleTheme } = app.actions
|
||||
|
||||
export default app.reducer
|
@ -1,23 +0,0 @@
|
||||
import { RootState } from './store'
|
||||
|
||||
export const loadState: () => RootState = () => {
|
||||
try {
|
||||
const serializedState = localStorage.getItem('state')
|
||||
if (serializedState === null || serializedState === 'undefined') {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return JSON.parse(serializedState)
|
||||
} catch (err) {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
export const saveState = (state: Partial<RootState>) => {
|
||||
try {
|
||||
const serializedState = JSON.stringify(state)
|
||||
localStorage.setItem('state', serializedState)
|
||||
} catch (err) {
|
||||
// Ignore write errors
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
import { configureStore } from '@reduxjs/toolkit'
|
||||
import { combineReducers } from 'redux'
|
||||
|
||||
import app from '../redux/appModule'
|
||||
import { loadState, saveState } from './persistStore'
|
||||
|
||||
const preloadedState = loadState()
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
app,
|
||||
})
|
||||
|
||||
const store = configureStore({
|
||||
reducer: rootReducer,
|
||||
preloadedState,
|
||||
})
|
||||
|
||||
store.subscribe(() => {
|
||||
const { app } = store.getState()
|
||||
saveState({ app })
|
||||
})
|
||||
|
||||
export type RootState = ReturnType<typeof rootReducer>
|
||||
export type RootDispatch = typeof store.dispatch
|
||||
|
||||
export default store
|
@ -1,93 +0,0 @@
|
||||
import {
|
||||
Button,
|
||||
createStyles,
|
||||
Grid,
|
||||
makeStyles,
|
||||
Theme,
|
||||
Typography,
|
||||
} from '@material-ui/core'
|
||||
import { graphql, Link } from 'gatsby'
|
||||
import React from 'react'
|
||||
import Hero from '../components/hero'
|
||||
import ProjectCard from '../components/ProjectCard'
|
||||
import SEO from '../components/seo'
|
||||
import { Category, Project } from '../types'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
wrapper: {
|
||||
paddingLeft: theme.spacing(2),
|
||||
paddingRight: theme.spacing(2),
|
||||
},
|
||||
backButton: {
|
||||
textAlign: 'center',
|
||||
margin: theme.spacing(4),
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
type Props = {
|
||||
data: {
|
||||
appCategory: Category
|
||||
allAppProject: {
|
||||
edges: {
|
||||
node: Project
|
||||
}[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const CategoryTemplate: React.FC<Props> = props => {
|
||||
const classes = useStyles()
|
||||
|
||||
const category = props.data.appCategory
|
||||
const projectEdges = props.data.allAppProject.edges
|
||||
const projects: Project[] = projectEdges.map(n => n.node)
|
||||
|
||||
return (
|
||||
<>
|
||||
<SEO title="Home" />
|
||||
<Hero
|
||||
title={`Category: ${category.title}`}
|
||||
description={category.description || ''}
|
||||
></Hero>
|
||||
<Typography className={classes.backButton}>
|
||||
<Button component={Link} to="/" variant="contained">
|
||||
Back to category list
|
||||
</Button>
|
||||
</Typography>
|
||||
<div className={classes.wrapper}>
|
||||
<Grid container spacing={2}>
|
||||
{projects.map(project => {
|
||||
return (
|
||||
<Grid item xs={12} sm={6} key={project.id}>
|
||||
<ProjectCard project={project} />
|
||||
</Grid>
|
||||
)
|
||||
})}
|
||||
</Grid>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default CategoryTemplate
|
||||
|
||||
export const pageQuery = graphql`
|
||||
query CategoryPageQuery($slug: String!) {
|
||||
appCategory(slug: { eq: $slug }) {
|
||||
id
|
||||
description
|
||||
slug
|
||||
title
|
||||
}
|
||||
|
||||
allAppProject(filter: { category_ids: { eq: $slug } }) {
|
||||
edges {
|
||||
node {
|
||||
...ProjectCardFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
@ -1,74 +0,0 @@
|
||||
import { createStyles, Grid, makeStyles, Theme } from '@material-ui/core'
|
||||
import { graphql } from 'gatsby'
|
||||
import React from 'react'
|
||||
import Hero from '../components/hero'
|
||||
import ProjectCard from '../components/ProjectCard'
|
||||
import SEO from '../components/seo'
|
||||
import { Category, Project } from '../types'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
wrapper: {
|
||||
paddingLeft: theme.spacing(2),
|
||||
paddingRight: theme.spacing(2),
|
||||
},
|
||||
backButton: {
|
||||
textAlign: 'center',
|
||||
margin: theme.spacing(4),
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
type Props = {
|
||||
data: {
|
||||
appCategory: Category
|
||||
allAppProject: {
|
||||
edges: {
|
||||
node: Project
|
||||
}[]
|
||||
}
|
||||
}
|
||||
pageContext: {
|
||||
tag: string
|
||||
slug: string
|
||||
}
|
||||
}
|
||||
|
||||
const TagTemplate: React.FC<Props> = props => {
|
||||
const classes = useStyles()
|
||||
|
||||
const projectEdges = props.data.allAppProject.edges
|
||||
const projects: Project[] = projectEdges.map(n => n.node)
|
||||
|
||||
return (
|
||||
<>
|
||||
<SEO title="Home" />
|
||||
<Hero title={`Tag: #${props.pageContext.tag}`} description=""></Hero>
|
||||
<div className={classes.wrapper}>
|
||||
<Grid container spacing={2}>
|
||||
{projects.map(project => {
|
||||
return (
|
||||
<Grid item xs={12} sm={6} key={project.id}>
|
||||
<ProjectCard project={project} />
|
||||
</Grid>
|
||||
)
|
||||
})}
|
||||
</Grid>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default TagTemplate
|
||||
|
||||
export const pageQuery = graphql`
|
||||
query TagPageQuery($slug: String!) {
|
||||
allAppProject(filter: { tags: { eq: $slug } }) {
|
||||
edges {
|
||||
node {
|
||||
...ProjectCardFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
@ -1,46 +0,0 @@
|
||||
import deepMerge from 'deepmerge'
|
||||
import { red } from '@material-ui/core/colors'
|
||||
import {
|
||||
createMuiTheme,
|
||||
responsiveFontSizes,
|
||||
ThemeOptions,
|
||||
Theme,
|
||||
} from '@material-ui/core/styles'
|
||||
|
||||
const makeTheme = (variant: ThemeOptions): Theme => {
|
||||
const common = {
|
||||
palette: {
|
||||
primary: {
|
||||
main: '#3E3F3A',
|
||||
},
|
||||
secondary: {
|
||||
main: '#19857b',
|
||||
},
|
||||
error: {
|
||||
main: red.A400,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const theme = createMuiTheme(deepMerge(common, variant))
|
||||
return responsiveFontSizes(theme)
|
||||
}
|
||||
|
||||
const light: ThemeOptions = {
|
||||
palette: {
|
||||
type: 'light',
|
||||
},
|
||||
}
|
||||
|
||||
const dark: ThemeOptions = {
|
||||
palette: {
|
||||
type: 'dark',
|
||||
},
|
||||
}
|
||||
|
||||
const themes = {
|
||||
light: makeTheme(light),
|
||||
dark: makeTheme(dark),
|
||||
}
|
||||
|
||||
export default themes
|
@ -1,25 +0,0 @@
|
||||
export type Category = {
|
||||
id: string
|
||||
slug: string
|
||||
parentSlug: string | null
|
||||
projectCount: number
|
||||
description: string | null
|
||||
title: string | null
|
||||
}
|
||||
|
||||
export type Project = {
|
||||
category_ids: string[]
|
||||
date_added: string
|
||||
description: string | null
|
||||
homepage: string | null
|
||||
id: string
|
||||
itunes: string | null
|
||||
lang: string | null
|
||||
license: string
|
||||
screenshots: string[]
|
||||
source: string | null
|
||||
stars: number
|
||||
suggested_by: string
|
||||
tags: string[]
|
||||
title: string
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 198 B |
@ -1,2 +0,0 @@
|
||||
User-agent: *
|
||||
Disallow:
|
@ -1,19 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"lib": ["dom", "esnext"],
|
||||
"noImplicitAny": true,
|
||||
"jsx": "preserve",
|
||||
"sourceMap": true,
|
||||
"removeComments": true,
|
||||
"noEmit": true,
|
||||
"isolatedModules": true,
|
||||
"strict": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "public", ".cache"]
|
||||
}
|
13662
gatsby/yarn.lock
13662
gatsby/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -1,2 +0,0 @@
|
||||
[build]
|
||||
base = "gatsby"
|
Loading…
x
Reference in New Issue
Block a user