├── .eslintrc.json
├── .gitbook
└── assets
│ ├── screenshot-2021-09-22-211556.png
│ ├── spaces_gitbook_avatar-rectangle (1).png
│ └── spaces_gitbook_avatar-rectangle.png
├── .github
└── workflows
│ ├── publish.yml
│ └── tests.yml
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SUMMARY.md
├── base-tsconfig.json
├── concept.md
├── documentation
└── getting_started.md
├── getting-started.md
├── lerna.json
├── package-lock.json
├── package.json
└── packages
├── README.md
├── base-shell
├── .gitignore
├── README.md
├── create-base-shell
│ ├── index.js
│ ├── package.json
│ └── template
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── index.html
│ │ ├── jsconfig.json
│ │ ├── package.json
│ │ ├── public
│ │ ├── favicon.ico
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ │ ├── src
│ │ ├── config
│ │ │ ├── config.jsx
│ │ │ ├── defaultRoutes.jsx
│ │ │ ├── index.js
│ │ │ ├── locales
│ │ │ │ ├── de.js
│ │ │ │ ├── en.js
│ │ │ │ ├── index.js
│ │ │ │ └── ru.js
│ │ │ ├── menuItems.js
│ │ │ └── routes.jsx
│ │ ├── containers
│ │ │ └── Menu
│ │ │ │ └── index.jsx
│ │ ├── demo-index.jsx
│ │ └── pages
│ │ │ ├── About
│ │ │ └── index.jsx
│ │ │ ├── Home
│ │ │ └── index.jsx
│ │ │ ├── LandingPage
│ │ │ └── index.jsx
│ │ │ ├── PageNotFound
│ │ │ └── index.jsx
│ │ │ └── SignIn
│ │ │ └── index.jsx
│ │ └── vite.config.js
├── cypress.config.ts
├── cypress
│ ├── e2e
│ │ └── spec.cy.js
│ ├── fixtures
│ │ └── example.json
│ └── support
│ │ ├── commands.js
│ │ └── e2e.js
├── index.html
├── package.json
├── src
│ ├── components
│ │ ├── AuthorizedRoute
│ │ │ └── index.tsx
│ │ ├── UnauthorizedRoute
│ │ │ └── index.tsx
│ │ └── index.ts
│ ├── containers
│ │ ├── App
│ │ │ └── index.tsx
│ │ ├── Layout
│ │ │ └── index.tsx
│ │ └── index.ts
│ ├── index.ts
│ ├── providers
│ │ ├── AddToHomeScreen
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ └── index.tsx
│ │ ├── Auth
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ └── index.tsx
│ │ ├── Config
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ └── index.tsx
│ │ ├── Locale
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ └── index.tsx
│ │ ├── Online
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ └── index.tsx
│ │ ├── SimpleValues
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ └── index.tsx
│ │ ├── Update
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ └── index.tsx
│ │ └── index.ts
│ └── utils
│ │ ├── config.ts
│ │ ├── index.ts
│ │ └── locale.ts
├── tsconfig.json
└── vite.config.ts
├── bootstrap-shell
├── .gitignore
├── .travis.yml
├── .vscode
│ └── launch.json
├── README.md
├── cra-template-bs
│ ├── README.md
│ ├── package.json
│ ├── template.json
│ └── template
│ │ ├── gitignore
│ │ ├── jsconfig.json
│ │ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ │ └── src
│ │ ├── App.js
│ │ ├── components
│ │ ├── Loading.js
│ │ ├── Loading
│ │ │ └── Loading.js
│ │ └── Menu
│ │ │ └── MenuRight.js
│ │ ├── config
│ │ ├── config.js
│ │ ├── dark.scss
│ │ ├── index.js
│ │ ├── locales
│ │ │ ├── de.js
│ │ │ ├── en.js
│ │ │ ├── index.js
│ │ │ └── ru.js
│ │ ├── menuItems.js
│ │ ├── routes.js
│ │ └── themes.js
│ │ ├── index.js
│ │ └── pages
│ │ ├── DialogDemo
│ │ └── index.js
│ │ ├── Home
│ │ └── Home.js
│ │ ├── LandingPage
│ │ ├── LandingPage.js
│ │ └── index.js
│ │ └── PageNotFound
│ │ └── PageNotFound.js
├── demo
│ └── src
│ │ └── index.js
├── nwb.config.js
├── package-lock.json
├── package.json
├── src
│ ├── assets
│ │ └── rmw.svg
│ ├── components
│ │ ├── Menu
│ │ │ ├── Menu.js
│ │ │ ├── MenuDropdown.js
│ │ │ └── MenuDropdownMobile.js
│ │ └── Modal
│ │ │ └── index.js
│ ├── containers
│ │ ├── LayoutContainer
│ │ │ └── LayoutContainer.js
│ │ └── Page
│ │ │ └── Page.js
│ ├── index.js
│ ├── providers
│ │ ├── Menu
│ │ │ ├── Context.js
│ │ │ ├── Provider.js
│ │ │ ├── index.js
│ │ │ ├── store
│ │ │ │ ├── actions.js
│ │ │ │ ├── reducer.js
│ │ │ │ └── types.js
│ │ │ └── with.js
│ │ ├── Modal
│ │ │ ├── Context.js
│ │ │ ├── Provider.js
│ │ │ ├── index.js
│ │ │ ├── store
│ │ │ │ ├── actions.js
│ │ │ │ ├── reducer.js
│ │ │ │ └── types.js
│ │ │ └── with.js
│ │ └── Theme
│ │ │ ├── Context.js
│ │ │ ├── Provider.js
│ │ │ ├── index.js
│ │ │ └── with.js
│ ├── styles
│ │ └── custom-bootstrap.css
│ └── utils
│ │ └── theme.js
└── tests
│ ├── .eslintrc
│ └── index.test.js
├── firebase-function-tools
├── .gitignore
├── .travis.yml
├── README.md
├── nwb.config.js
├── package-lock.json
├── package.json
├── src
│ ├── counting.js
│ ├── customClaims.js
│ ├── index.js
│ ├── load.js
│ ├── notifications.js
│ ├── thumbnail.js
│ └── users.js
└── tests
│ ├── .eslintrc
│ └── index-test.js
├── material-ui-shell
├── .gitignore
├── README.md
├── create-material-ui-shell
│ ├── index.js
│ ├── package.json
│ └── template
│ │ ├── .gitignore
│ │ ├── index.html
│ │ ├── jsconfig.json
│ │ ├── package.json
│ │ ├── public
│ │ ├── favicon.ico
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ │ ├── src
│ │ ├── components
│ │ │ ├── CustomPaper
│ │ │ │ └── index.jsx
│ │ │ └── Menu
│ │ │ │ ├── MenuContent.jsx
│ │ │ │ └── index.jsx
│ │ ├── config
│ │ │ ├── config.jsx
│ │ │ ├── index.js
│ │ │ ├── locales
│ │ │ │ ├── de.js
│ │ │ │ ├── en.js
│ │ │ │ ├── index.js
│ │ │ │ └── ru.js
│ │ │ ├── menuItems.jsx
│ │ │ ├── routes.jsx
│ │ │ └── themes.js
│ │ ├── demo-index.jsx
│ │ └── pages
│ │ │ ├── About
│ │ │ └── index.jsx
│ │ │ ├── DialogDemo
│ │ │ └── index.jsx
│ │ │ ├── FilterDemo
│ │ │ ├── data.json
│ │ │ └── index.jsx
│ │ │ ├── Home
│ │ │ └── index.jsx
│ │ │ ├── LandingPage
│ │ │ └── index.jsx
│ │ │ ├── ListPageDemo
│ │ │ ├── data.json
│ │ │ └── index.jsx
│ │ │ ├── MyAccount
│ │ │ └── index.jsx
│ │ │ ├── PageNotFound
│ │ │ └── index.jsx
│ │ │ ├── PasswordReset
│ │ │ └── index.jsx
│ │ │ ├── SignIn
│ │ │ └── index.jsx
│ │ │ ├── SignUp
│ │ │ └── index.jsx
│ │ │ ├── TabsDemo
│ │ │ └── index.jsx
│ │ │ └── ToastDemo
│ │ │ └── index.jsx
│ │ └── vite.config.js
├── cypress.config.ts
├── cypress
│ ├── e2e
│ │ └── spec.cy.js
│ ├── fixtures
│ │ └── example.json
│ ├── screenshots
│ │ └── spec.cy.js
│ │ │ └── My React App -- renders app container top text (failed).png
│ └── support
│ │ ├── commands.js
│ │ └── e2e.js
├── demo.jsx
├── index.html
├── package.json
├── src
│ ├── common.type.ts
│ ├── components
│ │ ├── FilterDrawer
│ │ │ └── index.tsx
│ │ ├── Loading
│ │ │ └── index.tsx
│ │ ├── MenuHeader
│ │ │ └── index.tsx
│ │ ├── QuestionDialog
│ │ │ └── index.tsx
│ │ ├── Scrollbar
│ │ │ └── index.tsx
│ │ ├── SearchField
│ │ │ └── index.tsx
│ │ ├── UpdateDialog
│ │ │ └── index.tsx
│ │ └── index.ts
│ ├── containers
│ │ ├── ImageUploadDialog
│ │ │ ├── getCropImage.tsx
│ │ │ └── index.tsx
│ │ ├── LayoutContainer
│ │ │ └── index.tsx
│ │ ├── Menu
│ │ │ └── index.tsx
│ │ ├── ResponsiveMenu
│ │ │ └── index.tsx
│ │ ├── SelectableMenuList
│ │ │ └── index.tsx
│ │ ├── UpdateContainer
│ │ │ └── index.tsx
│ │ ├── VirtualList
│ │ │ └── index.tsx
│ │ └── index.ts
│ ├── index.ts
│ ├── pages
│ │ ├── LandingPage
│ │ │ └── index.tsx
│ │ ├── ListPage
│ │ │ └── index.tsx
│ │ ├── Page
│ │ │ └── index.tsx
│ │ ├── PageNotFound
│ │ │ └── index.tsx
│ │ └── index.ts
│ ├── providers
│ │ ├── Dialogs
│ │ │ └── Question
│ │ │ │ ├── Context.tsx
│ │ │ │ ├── Provider.tsx
│ │ │ │ └── index.tsx
│ │ ├── Filter
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ ├── fields
│ │ │ │ ├── boolean.tsx
│ │ │ │ ├── date.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── number.tsx
│ │ │ │ ├── text.tsx
│ │ │ │ └── time.tsx
│ │ │ ├── index.tsx
│ │ │ └── store
│ │ │ │ ├── actions.tsx
│ │ │ │ ├── reducer.tsx
│ │ │ │ ├── selectors.tsx
│ │ │ │ └── types.tsx
│ │ ├── Menu
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ ├── index.tsx
│ │ │ └── store
│ │ │ │ ├── actions.tsx
│ │ │ │ ├── reducer.tsx
│ │ │ │ └── types.tsx
│ │ ├── Theme
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ └── index.tsx
│ │ ├── VirtualLists
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ └── index.tsx
│ │ └── index.ts
│ └── utils
│ │ └── index.ts
├── tsconfig.json
└── vite.config.ts
└── rmw-shell
├── .gitignore
├── CONTRIBUTING.md
├── README.md
├── create-rmw-shell
├── index.js
├── package.json
└── template
│ ├── .firebaserc
│ ├── .gitignore
│ ├── firebase.json
│ ├── firebase
│ ├── database.rules.json
│ ├── firestore.indexes.json
│ ├── firestore.rules
│ ├── functions
│ │ ├── .gitignore
│ │ ├── auth
│ │ │ ├── onCreate.f.js
│ │ │ └── onDelete.f.js
│ │ ├── db
│ │ │ ├── admins
│ │ │ │ └── onWrite.f.js
│ │ │ ├── groupChatMessages
│ │ │ │ └── onCreate.f.js
│ │ │ ├── groupChats
│ │ │ │ ├── members
│ │ │ │ │ ├── onCreate.f.js
│ │ │ │ │ └── onDelete.f.js
│ │ │ │ └── name
│ │ │ │ │ └── onUpdate.f.js
│ │ │ ├── publicChats
│ │ │ │ └── onCreate.f.js
│ │ │ ├── roleGrants
│ │ │ │ └── onWrite.f.js
│ │ │ ├── roles
│ │ │ │ └── onWrite.f.js
│ │ │ ├── triggers
│ │ │ │ └── onCreate.f.js
│ │ │ ├── userChatMessages
│ │ │ │ ├── onCreate.f.js
│ │ │ │ └── onUpdate.f.js
│ │ │ ├── userGrants
│ │ │ │ └── onWrite.f.js
│ │ │ ├── userRoles
│ │ │ │ └── onWrite.f.js
│ │ │ ├── users
│ │ │ │ └── onWrite.f.js
│ │ │ └── usersCount
│ │ │ │ └── onDelete.f.js
│ │ ├── gitignore
│ │ ├── https
│ │ │ ├── admin
│ │ │ │ └── onCall.f.js
│ │ │ ├── api
│ │ │ │ ├── companies
│ │ │ │ │ └── onRequest.f.js
│ │ │ │ └── users
│ │ │ │ │ └── onRequest.f.js
│ │ │ ├── messages
│ │ │ │ └── onCall.f.js
│ │ │ └── usersSync
│ │ │ │ └── onCall.f.js
│ │ ├── index.js
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── storage
│ │ │ ├── onFinalize.f.js
│ │ │ └── thumbnails.js
│ │ └── utils
│ │ │ ├── customClaims.js
│ │ │ ├── splitStringToArray.js
│ │ │ └── users.js
│ └── storage.rules
│ ├── index.html
│ ├── jsconfig.json
│ ├── package.json
│ ├── public
│ ├── 404.svg
│ ├── background.webp
│ ├── bottom.jpg
│ ├── favicon.ico
│ ├── firebase-messaging-sw.js
│ ├── firebase.png
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ ├── maskable_icon.png
│ ├── material-ui.png
│ ├── react.png
│ ├── rmw.svg
│ └── robots.txt
│ ├── src
│ ├── components
│ │ ├── Forms
│ │ │ ├── Company.jsx
│ │ │ └── Task.jsx
│ │ └── Menu
│ │ │ └── MenuContent.jsx
│ ├── config
│ │ ├── config.jsx
│ │ ├── getDefaultRoutes.jsx
│ │ ├── grants.jsx
│ │ ├── index.jsx
│ │ ├── locales
│ │ │ ├── de.js
│ │ │ ├── en.js
│ │ │ ├── index.js
│ │ │ └── ru.js
│ │ ├── menuItems.jsx
│ │ ├── routes.jsx
│ │ └── themes.jsx
│ ├── containers
│ │ └── Reports
│ │ │ ├── Days.jsx
│ │ │ ├── Months.jsx
│ │ │ └── Providers.jsx
│ ├── demo-index.jsx
│ ├── index.html
│ ├── pages
│ │ ├── About
│ │ │ └── index.jsx
│ │ ├── Dashboard
│ │ │ └── index.jsx
│ │ ├── Demo
│ │ │ ├── Admin
│ │ │ │ └── index.jsx
│ │ │ ├── Companies
│ │ │ │ ├── Company.jsx
│ │ │ │ └── index.jsx
│ │ │ └── Tasks
│ │ │ │ ├── Task.jsx
│ │ │ │ └── index.jsx
│ │ ├── Firebase
│ │ │ ├── Cols.jsx
│ │ │ ├── Docs.jsx
│ │ │ ├── Lists.jsx
│ │ │ ├── Messaging.jsx
│ │ │ ├── Paths.jsx
│ │ │ └── Storage.jsx
│ │ ├── LandingPage
│ │ │ ├── Footer.jsx
│ │ │ ├── PageContent.jsx
│ │ │ ├── index.jsx
│ │ │ └── messages
│ │ │ │ ├── bs.json
│ │ │ │ ├── de.json
│ │ │ │ ├── en.json
│ │ │ │ ├── es.json
│ │ │ │ ├── fr.json
│ │ │ │ ├── index.js
│ │ │ │ ├── it.json
│ │ │ │ ├── pt.json
│ │ │ │ └── ru.json
│ │ ├── PageNotFound
│ │ │ ├── 404.svg
│ │ │ └── index.jsx
│ │ └── Search
│ │ │ └── index.jsx
│ ├── service-worker.js
│ └── serviceWorkerRegistration.js
│ └── vite.config.js
├── cypress.config.js
├── cypress
├── e2e
│ └── spec.cy.js
├── fixtures
│ └── example.json
└── support
│ ├── commands.js
│ └── e2e.js
├── index.html
├── package.json
├── src
├── components
│ ├── ChatMessage
│ │ └── index.tsx
│ ├── FormFields
│ │ ├── Autocomplete.tsx
│ │ ├── AvatarImage.tsx
│ │ ├── DatePicker.tsx
│ │ ├── KeyboardDatePicker.tsx
│ │ ├── TextField.tsx
│ │ ├── Util.tsx
│ │ └── index.tsx
│ ├── Forms
│ │ ├── Role.tsx
│ │ └── index.tsx
│ ├── Icons
│ │ ├── FacebookIcon.tsx
│ │ ├── GitHubIcon.tsx
│ │ ├── GoogleIcon.tsx
│ │ ├── RMWIcon.tsx
│ │ ├── ReduxIcon.tsx
│ │ ├── TwitterIcon.tsx
│ │ └── index.tsx
│ ├── SnackMessage
│ │ └── index.tsx
│ ├── UserRow
│ │ └── index.tsx
│ └── index.ts
├── containers
│ ├── AuthUI
│ │ └── index.tsx
│ ├── Chat
│ │ ├── Input.tsx
│ │ └── index.tsx
│ ├── Firebase
│ │ ├── From.tsx
│ │ └── index.tsx
│ ├── GrantsList
│ │ └── index.tsx
│ ├── ImageUploadDialog
│ │ ├── getCropImage.tsx
│ │ └── index.tsx
│ ├── ImageViewer
│ │ └── index.tsx
│ ├── Layout
│ │ └── index.tsx
│ ├── Page
│ │ ├── FormPage.tsx
│ │ ├── ListPage.tsx
│ │ ├── MarkdownPage.tsx
│ │ └── index.tsx
│ ├── ResponsiveMenu
│ │ └── index.tsx
│ ├── RolesList
│ │ └── index.tsx
│ └── index.ts
├── index.ts
├── pages
│ ├── Chats
│ │ └── index.tsx
│ ├── CreateChat
│ │ └── index.tsx
│ ├── EditAdmins
│ │ └── index.tsx
│ ├── EditMembers
│ │ └── index.tsx
│ ├── GroupChat
│ │ └── index.tsx
│ ├── MyAccount
│ │ └── index.tsx
│ ├── Roles
│ │ ├── Role.tsx
│ │ └── index.tsx
│ ├── SignIn
│ │ └── index.tsx
│ ├── Users
│ │ ├── User.tsx
│ │ └── index.tsx
│ └── index.ts
├── providers
│ ├── Firebase
│ │ ├── Cols
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ └── index.tsx
│ │ ├── Docs
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ └── index.tsx
│ │ ├── Lists
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ └── index.tsx
│ │ ├── Messaging
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ └── index.tsx
│ │ ├── Paths
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ └── index.tsx
│ │ └── Storage
│ │ │ ├── Context.tsx
│ │ │ ├── Provider.tsx
│ │ │ └── index.tsx
│ └── index.ts
└── utils
│ ├── auth.tsx
│ ├── index.ts
│ ├── locale.tsx
│ └── location.tsx
├── tests
├── .eslintrc
└── index.test.js
├── tsconfig.json
└── vite.config.ts
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["react-app"]
3 | }
4 |
--------------------------------------------------------------------------------
/.gitbook/assets/screenshot-2021-09-22-211556.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/.gitbook/assets/screenshot-2021-09-22-211556.png
--------------------------------------------------------------------------------
/.gitbook/assets/spaces_gitbook_avatar-rectangle (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/.gitbook/assets/spaces_gitbook_avatar-rectangle (1).png
--------------------------------------------------------------------------------
/.gitbook/assets/spaces_gitbook_avatar-rectangle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/.gitbook/assets/spaces_gitbook_avatar-rectangle.png
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: Tests
2 |
3 | on:
4 | pull_request:
5 | branches: [master]
6 |
7 | jobs:
8 | test:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v4
12 | - name: Use Node.js
13 | uses: actions/setup-node@v4
14 | with:
15 | node-version: "20"
16 | - name: Install dependencies
17 | run: npm ci
18 | - name: Run tests
19 | run: npx lerna run test:package --since master
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | npm-debug.log*
3 | .dccache
4 | .DS_Store
5 | lerna-dubug.log
6 | .npmrc
7 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Prerequisites
2 |
3 | [Node.js](http://nodejs.org/) >= v4 must be installed.
4 |
5 | ## Installation
6 |
7 | - Running `npm install` in the components's root directory will install everything you need for development.
8 |
9 | ## Demo Development Server
10 |
11 | - `npm start` will run a development server with the component's demo app at [http://localhost:3000](http://localhost:3000) with hot module reloading.
12 |
13 | ## Running Tests
14 |
15 | - `npm test` will run the tests once.
16 |
17 | - `npm run test:coverage` will run the tests and produce a coverage report in `coverage/`.
18 |
19 | - `npm run test:watch` will run the tests on every change.
20 |
21 | ## Building
22 |
23 | - `npm run build` will build the component for publishing to npm and also bundle the demo app.
24 |
25 | - `npm run clean` will delete built resources.
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Tarik Huber
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Table of contents
2 |
3 | * [React Most Wanted](README.md)
4 | * [Concept](concept.md)
5 | * [Getting started](getting-started.md)
6 |
7 |
--------------------------------------------------------------------------------
/base-tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": true,
7 | "skipLibCheck": true,
8 | "esModuleInterop": true,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "jsx": "react-jsx",
17 | "declaration": true,
18 | "emitDeclarationOnly": true
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/concept.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: >-
3 | React Most Wanted uses a Layer based concept. Each layer has its own
4 | functionality and every layer above uses the features of the one below.
5 | ---
6 |
7 | # Concept
8 |
9 | React Most Wanted is based on **3 layers/shells**:
10 |
11 | * **base-shell** - The base for every RMW project. It includes the management of the \`Auth\` state, Internationalization state, the basic UI Layout, and the routing.
12 | * **mui-shell** - This layer includes Material-UI design into the base-shell with handy components like Page, a responsive Menu, and settings for language.
13 | * **rmw-shell** - This layer includes all the features from the previous ones and adds integration to Firebase by providing handy tools to kick start a new React project with the full power of Firebase.
14 |
15 | 
16 |
17 |
--------------------------------------------------------------------------------
/getting-started.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Each shell has its own package and template.
3 | ---
4 |
5 | # Getting started
6 |
7 | ## base-shell
8 |
9 | Creating a **shell** starter kit is a fairly straight forward process:
10 |
11 | ```
12 | npx create-react-app my-app --template base
13 | ```
14 |
15 | ## mui-shell
16 |
17 | ```text
18 | npx create-react-app my-app --template material-ui
19 | ```
20 |
21 | ## rmw-shell
22 |
23 | ```text
24 | npx create-react-app my-app --template rmw
25 | ```
26 |
27 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "node_modules/lerna/schemas/lerna-schema.json",
3 | "version": "independent",
4 | "command": {
5 | "publish": {
6 | "gitReset": false
7 | }
8 | },
9 | "packages": [
10 | "packages/base-shell",
11 | "packages/base-shell/create-base-shell",
12 | "packages/base-shell/create-base-shell/template",
13 | "packages/material-ui-shell",
14 | "packages/material-ui-shell/create-material-ui-shell",
15 | "packages/material-ui-shell/create-material-ui-shell/template",
16 | "packages/rmw-shell",
17 | "packages/rmw-shell/create-rmw-shell",
18 | "packages/rmw-shell/create-rmw-shell/template"
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "root",
3 | "private": true,
4 | "workspaces": [
5 | "packages/rmw-shell",
6 | "packages/material-ui-shell",
7 | "packages/base-shell"
8 | ],
9 | "devDependencies": {
10 | "lerna": "^8.1.8"
11 | },
12 | "optionalDependencies": {
13 | "@rollup/rollup-linux-x64-gnu": "*"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/base-shell/.gitignore:
--------------------------------------------------------------------------------
1 | /coverage
2 | /node_modules
3 | npm-debug.log*
4 | dist/
5 | stats.html
6 |
--------------------------------------------------------------------------------
/packages/base-shell/README.md:
--------------------------------------------------------------------------------
1 | # base-shell
2 |
3 | **[Base shell](./packages/base-shell/)**:
4 | the basic react setup: routing, internationalization and async load.
5 |
6 | `npx create-react-app my-app --template base`
7 |
8 | .
9 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@ecronix/create-base-shell",
3 | "version": "1.0.42",
4 | "description": "A template to create new projects based on @ecronix/base-shell",
5 | "bin": {
6 | "create-my-template": "index.js"
7 | },
8 | "main": "index.js",
9 | "devDependencies": {
10 | "base-shell-template": "^1.0.39"
11 | },
12 | "scripts": {
13 | "start": "node index.js"
14 | },
15 | "keywords": [
16 | "ecronix",
17 | "base-shell",
18 | "react-most-wanted"
19 | ],
20 | "author": "Abdallah",
21 | "license": "MIT"
22 | }
23 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 |
9 | # testing
10 | /coverage
11 |
12 | # production
13 | /build
14 |
15 | # misc
16 | .DS_Store
17 | .env.local
18 | .env.development.local
19 | .env.test.local
20 | .env.production.local
21 |
22 | npm-debug.log*
23 | yarn-debug.log*
24 | yarn-error.log*
25 | firebase-debug.log*
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/README.md:
--------------------------------------------------------------------------------
1 | This project was bootstrapped with `@ecronix/base-shell`
2 |
3 | ## Available Scripts
4 |
5 | In the project directory, you can run:
6 |
7 | ### `npm run dev`
8 |
9 | ### `npm run build`
10 |
11 | ### `npm run serve`
12 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "src"
4 | },
5 | "include": ["src"]
6 | }
7 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "base-shell-template",
3 | "version": "1.0.39",
4 | "description": "This project was bootstrapped with [@ecronix/base-shell](https://github.com/ecronix/react-most-wanted)",
5 | "private": "true",
6 | "type": "module",
7 | "scripts": {
8 | "dev": "vite",
9 | "build": "vite build",
10 | "serve": "vite preview"
11 | },
12 | "dependencies": {
13 | "@ecronix/base-shell": "^2.6.63"
14 | },
15 | "devDependencies": {
16 | "@vitejs/plugin-react": "^4",
17 | "vite": "^5"
18 | },
19 | "keywords": [],
20 | "author": "",
21 | "license": "ISC"
22 | }
23 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/base-shell/create-base-shell/template/public/favicon.ico
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/base-shell/create-base-shell/template/public/logo192.png
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/base-shell/create-base-shell/template/public/logo512.png
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/src/config/defaultRoutes.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | const getDefaultRoutes = (appConfig) => {
4 | const { pages } = appConfig || {}
5 | const { PageNotFound = () => Page not found
} = pages || {}
6 |
7 | return [{ path: '*', element: }]
8 | }
9 |
10 | export default getDefaultRoutes
11 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/src/config/index.js:
--------------------------------------------------------------------------------
1 | export { default } from "./config";
2 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/src/config/locales/de.js:
--------------------------------------------------------------------------------
1 | const messages = {
2 | sign_in: 'Anmelden',
3 | sign_out: 'Abmelden',
4 | username: 'Nutzername',
5 | password: 'Passwort',
6 | about: 'Über',
7 | home: 'Startseite',
8 | page_not_found: 'Seite nicht gefunden',
9 | settings: 'Einstellungen',
10 | language: 'Sprache',
11 | en: 'Englisch',
12 | de: 'Deutsch',
13 | ru: 'Russisch',
14 | }
15 |
16 | export default messages
17 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/src/config/locales/en.js:
--------------------------------------------------------------------------------
1 | const messages = {
2 | sign_in: 'Sign in',
3 | sign_out: 'Sign out',
4 | username: 'Username',
5 | password: 'Password',
6 | about: 'About',
7 | home: 'Home',
8 | page_not_found: 'Page not found',
9 | settings: 'Settings',
10 | language: 'Language',
11 | en: 'English',
12 | de: 'German',
13 | ru: 'Russian',
14 | }
15 |
16 | export default messages
17 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/src/config/locales/index.js:
--------------------------------------------------------------------------------
1 | const locales = [
2 | {
3 | locale: 'en',
4 | messages: import('./en'),
5 | },
6 | {
7 | locale: 'ru',
8 | messages: import('./ru'),
9 | },
10 | {
11 | locale: 'de',
12 | messages: import('./de'),
13 | },
14 | ]
15 |
16 | export default locales
17 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/src/config/locales/ru.js:
--------------------------------------------------------------------------------
1 | const messages = {
2 | sign_in: 'Вход',
3 | sign_out: 'Выход',
4 | username: 'Имя пользователя',
5 | password: 'Пароль',
6 | about: 'О нас',
7 | home: 'Главная',
8 | page_not_found: 'Страница не найдена',
9 | settings: 'Настройки',
10 | language: 'Язык',
11 | en: 'English',
12 | de: 'Deutsch',
13 | ru: 'Русский',
14 | }
15 |
16 | export default messages
17 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/src/config/routes.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { AuthorizedRoute, UnauthorizedRoute } from "@ecronix/base-shell";
3 | import { SignInPage } from "../pages/SignIn";
4 | import { HomePage } from "../pages/Home";
5 | import { AboutPage } from "../pages/About";
6 |
7 | const routes = [
8 | {
9 | path: "/signin",
10 | exact: true,
11 | element: (
12 |
13 |
14 |
15 | ),
16 | },
17 | { path: "/about", exact: true, element: },
18 | {
19 | path: "/home",
20 | exact: true,
21 | element: (
22 |
23 |
24 |
25 | ),
26 | },
27 | ];
28 |
29 | export default routes;
30 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/src/demo-index.jsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from "react";
2 | import { createRoot } from "react-dom/client";
3 | import { AppContainer } from "@ecronix/base-shell";
4 | import config from "./config";
5 |
6 | createRoot(document.getElementById("root")).render(
7 |
8 |
9 | ,
10 | );
11 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/src/pages/About/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useIntl } from "react-intl";
3 |
4 | export const AboutPage = () => {
5 | const intl = useIntl();
6 | return {intl.formatMessage({ id: "about" })}
;
7 | };
8 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/src/pages/Home/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useIntl } from "react-intl";
3 | import { useSimpleValues, useOnline } from "@ecronix/base-shell";
4 |
5 | export const HomePage = () => {
6 | const intl = useIntl();
7 | const isOnline = useOnline();
8 | const { setValue, getValue, clearAll } = useSimpleValues();
9 |
10 | const simpleNValueKey = "nkey";
11 | const simplePValueKey = "pKey";
12 |
13 | return (
14 |
15 | Non persistent: {getValue(simpleNValueKey, "empty")}
16 |
17 |
18 | Persistent: {getValue(simplePValueKey, "empty")}
19 |
20 | {isOnline ? "online" : "offline"}
21 |
22 |
23 |
30 |
31 |
32 |
39 |
40 |
41 |
51 |
52 | {intl.formatMessage({ id: "home" })}
53 |
54 |
55 | );
56 | };
57 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/src/pages/LandingPage/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Link } from "react-router-dom";
3 |
4 | export const LandingPage = () => {
5 | return (
6 |
7 | Landing Page
8 |
9 | Home
10 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/src/pages/PageNotFound/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useIntl } from "react-intl";
3 |
4 | export const PageNotFound = () => {
5 | const intl = useIntl();
6 | return {intl.formatMessage({ id: "page_not_found" })}
;
7 | };
8 |
--------------------------------------------------------------------------------
/packages/base-shell/create-base-shell/template/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import react from "@vitejs/plugin-react";
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/packages/base-shell/cypress.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "cypress";
2 |
3 | export default defineConfig({
4 | e2e: {
5 | setupNodeEvents(on, config) {
6 | // implement node event listeners here
7 | },
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/packages/base-shell/cypress/e2e/spec.cy.js:
--------------------------------------------------------------------------------
1 | describe("My React App", () => {
2 | beforeEach(() => {
3 | cy.visit("http://localhost:5173");
4 | });
5 |
6 | it("renders the app", () => {
7 | cy.get("#root").should("exist");
8 | });
9 |
10 | it('renders "app container top" text', () => {
11 | cy.contains("App Container top").should("exist");
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/packages/base-shell/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
6 |
--------------------------------------------------------------------------------
/packages/base-shell/cypress/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add('login', (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This will overwrite an existing command --
25 | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
--------------------------------------------------------------------------------
/packages/base-shell/cypress/support/e2e.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/e2e.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
--------------------------------------------------------------------------------
/packages/base-shell/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/base-shell/src/components/index.ts:
--------------------------------------------------------------------------------
1 | export { AuthorizedRoute } from "./AuthorizedRoute";
2 | export { UnauthorizedRoute } from "./UnauthorizedRoute";
3 |
--------------------------------------------------------------------------------
/packages/base-shell/src/containers/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./Layout";
2 | export * from "./App";
3 |
--------------------------------------------------------------------------------
/packages/base-shell/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./components";
2 | export * from "./containers";
3 | export * from "./utils";
4 | export * from "./providers";
5 |
6 | declare global {
7 | interface Window {
8 | update?: () => void;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/AddToHomeScreen/Context.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { AddToHomeScreenStateProps } from "./Provider";
3 | export interface AddToHomeScreenContextType {
4 | deferredPrompt?: Event | undefined;
5 | isAppInstallable?: boolean;
6 | isAppInstalled?: boolean;
7 |
8 | /**
9 | * @description Updates addToHomeScreenContext with provided data
10 | * @param {AddToHomeScreenStateProps}
11 | */
12 | setA2HPState: React.Dispatch>;
13 | }
14 |
15 | const Context = React.createContext(
16 | undefined
17 | );
18 |
19 | export default Context;
20 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/AddToHomeScreen/Provider.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import Context from "./Context";
3 |
4 | const initialState: AddToHomeScreenStateProps = {
5 | deferredPrompt: undefined,
6 | isAppInstallable: false,
7 | isAppInstalled: false,
8 | };
9 |
10 | export type AddToHomeScreenStateProps = {
11 | deferredPrompt?: Event | undefined;
12 | isAppInstallable?: boolean;
13 | isAppInstalled?: boolean;
14 | };
15 |
16 | const Provider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
17 | const [state, setA2HPState] =
18 | useState(initialState);
19 |
20 | window.addEventListener("beforeinstallprompt", (e) => {
21 | // Prevent Chrome 67 and earlier from automatically showing the prompt
22 | e.preventDefault();
23 | // Stash the event so it can be triggered later.
24 | setA2HPState({ deferredPrompt: e, isAppInstallable: true });
25 | });
26 |
27 | window.addEventListener("appinstalled", (evt) => {
28 | setA2HPState({ isAppInstalled: true });
29 | });
30 |
31 | return (
32 |
33 | {children}
34 |
35 | );
36 | };
37 |
38 | export default Provider;
39 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/AddToHomeScreen/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import Context, { AddToHomeScreenContextType } from "./Context";
3 | import Provider from "./Provider";
4 |
5 | /**
6 | * Custom hook for addToHomeScreenContext
7 | *
8 | * @function
9 | * @returns {AddToHomeScreenContext} The locale context value.
10 | * @throws {Error} If used outside of AddToHomeScreenProvider
11 | * @example
12 | * const a2HSContext = useAddToHomeScreen();
13 | *
14 | * @description
15 | * This hook provides access to AddToHomeScreenContext.
16 | *
17 | * @see {@link AddToHomeScreenContextType} for the shape of the returned context
18 | */
19 | function useAddToHomeScreen(): AddToHomeScreenContextType {
20 | const context = useContext(Context);
21 | if (!context) {
22 | throw new Error(
23 | "useAddToHomeScreen must be used within a AddToHomeScreenProvider"
24 | );
25 | }
26 | return context;
27 | }
28 |
29 | export {
30 | useAddToHomeScreen,
31 | Context as AddToHomeScreenContext,
32 | Provider as AddToHomeScreenProvider,
33 | };
34 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/Auth/Context.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export type ProviderData = { providerId: string };
4 | export type AuthUser = {
5 | isAuthenticated: boolean;
6 | photoURL: string;
7 | displayName: string;
8 | email: string;
9 | uid: string;
10 | isAdmin?: boolean;
11 | providerData?: ProviderData[];
12 | notificationsDisabled?: boolean;
13 | grants?: string[];
14 | };
15 |
16 | // TODO Fix isAuthGranted import everywhere
17 | export interface IAuthContext {
18 | /**
19 | * @description Authorized user object
20 | */
21 | auth: AuthUser;
22 |
23 | /**
24 | * @description Set auth to provided auth parameter
25 | * @param auth
26 | */
27 | setAuth: (auth: any) => void;
28 |
29 | /**
30 | * @description Update auth to provided auth parameter
31 | * @param auth
32 | */
33 | updateAuth: (auth: any) => void;
34 |
35 | isAuthGranted?: (auth: AuthUser, type: string) => boolean;
36 | }
37 |
38 | const ConfigContext = React.createContext(undefined);
39 |
40 | export default ConfigContext;
41 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/Auth/Provider.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useReducer } from "react";
2 | import Context from "./Context";
3 |
4 | type ReducerAction = {
5 | type: string;
6 | auth: any;
7 | };
8 |
9 | function reducer(state: any, action: ReducerAction) {
10 | const { type, auth } = action;
11 | switch (type) {
12 | case "SET_AUTH":
13 | return auth;
14 | case "UPDATE_AUTH":
15 | return { ...state, ...auth };
16 | default:
17 | throw new Error();
18 | }
19 | }
20 |
21 | const Provider: React.FC<{
22 | children: React.ReactNode;
23 | persistKey: string;
24 | }> = ({ persistKey = "auth", children }) => {
25 | const persistAuth = JSON.parse(
26 | localStorage.getItem(persistKey)?.replace("undefined", "{}") || "{}"
27 | );
28 |
29 | const [auth, dispatch] = useReducer(reducer, persistAuth || {});
30 |
31 | useEffect(() => {
32 | try {
33 | localStorage.setItem(persistKey, JSON.stringify(auth));
34 | } catch (error) {
35 | console.warn(error);
36 | }
37 | }, [auth, persistKey]);
38 |
39 | const setAuth = (auth: any) => {
40 | dispatch({ type: "SET_AUTH", auth });
41 | };
42 |
43 | const updateAuth = (auth: any) => {
44 | dispatch({ type: "UPDATE_AUTH", auth });
45 | };
46 |
47 | return (
48 |
49 | {children}
50 |
51 | );
52 | };
53 |
54 | export default Provider;
55 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/Auth/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from "react";
2 | import Context, { IAuthContext } from "./Context";
3 | import Provider from "./Provider";
4 | /**
5 | * Custom hook to access the authentication context.
6 | *
7 | * @function
8 | * @returns {IAuthContext} The authentication context value.
9 | * @throws {Error} If used outside of an AuthProvider.
10 | * @example
11 | * const auth = useAuth();
12 | * console.log(auth.isAuthenticated);
13 | *
14 | * @description
15 | * This hook provides access to the authentication context, which includes
16 | * information about the current user's authentication state and related
17 | * functions. It must be used within a component that is wrapped by an
18 | * AuthProvider.
19 | *
20 | * The IAuthContext typically includes properties such as:
21 | * - isAuthenticated: A boolean indicating if the user is authenticated
22 | * - user: The current user object (if authenticated)
23 | * - login: A function to log in the user
24 | * - logout: A function to log out the user
25 | *
26 | * @see {@link IAuthContext} for the shape of the returned context
27 | */
28 | function useAuth(): IAuthContext {
29 | const context = useContext(Context);
30 |
31 | if (context === undefined) {
32 | throw new Error("useAuth must be used within a AuthProvider");
33 | }
34 |
35 | return context;
36 | }
37 |
38 | export { useAuth, Context as AuthContext, Provider as AuthProvider };
39 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/Config/Context.tsx:
--------------------------------------------------------------------------------
1 | import { AppConfig } from "@ecronix/base-shell";
2 | import React from "react";
3 |
4 | export interface ConfigContextType {
5 | /**
6 | * @description App configuration
7 | */
8 | appConfig: AppConfig;
9 | }
10 |
11 | const ConfigContext = React.createContext(
12 | undefined
13 | );
14 |
15 | export default ConfigContext;
16 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/Config/Provider.tsx:
--------------------------------------------------------------------------------
1 | import React, { ReactNode } from "react";
2 | import Context from "./Context";
3 | import { AppConfig } from "@ecronix/base-shell";
4 |
5 | interface ProviderProps {
6 | appConfig: AppConfig;
7 | children: ReactNode;
8 | }
9 |
10 | const Provider: React.FC = ({ appConfig, children }) => {
11 | return {children};
12 | };
13 |
14 | export default Provider;
15 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/Config/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from "react";
2 | import Context, { ConfigContextType } from "./Context";
3 | import Provider from "./Provider";
4 |
5 | /**
6 | * Custom hook to access the config provider
7 | *
8 | * @function
9 | * @returns {ConfigContextType} The configuration context.
10 | * @throws {Error} If used outside of an ConfigProvider.
11 | * @example
12 | * const { appConfig } = useConfig();
13 | *
14 | * @description
15 | * This hook provides access to the configuration context. It provides json object containing all configuration data
16 | * and must be used withing ConfigProvider
17 | *
18 | * @see {@link ConfigContextType} for the shape of the returned context
19 | */
20 | function useConfig(): ConfigContextType {
21 | const context = useContext(Context);
22 |
23 | if (context === undefined) {
24 | throw new Error("useConfig must be used within a ConfigProvider");
25 | }
26 |
27 | return context;
28 | }
29 |
30 | export { useConfig, Context as ConfigContext, Provider as ConfigProvider };
31 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/Locale/Context.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export interface LocaleContextType {
4 | /**
5 | * Current locale settings - defaults to 'en'
6 | * @type {string}
7 | */
8 | locale: string;
9 |
10 | /**
11 | * Method to update locale settings
12 | * @param {string} locale - New provided locale string
13 | */
14 | setLocale: React.Dispatch>;
15 | }
16 |
17 | const Context = React.createContext(undefined);
18 |
19 | export default Context;
20 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/Locale/Provider.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import Context from "./Context";
3 |
4 | export interface LocaleProviderProps {
5 | children: React.ReactNode;
6 | defaultLocale?: string;
7 | persistKey?: string;
8 | }
9 |
10 | const Provider: React.FC = ({
11 | children,
12 | defaultLocale = "en",
13 | persistKey = "locale",
14 | }) => {
15 | const persistLocale = localStorage.getItem(persistKey);
16 | const [locale, setLocale] = useState(persistLocale || defaultLocale);
17 |
18 | useEffect(() => {
19 | try {
20 | localStorage.setItem(persistKey, locale);
21 | } catch (error) {
22 | console.warn(error);
23 | }
24 | }, [locale, persistKey]);
25 |
26 | return (
27 |
28 | {children}
29 |
30 | );
31 | };
32 |
33 | export default Provider;
34 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/Locale/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import Context, { LocaleContextType } from "./Context";
3 | import Provider from "./Provider";
4 |
5 | /**
6 | * Custom hook for accessing locale context
7 | *
8 | * @function
9 | * @returns {LocaleContextType} The locale context value.
10 | * @throws {Error} If used outside of LocaleContext
11 | * @example
12 | * const { setLocale, locale = "en" } = useLocale();
13 | *
14 | * @description
15 | * This hook provides access localization context. It provides locale value and method to update locale value.
16 | *
17 | * @see {@link LocaleProvider} for providing localization context
18 | * @see {@link LocaleContextType} for the shape of the returned context
19 | */
20 | function useLocale(): LocaleContextType {
21 | const context = useContext(Context);
22 | if (!context) {
23 | throw new Error("useLocale must be used within a LocaleProvider");
24 | }
25 | return context;
26 | }
27 |
28 | export { useLocale, Context as LocaleContext, Provider as LocaleProvider };
29 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/Online/Context.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const Context = React.createContext(undefined);
4 |
5 | export default Context;
6 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/Online/Provider.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import Context from "./Context";
3 |
4 | export interface OnlineProviderProps {
5 | children: React.ReactNode;
6 | }
7 |
8 | const Provider: React.FC = ({ children }) => {
9 | const [isOnline, setOnline] = useState(navigator.onLine);
10 |
11 | window.addEventListener("online", () => setOnline(true));
12 | window.addEventListener("offline", () => setOnline(false));
13 |
14 | return {children};
15 | };
16 |
17 | export default Provider;
18 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/Online/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import Context from "./Context";
3 | import Provider from "./Provider";
4 |
5 | /**
6 | * Custom hook to access the online listener provider.
7 | *
8 | * @function
9 | * @returns {boolean} Boolean value regarding if client is online or offline
10 | * @throws {Error} If used outside of an OnlineProvider.
11 | * @example
12 | * const isOnline = useOnline();
13 | *
14 | * @description
15 | * This hook provides access to the online listener context. It returns true if client is online.
16 | */
17 | function useOnline(): boolean {
18 | const context = useContext(Context);
19 | if (!context) {
20 | throw new Error("useOnline must be used within a OnlineProvider");
21 | }
22 | return context;
23 | }
24 |
25 | export { useOnline, Context as OnlineContext, Provider as OnlineProvider };
26 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/SimpleValues/Context.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export interface SimpleValuesContextType {
4 | /**
5 | * Sets a value in the context.
6 | * @param params - The parameters to set a value.
7 | * @param params.key - The key to identify the value.
8 | * @param params.value - The value to set.
9 | * @param boolean params.persist - Whether to persist the value (e.g., in local storage). Defaults to 'false'.
10 | */
11 | setValue: (key: string, value: any, persist?: boolean) => void;
12 |
13 | /**
14 | * Gets a value from the context by key.
15 | * @param key - The key to retrieve the value for.
16 | * @returns The value corresponding to the key.
17 | */
18 | getValue: (key: string, defaultValue?: any) => string;
19 |
20 | /**
21 | * Clears a value from the context by key.
22 | * @param key - The key to clear the value for.
23 | */
24 | clearValue: (key: string) => void;
25 |
26 | /**
27 | * Clears all values from the context.
28 | */
29 | clearAll: () => void;
30 | }
31 |
32 | const Context = React.createContext(
33 | undefined
34 | );
35 |
36 | export default Context;
37 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/SimpleValues/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import Context, { SimpleValuesContextType } from "./Context";
3 | import Provider from "./Provider";
4 | /**
5 | * Custom hook to access the simple values context.
6 | *
7 | * @function
8 | * @returns {SimpleValuesContextType} The simple values context value.
9 | * @throws {Error} If used outside of an SimpleValuesProvider.
10 | * @example
11 | * const { setValue, getValue, clearAll, clearValue } = useSimpleValues();
12 | *
13 | * @description
14 | * This hook provides access to the simple values context. It must be used inside SimpleValuesProvider.
15 | * It provides set of methods for manipulating values.
16 | * It provides following methods
17 | * - setValue
18 | * - getValue
19 | * - clearAll
20 | * - clearValue
21 | *
22 | * @see {@link SimpleValuesContextType} for the shape of the returned context
23 | */
24 | function useSimpleValues(): SimpleValuesContextType {
25 | const context = useContext(Context);
26 | if (!context) {
27 | throw new Error(
28 | "useSimpleValues must be used within a SimpleValuesProvider"
29 | );
30 | }
31 | return context;
32 | }
33 |
34 | export {
35 | useSimpleValues,
36 | Context as SimpleValuesContext,
37 | Provider as SimpleValuesProvider,
38 | };
39 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/Update/Context.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export interface UpdateContextType {
4 | /**
5 | * @description Value indicating if update is available or not
6 | */
7 | isUpdateAvailable: boolean;
8 |
9 | /**
10 | * @description Method for updating window
11 | * @param registration
12 | */
13 | runUpdate: (registration: any) => void;
14 | }
15 |
16 | const Context = React.createContext(undefined);
17 |
18 | export default Context;
19 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/Update/Provider.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import Context from "./Context";
3 |
4 | const runUpdate = (registration: any) => {
5 | try {
6 | if (registration) {
7 | registration.waiting.postMessage({ type: "SKIP_WAITING" });
8 | }
9 | if (window.update) {
10 | window.update && window.update();
11 | }
12 | } catch (error) {
13 | console.log(error);
14 | }
15 | };
16 |
17 | const Provider: React.FC<{
18 | children: React.ReactNode;
19 | checkInterval: number;
20 | }> = ({ children, checkInterval }) => {
21 | const [isUpdateAvailable, setUpdateAvailable] = useState(false);
22 |
23 | const checkUpdate = () => {
24 | if (window.update) {
25 | setUpdateAvailable(true);
26 | } else {
27 | setUpdateAvailable(false);
28 | setTimeout(checkUpdate, checkInterval);
29 | }
30 | };
31 |
32 | useEffect(checkUpdate, [checkUpdate]);
33 |
34 | return (
35 |
36 | {children}
37 |
38 | );
39 | };
40 |
41 | export default Provider;
42 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/Update/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import Context, { UpdateContextType } from "./Context";
3 | import Provider from "./Provider";
4 |
5 | /**
6 | * Custom hook to access the update context.
7 | *
8 | * @function
9 | * @returns {UpdateContextType} The update context value.
10 | * @throws {Error} If used outside of an UpdateProvider.
11 | *
12 | * @description
13 | * This hook provides access to the update context. It must be used within UpdateProvider.
14 | *
15 | *
16 | * @see {@link UpdateContextType} for the shape of the returned context
17 | */
18 | function useUpdate(): UpdateContextType {
19 | const context = useContext(Context);
20 | if (!context) {
21 | throw new Error("useUpdate must be used within a UpdateProvider");
22 | }
23 | return context;
24 | }
25 |
26 | export { useUpdate, Context as UpdateContext, Provider as UpdateProvider };
27 |
--------------------------------------------------------------------------------
/packages/base-shell/src/providers/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./Update";
2 | export * from "./SimpleValues";
3 | export * from "./Online";
4 | export * from "./Locale";
5 | export * from "./Config";
6 | export * from "./Auth";
7 | export * from "./AddToHomeScreen";
8 |
--------------------------------------------------------------------------------
/packages/base-shell/src/utils/config.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @function
3 | * @description Method for merging two different objects. It accepts 2 objects and returns new object.
4 | * @param {Record} obj1 First object
5 | * @param {Record} obj2 Second object
6 | * @returns New object created from merging provided objects
7 | */
8 | export const merge = (obj1: Record, obj2: Record) => {
9 | let temp = { ...obj1, ...obj2 };
10 |
11 | Object.keys(temp).forEach((key) => {
12 | if (typeof temp[key] === "object" && !(temp[key] instanceof Array)) {
13 | temp[key] = { ...obj1[key], ...obj2[key] };
14 | }
15 | });
16 |
17 | return temp;
18 | };
19 |
--------------------------------------------------------------------------------
/packages/base-shell/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export { merge } from "./config";
2 | export * from "./locale";
3 |
--------------------------------------------------------------------------------
/packages/base-shell/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../base-tsconfig.json",
3 | "compilerOptions": {
4 | "paths": {
5 | "@ecronix/base-shell": ["./src"],
6 | "@ecronix/base-shell/*": ["./src/*"]
7 | },
8 | "declarationDir": "./dist/types",
9 | },
10 | "include": ["src/**/*"],
11 | "exclude": ["node_modules"]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/base-shell/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import path from "node:path";
4 | import { visualizer } from "rollup-plugin-visualizer";
5 | import { externalizeDeps } from "vite-plugin-externalize-deps";
6 |
7 | // https://vitejs.dev/config/
8 | export default defineConfig({
9 | plugins: [react(), visualizer(), externalizeDeps()],
10 | resolve: {
11 | alias: {
12 | "@ecronix/base-shell": path.resolve(__dirname, "./src"),
13 | },
14 | extensions: [".js", ".ts", ".jsx", ".tsx"],
15 | },
16 | build: {
17 | minify: false,
18 | lib: {
19 | entry: path.resolve(__dirname, "./src/index.ts"),
20 | name: "base-shell",
21 | formats: ["es"],
22 | },
23 | },
24 | });
25 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/.gitignore:
--------------------------------------------------------------------------------
1 | /coverage
2 | /demo/dist
3 | /es
4 | /lib
5 | /node_modules
6 | /umd
7 | npm-debug.log*
8 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 |
3 | language: node_js
4 | node_js:
5 | - 8
6 |
7 | before_install:
8 | - npm install codecov.io coveralls
9 |
10 | after_success:
11 | - cat ./coverage/lcov.info | ./node_modules/codecov.io/bin/codecov.io.js
12 | - cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
13 |
14 | branches:
15 | only:
16 | - master
17 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "type": "pwa-chrome",
9 | "request": "launch",
10 | "name": "Launch Chrome against localhost",
11 | "url": "http://localhost:3000",
12 | "webRoot": "${workspaceFolder}"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/packages/bootstrap-shell/README.md:
--------------------------------------------------------------------------------
1 | # material-ui-shell
2 |
3 | [![Travis][build-badge]][build]
4 | [![npm package][npm-badge]][npm]
5 | [![Coveralls][coveralls-badge]][coveralls]
6 |
7 | Describe material-ui-shell here.
8 |
9 | [build-badge]: https://img.shields.io/travis/user/repo/master.png?style=flat-square
10 | [build]: https://travis-ci.org/user/repo
11 |
12 | [npm-badge]: https://img.shields.io/npm/v/npm-package.png?style=flat-square
13 | [npm]: https://www.npmjs.org/package/npm-package
14 |
15 | [coveralls-badge]: https://img.shields.io/coveralls/user/repo/master.png?style=flat-square
16 | [coveralls]: https://coveralls.io/github/user/repo
17 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/README.md:
--------------------------------------------------------------------------------
1 | # cra-template-base-shell
2 |
3 | This is the base-shell template for [Create React App](https://github.com/facebook/create-react-app).
4 |
5 | Use it like this:
6 | `npx create-react-app base-shell-app --template cra-template-base`
7 |
8 | For more information, please refer to:
9 |
10 | - [Getting Started](https://create-react-app.dev/docs/getting-started) – How to create a new app.
11 | - [User Guide](https://create-react-app.dev) – How to develop apps bootstrapped with Create React App.
12 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cra-template-bs",
3 | "version": "0.1.1",
4 | "keywords": [
5 | "react",
6 | "create-react-app",
7 | "template",
8 | "bootstrap"
9 | ],
10 | "description": "The bootstrap template for Create React App.",
11 | "main": "template.json",
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/TarikHuber/react-most-wanted",
15 | "directory": "packages/base-shell/cra-template-material-ui"
16 | },
17 | "license": "MIT",
18 | "engines": {
19 | "node": ">=8"
20 | },
21 | "bugs": {
22 | "url": "https://github.com/TarikHuber/react-most-wanted/issues"
23 | },
24 | "files": [
25 | "template",
26 | "template.json"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template.json:
--------------------------------------------------------------------------------
1 | {
2 | "package": {
3 | "dependencies": {
4 | "jss": "10.x",
5 | "jss-rtl": "0.x",
6 | "@formatjs/intl-relativetimeformat": "8.x",
7 | "base-shell": "1.x",
8 | "material-ui-shell": "2.x",
9 | "github-markdown-css": "4.x",
10 | "intl": "1.x",
11 | "intl-locales-supported": "1.x",
12 | "notistack": "2.x",
13 | "react": "17.x",
14 | "react-custom-scrollbars": "4.x",
15 | "react-dom": "17.x",
16 | "react-easy-crop": "3.x",
17 | "react-intl": "5.x",
18 | "react-ios-pwa-prompt": "1.x",
19 | "react-markdown": "7.x",
20 | "react-router-dom": "5.x",
21 | "react-virtualized-auto-sizer": "1.x",
22 | "react-window": "1.x",
23 | "@mui/material": "5.x",
24 | "@emotion/react": "11.x",
25 | "@emotion/styled": "11.x",
26 | "@mui/icons-material": "5.x",
27 | "bootstrap": "5.x",
28 | "react-bootstrap": "2.x",
29 | "react-bootstrap-icons": "1.x"
30 | },
31 | "devDependencies": {
32 | "@babel/core": "7.x",
33 | "@types/react": "17.x",
34 | "typescript": "4.x"
35 | },
36 | "eslintConfig": {
37 | "extends": ["react-app", "react-app/jest"]
38 | }
39 | }
40 | }
41 |
42 |
43 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 |
9 | # testing
10 | /coverage
11 |
12 | # production
13 | /build
14 |
15 | # misc
16 | .DS_Store
17 | .env.local
18 | .env.development.local
19 | .env.test.local
20 | .env.production.local
21 |
22 | npm-debug.log*
23 | yarn-debug.log*
24 | yarn-error.log*
25 | firebase-debug.log*
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "src"
4 | },
5 | "include": ["src"]
6 | }
7 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/bootstrap-shell/cra-template-bs/template/public/favicon.ico
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/bootstrap-shell/cra-template-bs/template/public/logo192.png
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/bootstrap-shell/cra-template-bs/template/public/logo512.png
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import App from 'base-shell/lib'
3 | import _config from './config'
4 | export default class Demo extends Component {
5 | render() {
6 | return
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/components/Loading.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default function Loading() {
4 | return Loading
5 | }
6 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/components/Loading/Loading.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import * as BS from 'react-bootstrap'
3 |
4 | export default function CircularIndeterminate() {
5 | return (
6 |
18 |
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/components/Menu/MenuRight.js:
--------------------------------------------------------------------------------
1 |
2 | import React from 'react'
3 | import * as BS from "react-bootstrap"
4 | import { BsFacebook, BsInstagram, BsGithub } from "react-icons/bs";
5 |
6 | export default function MenuRight() {
7 | return (<>
8 | Hallo
9 |
10 |
11 |
12 | Download
13 | >
14 | )
15 | }
16 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/config/config.js:
--------------------------------------------------------------------------------
1 | import { lazy } from 'react'
2 | import routes from './routes'
3 | import parseLanguages from 'base-shell/lib/utils/locale'
4 | import locales from './locales'
5 | import React from 'react'
6 | import menuItems from './menuItems'
7 |
8 | const Loading = () => Loading...
9 |
10 | const config = {
11 | containers: {
12 | LayoutContainer: lazy(() =>
13 | import('bootstrap-shell/lib/containers/LayoutContainer/LayoutContainer')
14 | ),
15 | },
16 | components: {
17 | Loading,
18 | },
19 | auth: {
20 | signInURL: '/signin',
21 | },
22 | pwa: {
23 | useiOSPWAPrompt: true,
24 | iOSPWAPromptProps: {},
25 | },
26 | routes,
27 | locale: {
28 | locales,
29 | defaultLocale: parseLanguages(['en', 'de', 'ru'], 'en'),
30 | onError: (e) => {
31 | //console.warn(e)
32 | return
33 | },
34 | },
35 | menu: {
36 | width: 240,
37 | initialMobileMenuOpen: false,
38 | MenuRight: lazy(() => import('../components/Menu/MenuRight')),
39 | menuItems,
40 | },
41 | theme: {},
42 | pages: {
43 | // The LandingPage is completely separeted from the App and is not under the LayoutContainer
44 | LandingPage: lazy(() => import('../pages/LandingPage')),
45 | PageNotFound: lazy(() => import('../pages/PageNotFound/PageNotFound')),
46 | },
47 | }
48 |
49 | export default config
50 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/config/dark.scss:
--------------------------------------------------------------------------------
1 | $theme-colors: (
2 | 'info': tomato,
3 | 'danger': teal,
4 | );
5 |
6 | @import '~bootstrap/scss/bootstrap';
7 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/config/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './config.js'
2 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/config/locales/index.js:
--------------------------------------------------------------------------------
1 | const locales = [
2 | {
3 | locale: 'en',
4 | messages: import('./en'),
5 | //loadData: import(`@formatjs/intl-relativetimeformat/dist/locale-data/en`),
6 | },
7 | {
8 | locale: 'ru',
9 | messages: import('./ru'),
10 | //loadData: import(`@formatjs/intl-relativetimeformat/dist/locale-data/ru`),
11 | },
12 | {
13 | locale: 'de',
14 | messages: import('./de'),
15 | //loadData: import(`@formatjs/intl-relativetimeformat/dist/locale-data/de`),
16 | },
17 | ]
18 |
19 | export default locales
20 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/config/menuItems.js:
--------------------------------------------------------------------------------
1 | const menuItems = [
2 | /*
3 | {
4 | path: '/',
5 | displayName: 'Home',
6 | disabled: true,
7 | disabledMobile: false,
8 | },
9 | {
10 | path: '/',
11 | displayName: 'Dropdown with Link',
12 | disabled: true,
13 | disabledMobile: false,
14 | nested: [
15 |
16 | ]
17 | },
18 | */
19 | {
20 | displayName: 'Dropdown',
21 | disabled: false,
22 | nested: [
23 | {
24 | path: '/home',
25 | displayName: 'Home',
26 | disabled: false,
27 | },
28 | {
29 | displayName: 'Demo Pages',
30 | disabled: false,
31 | nested: [
32 | {
33 | path: '/dialog',
34 | displayName: 'Dialog Demo',
35 | disabled: false,
36 | },
37 | ]
38 | },
39 | ]
40 | }
41 | ]
42 |
43 | export default menuItems;
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/config/routes.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/jsx-key */
2 | import React, { lazy } from 'react'
3 | //import AuthorizedRoute from 'base-shell/lib/components/AuthorizedRoute'
4 | //import UnauthorizedRoute from 'base-shell/lib/components/UnauthorizedRoute'
5 |
6 | const Home = lazy(() => import('../pages/Home/Home'))
7 | const Dialog = lazy(() => import('../pages/DialogDemo'))
8 | const routes = [
9 | {
10 | path: '/home', // root path
11 | exact: true,
12 | element: ,
13 | },
14 | {
15 | path: '/dialog', // path /home2
16 | exact: true,
17 | element: ,
18 | },
19 | {
20 | path: '*', //Page not found
21 | exact: true,
22 | element: ,
23 | },
24 | ]
25 |
26 | export default routes
27 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/config/themes.js:
--------------------------------------------------------------------------------
1 | import red from '@mui/material/colors/red'
2 |
3 | const themes = [
4 | {
5 | id: 'default',
6 | },
7 | {
8 | id: 'dark',
9 | white: 'text-white',
10 | source: {
11 | bg: 'dark',
12 | bgColor: 'bg-dark',
13 | palette: {
14 | primary: white,
15 | secondary: white,
16 | error: red,
17 | },
18 | },
19 | },
20 | {
21 | id: 'custom',
22 | white: 'text-white',
23 | source: {
24 | bg: 'dark',
25 | bgColor: 'bg-dark',
26 | palette: {
27 | primary: white,
28 | secondary: white,
29 | error: red,
30 | },
31 | },
32 | },
33 | ]
34 |
35 | export default themes
36 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { render } from 'react-dom'
3 | import App from './App'
4 |
5 | render(, document.getElementById('root'))
6 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/pages/DialogDemo/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { useIntl } from 'react-intl'
3 | import Page from 'bootstrap-shell/lib/containers/Page/Page'
4 |
5 |
6 | const Dialog = () => {
7 | const intl = useIntl()
8 |
9 | return
13 | Dialog Demo
14 |
15 | }
16 |
17 | export default Dialog
18 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/pages/Home/Home.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Page from 'bootstrap-shell/lib/containers/Page/Page'
3 |
4 | export default function Home() {
5 |
6 | return (
7 | Hallo
8 | )
9 | }
10 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/pages/LandingPage/LandingPage.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link } from 'react-router-dom'
3 |
4 | const LandingPage = () => {
5 | return (
6 |
19 |
Cool Landing Page
20 |
21 |
22 | Home
23 |
24 |
25 | )
26 | }
27 | export default LandingPage
28 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/pages/LandingPage/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './LandingPage'
2 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/cra-template-bs/template/src/pages/PageNotFound/PageNotFound.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { useIntl } from 'react-intl'
3 |
4 | const PageNotFound = () => {
5 | const intl = useIntl()
6 |
7 | return (
8 |
9 | 404
10 |
11 | )
12 | }
13 |
14 | export default PageNotFound
15 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/demo/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { render } from 'react-dom'
3 | import App from '../../cra-template-bs/template/src/App'
4 |
5 | render(, document.querySelector('#demo'))
6 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/nwb.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | module.exports = {
4 | type: 'react-component',
5 | npm: {
6 | esModules: true,
7 | umd: false,
8 | },
9 | webpack: {
10 | extra: {
11 | devtool: 'inline-source-map',
12 | },
13 | aliases: {
14 | 'bootstrap-shell/lib': path.resolve('src'),
15 | },
16 | },
17 | }
18 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/components/Menu/MenuDropdown.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import * as BS from "react-bootstrap"
3 |
4 | export default function MenuDropdown({ navItem, className }) {
5 |
6 | return (
7 | navItem &&
8 |
9 | {navItem?.nested?.map(item => {
10 | return item.nested ?
11 | : {item.displayName}
12 |
13 | })}
14 |
15 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/components/Menu/MenuDropdownMobile.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import * as BS from "react-bootstrap"
3 | import { BsChevronDown } from "react-icons/bs"
4 |
5 | export default function MenuDropdownMobile({ navItem, className }) {
6 | const [menuOpen, setMenuOpen] = useState(false);
7 | return (
8 |
15 | setMenuOpen(!menuOpen)} className="text-secondary">{navItem.displayName}
18 | {navItem.nested?.map(menuItem => {
19 | return menuItem.nested ? :
20 |
21 | {menuItem.displayName}
22 |
23 | })}
24 |
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/components/Modal/index.js:
--------------------------------------------------------------------------------
1 | import { Modal } from 'react-bootstrap'
2 |
3 | import React from 'react'
4 |
5 | export default function index(props) {
6 | return (
7 |
8 |
9 | 1 Title {' '}
10 | {' '}
11 |
12 | here is the body
{' '}
13 | {' '}
14 |
15 | Issa footer
{' '}
16 | {' '}
17 |
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/containers/LayoutContainer/LayoutContainer.js:
--------------------------------------------------------------------------------
1 | import { useConfig } from 'base-shell/lib/providers/Config'
2 | import React from 'react'
3 | import MenuProvider from '../../providers/Menu/Provider'
4 | import '../../styles/custom-bootstrap.css';
5 |
6 | const LayoutContent = ({ children }) => {
7 | return (
8 |
14 | {children}
15 |
16 | )
17 | }
18 |
19 | export default function ({ children }) {
20 | const { appConfig } = useConfig()
21 | return (
22 |
23 |
24 |
25 | {children}
26 |
27 |
28 |
34 |
35 |
36 | )
37 | }
38 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/containers/Page/Page.js:
--------------------------------------------------------------------------------
1 | import React, { useContext } from 'react'
2 | import Menu from '../../components/Menu/Menu'
3 | import { useMenu } from '../../providers/Menu'
4 | import * as BS from "react-bootstrap"
5 |
6 | const Page = ({
7 | children,
8 | brand,
9 | contentStyle,
10 | }) => {
11 | let headerTitle = ''
12 |
13 | if (typeof brand === 'string' || brand instanceof String) {
14 | headerTitle = brand
15 | }
16 |
17 | return (
18 |
19 |
20 |
21 | {children}
22 |
23 |
24 | )
25 | }
26 |
27 | export default Page
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/index.js:
--------------------------------------------------------------------------------
1 | import config from './config'
2 |
3 | export default config
4 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Menu/Context.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export const Context = React.createContext(null)
4 |
5 | export default Context
6 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Menu/Provider.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useReducer } from 'react'
2 | import PropTypes from 'prop-types'
3 | import Context from './Context'
4 | import {
5 | setIsMobileMenuOpen
6 | } from './store/actions';
7 | import reducer from './store/reducer';
8 | import { SET_IS_MOBILE_MENU_OPEN } from './store/types';
9 |
10 | const Provider = ({ appConfig, children, persistKey = 'menu' }) => {
11 | const { menu } = appConfig || {};
12 | const { initialMobileMenuOpen } = menu;
13 | const savedState = JSON.parse(localStorage.getItem(persistKey))
14 | const [menuStore, dispatch] = useReducer(reducer, {
15 | isMobileMenuOpen: initialMobileMenuOpen,
16 | ...savedState,
17 | });
18 |
19 | const props = {
20 | DISPATCH_ACTION(value, newValue = null) {
21 | if (value === SET_IS_MOBILE_MENU_OPEN) {
22 | dispatch(setIsMobileMenuOpen(!menuStore.isMobileMenuOpen));
23 | }
24 | },
25 |
26 | // getters
27 | isMobileMenuOpen: menuStore.isMobileMenuOpen,
28 | }
29 |
30 | useEffect(() => {
31 | try {
32 | localStorage.setItem(persistKey, JSON.stringify(menuStore))
33 | } catch (error) {
34 | console.warn(error)
35 | }
36 | }, [menuStore, persistKey])
37 |
38 | return (
39 |
42 | {children}
43 |
44 | )
45 | }
46 |
47 | Provider.propTypes = {
48 | children: PropTypes.any,
49 | }
50 |
51 | export default Provider
52 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Menu/index.js:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react'
2 | import Context from './Context'
3 | export { default as withMenu } from './with.js'
4 | export { default } from './Provider.js'
5 |
6 | export function useMenu() {
7 | return useContext(Context)
8 | }
9 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Menu/store/actions.js:
--------------------------------------------------------------------------------
1 | import * as types from './types'
2 |
3 | export function setIsMobileMenuOpen(payload) {
4 | return {
5 | type: types.SET_IS_MOBILE_MENU_OPEN,
6 | payload: payload
7 | }
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Menu/store/reducer.js:
--------------------------------------------------------------------------------
1 | import * as types from './types'
2 |
3 | export default function reducer(state = {}, action) {
4 | const { type, payload } = action
5 | switch (type) {
6 | case types.SET_IS_MOBILE_MENU_OPEN:
7 | return { ...state, isMobileMenuOpen: payload }
8 | default:
9 | return state
10 | }
11 | }
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Menu/store/types.js:
--------------------------------------------------------------------------------
1 | export const SET_IS_MOBILE_MENU_OPEN = 'SET_IS_MOBILE_MENU_OPEN';
2 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Menu/with.js:
--------------------------------------------------------------------------------
1 | import Context from './Context'
2 | import React from 'react'
3 |
4 | const withContainer = (Component) => {
5 | const ChildComponent = (props) => {
6 | return (
7 |
8 | {(contextProps) => {
9 | return
10 | }}
11 |
12 | )
13 | }
14 |
15 | return ChildComponent
16 | }
17 |
18 | export default withContainer
19 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Modal/Context.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export const Context = React.createContext(null)
4 |
5 | export default Context
6 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Modal/Provider.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useReducer } from 'react'
2 | import PropTypes from 'prop-types'
3 | import Context from './Context'
4 | import {
5 | setIsMobileMenuOpen
6 | } from './store/actions';
7 | import reducer from './store/reducer';
8 | import { SET_IS_MOBILE_MENU_OPEN } from './store/types';
9 |
10 | const Provider = ({ appConfig, children, persistKey = 'menu' }) => {
11 | const { menu } = appConfig || {};
12 | const { initialMobileMenuOpen } = menu;
13 | const savedState = JSON.parse(localStorage.getItem(persistKey))
14 | const [menuStore, dispatch] = useReducer(reducer, {
15 | isMobileMenuOpen: initialMobileMenuOpen,
16 | ...savedState,
17 | });
18 |
19 | const props = {
20 | DISPATCH_ACTION(value, newValue = null) {
21 | if (value === SET_IS_MOBILE_MENU_OPEN) {
22 | dispatch(setIsMobileMenuOpen(!menuStore.isMobileMenuOpen));
23 | }
24 | },
25 |
26 | // getters
27 | isMobileMenuOpen: menuStore.isMobileMenuOpen,
28 | }
29 |
30 | useEffect(() => {
31 | try {
32 | localStorage.setItem(persistKey, JSON.stringify(menuStore))
33 | } catch (error) {
34 | console.warn(error)
35 | }
36 | }, [menuStore, persistKey])
37 |
38 | return (
39 |
42 | {children}
43 |
44 | )
45 | }
46 |
47 | Provider.propTypes = {
48 | children: PropTypes.any,
49 | }
50 |
51 | export default Provider
52 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Modal/index.js:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react'
2 | import Context from './Context'
3 | export { default as withMenu } from './with.js'
4 | export { default } from './Provider.js'
5 |
6 | export function useMenu() {
7 | return useContext(Context)
8 | }
9 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Modal/store/actions.js:
--------------------------------------------------------------------------------
1 | import * as types from './types'
2 |
3 | export function setIsMobileMenuOpen(payload) {
4 | return {
5 | type: types.SET_IS_MOBILE_MENU_OPEN,
6 | payload: payload
7 | }
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Modal/store/reducer.js:
--------------------------------------------------------------------------------
1 | import * as types from './types'
2 |
3 | export default function reducer(state = {}, action) {
4 | const { type, payload } = action
5 | switch (type) {
6 | case types.SET_IS_MOBILE_MENU_OPEN:
7 | return { ...state, isMobileMenuOpen: payload }
8 | default:
9 | return state
10 | }
11 | }
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Modal/store/types.js:
--------------------------------------------------------------------------------
1 | export const SET_IS_MOBILE_MENU_OPEN = 'SET_IS_MOBILE_MENU_OPEN';
2 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Modal/with.js:
--------------------------------------------------------------------------------
1 | import Context from './Context'
2 | import React from 'react'
3 |
4 | const withContainer = (Component) => {
5 | const ChildComponent = (props) => {
6 | return (
7 |
8 | {(contextProps) => {
9 | return
10 | }}
11 |
12 | )
13 | }
14 |
15 | return ChildComponent
16 | }
17 |
18 | export default withContainer
19 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Theme/Context.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export const Context = React.createContext(null)
4 |
5 | export default Context
6 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Theme/index.js:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react'
2 | import Context from './Context'
3 | export { default as withTheme } from './with.js'
4 | export { default } from './Provider.js'
5 |
6 | export function useTheme() {
7 | return useContext(Context)
8 | }
9 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/providers/Theme/with.js:
--------------------------------------------------------------------------------
1 | import Context from './Context'
2 | import React from 'react'
3 |
4 | const withContainer = (Component) => {
5 | const ChildComponent = (props) => {
6 | return (
7 |
8 | {(contextProps) => {
9 | return
10 | }}
11 |
12 | )
13 | }
14 |
15 | return ChildComponent
16 | }
17 |
18 | export default withContainer
19 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/styles/custom-bootstrap.css:
--------------------------------------------------------------------------------
1 | /*
2 | xs = Extra small <576px. Max container width None (auto)
3 | sm = Small ≥576px. Max container width 540px.
4 | md = Medium ≥768px. Max container width 720px.
5 | lg = Large ≥992px. Max container width 960px.
6 | xl = Extra large ≥1200px. Max container width 1140px.
7 | */
8 |
9 | :root {
10 | --bs-primary: white !important;
11 | --bs-primary-rgb: 52, 58, 64 !important;
12 | }
13 |
14 | .dropdown-menu {
15 | min-width: 12rem !important;
16 | }
17 |
18 | .dropdown-submenu {
19 | position: relative;
20 | }
21 |
22 | .dropdown-submenu .dropdown-menu[data-bs-popper] {
23 | right: 0;
24 | top: -3px;
25 | left: 99%;
26 | }
27 |
28 | .dropdown-toggle {
29 | padding: 0.25rem 1rem !important;
30 | }
31 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/src/utils/theme.js:
--------------------------------------------------------------------------------
1 | //import { createTheme } from '@mui/material/styles'
2 | import { createTheme } from '@mui/material/styles'
3 |
4 | const getThemeSource = (id, ts, isDarkMode, isRTL) => {
5 | if (ts) {
6 | for (let i = 0; i < ts.length; i++) {
7 | if (ts[i]['id'] === id) {
8 | const source = ts[i]['source']
9 | const palette = source != null ? source.palette : {}
10 | return createTheme({
11 | ...source,
12 | palette: { ...palette, mode: isDarkMode ? 'dark' : 'light' },
13 | direction: isRTL ? 'rtl' : 'ltr',
14 | })
15 | }
16 | }
17 | }
18 |
19 | return createTheme({
20 | palette: { mode: isDarkMode ? 'dark' : 'light' },
21 | direction: isRTL ? 'rtl' : 'ltr',
22 | })
23 | }
24 |
25 | export default getThemeSource
26 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/tests/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "mocha": true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/packages/bootstrap-shell/tests/index.test.js:
--------------------------------------------------------------------------------
1 | import expect from 'expect'
2 | import React from 'react'
3 | import {render, unmountComponentAtNode} from 'react-dom'
4 |
5 | import Component from 'src/'
6 |
7 | describe('Component', () => {
8 | let node
9 |
10 | beforeEach(() => {
11 | node = document.createElement('div')
12 | })
13 |
14 | afterEach(() => {
15 | unmountComponentAtNode(node)
16 | })
17 |
18 | it('displays a welcome message', () => {
19 | render(, node, () => {
20 | expect(node.innerHTML).toContain('Welcome to React components')
21 | })
22 | })
23 | })
24 |
--------------------------------------------------------------------------------
/packages/firebase-function-tools/.gitignore:
--------------------------------------------------------------------------------
1 | /coverage
2 | /demo/dist
3 | /es
4 | /lib
5 | /node_modules
6 | /umd
7 | npm-debug.log*
8 |
--------------------------------------------------------------------------------
/packages/firebase-function-tools/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 |
3 | language: node_js
4 | node_js:
5 | - 8
6 |
7 | before_install:
8 | - npm install codecov.io coveralls
9 |
10 | after_success:
11 | - cat ./coverage/lcov.info | ./node_modules/codecov.io/bin/codecov.io.js
12 | - cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
13 |
14 | branches:
15 | only:
16 | - master
17 |
--------------------------------------------------------------------------------
/packages/firebase-function-tools/README.md:
--------------------------------------------------------------------------------
1 | # firebase-function-tools
2 |
3 | Based on this [article](https://codeburst.io/organizing-your-firebase-cloud-functions-67dc17b3b0da)
4 |
--------------------------------------------------------------------------------
/packages/firebase-function-tools/nwb.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | type: 'react-component',
3 | npm: {
4 | esModules: false,
5 | umd: false,
6 | },
7 | }
8 |
--------------------------------------------------------------------------------
/packages/firebase-function-tools/src/counting.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | handleListChange: (data, context, counterName) => {
3 | if (data.after.exists() && data.before.exists()) {
4 | return null
5 | }
6 |
7 | const collectionRef = data.after.ref.parent
8 | const countRef = collectionRef.parent.child(counterName)
9 |
10 | // Return the promise from countRef.transaction() so our function
11 | // waits for this async event to complete before it exits.
12 | return countRef.transaction(current => {
13 | if (data.after.exists()) {
14 | return (current || 0) + 1
15 | } else {
16 | return (current || 0) - 1
17 | }
18 | })
19 | },
20 | handleRecount: (data, context, listName, correction = 0) => {
21 | if (!data.exists()) {
22 | const counterRef = data.ref
23 | const collectionRef = counterRef.parent.child(listName)
24 |
25 | // Return the promise from counterRef.set() so our function
26 | // waits for this async event to complete before it exits.
27 | return collectionRef
28 | .once('value')
29 | .then(messagesData =>
30 | counterRef.set(messagesData.numChildren() + correction)
31 | )
32 | }
33 | return null
34 | },
35 | }
36 |
--------------------------------------------------------------------------------
/packages/firebase-function-tools/src/customClaims.js:
--------------------------------------------------------------------------------
1 | import admin from 'firebase-admin'
2 |
3 | const setClaim = async (uid, name, value = true) => {
4 | const user = await admin.auth().getUser(uid)
5 |
6 | const { [name]: claimName, ...rest } = user.customClaims || {}
7 |
8 | await admin.auth().setCustomUserClaims(uid, { ...rest, [name]: value })
9 | }
10 |
11 | const removeClaim = async (uid, name) => {
12 | const user = await admin.auth().getUser(uid)
13 |
14 | const { [name]: claimName, ...rest } = user.customClaims || {}
15 |
16 | await admin.auth().setCustomUserClaims(uid, { ...rest })
17 | }
18 |
19 | export { setClaim, removeClaim }
20 |
--------------------------------------------------------------------------------
/packages/firebase-function-tools/src/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './load'
2 |
--------------------------------------------------------------------------------
/packages/firebase-function-tools/src/notifications.js:
--------------------------------------------------------------------------------
1 | const admin = require('firebase-admin')
2 |
3 | module.exports = {
4 | notifyUser: (userUid, payload, tokensBasePath = 'notification_tokens') => {
5 | console.log(userUid, payload)
6 |
7 | return admin
8 | .database()
9 | .ref(`/${tokensBasePath}/${userUid}`)
10 | .once('value')
11 | .then(snapshot => {
12 | let registrationTokens = []
13 |
14 | snapshot.forEach(token => {
15 | if (token.val()) {
16 | registrationTokens.push(token.key)
17 | }
18 | })
19 |
20 | if (registrationTokens.length) {
21 | return admin.messaging().sendToDevice(registrationTokens, payload)
22 | } else {
23 | console.log('Not tokens registered')
24 | return null
25 | }
26 | })
27 | },
28 | }
29 |
--------------------------------------------------------------------------------
/packages/firebase-function-tools/src/users.js:
--------------------------------------------------------------------------------
1 | const admin = require('firebase-admin')
2 |
3 | // Source: https://firebase.google.com/docs/auth/admin/manage-users
4 | const listAllUsers = (userIds = [], nextPageToken) => {
5 | // List batch of users, 1000 at a time.
6 | return admin
7 | .auth()
8 | .listUsers(1000, nextPageToken)
9 | .then(resp => {
10 | if (resp.pageToken) {
11 | // List next batch of users.
12 | return listAllUsers(userIds.concat(resp.users), resp.pageToken)
13 | }
14 | return userIds.concat(resp.users)
15 | })
16 | }
17 |
18 | module.exports = {
19 | listAllUsers: listAllUsers,
20 | }
21 |
--------------------------------------------------------------------------------
/packages/firebase-function-tools/tests/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "mocha": true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/packages/firebase-function-tools/tests/index-test.js:
--------------------------------------------------------------------------------
1 | import expect from 'expect'
2 | import React from 'react'
3 | import {render, unmountComponentAtNode} from 'react-dom'
4 |
5 | import Component from 'src/'
6 |
7 | describe('Component', () => {
8 | let node
9 |
10 | beforeEach(() => {
11 | node = document.createElement('div')
12 | })
13 |
14 | afterEach(() => {
15 | unmountComponentAtNode(node)
16 | })
17 |
18 | it('displays a welcome message', () => {
19 | render(, node, () => {
20 | expect(node.innerHTML).toContain('Welcome to React components')
21 | })
22 | })
23 | })
24 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/.gitignore:
--------------------------------------------------------------------------------
1 | /coverage
2 | /dist
3 | /node_modules
4 | npm-debug.log*
5 | stats.html
6 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/README.md:
--------------------------------------------------------------------------------
1 | # material-ui-shell
2 |
3 | [![Travis][build-badge]][build]
4 | [![npm package][npm-badge]][npm]
5 | [![Coveralls][coveralls-badge]][coveralls]
6 |
7 | Describe material-ui-shell here.
8 |
9 | [build-badge]: https://img.shields.io/travis/user/repo/master.png?style=flat-square
10 | [build]: https://travis-ci.org/user/repo
11 |
12 | [npm-badge]: https://img.shields.io/npm/v/npm-package.png?style=flat-square
13 | [npm]: https://www.npmjs.org/package/npm-package
14 |
15 | [coveralls-badge]: https://img.shields.io/coveralls/user/repo/master.png?style=flat-square
16 | [coveralls]: https://coveralls.io/github/user/repo
17 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@ecronix/create-material-ui-shell",
3 | "version": "1.0.38",
4 | "description": "A template to create new projects based on @ecronix/material-ui-shell",
5 | "bin": {
6 | "create-my-template": "index.js"
7 | },
8 | "main": "index.js",
9 | "devDependencies": {
10 | "material-ui-shell-template": "^1.0.41"
11 | },
12 | "scripts": {
13 | "start": "node index.js"
14 | },
15 | "keywords": [
16 | "ecronix",
17 | "material-ui-shell",
18 | "react-most-wanted"
19 | ],
20 | "author": "Abdallah",
21 | "license": "MIT"
22 | }
23 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 |
9 | # testing
10 | /coverage
11 |
12 | # production
13 | /build
14 |
15 | # misc
16 | .DS_Store
17 | .env.local
18 | .env.development.local
19 | .env.test.local
20 | .env.production.local
21 |
22 | npm-debug.log*
23 | yarn-debug.log*
24 | yarn-error.log*
25 | firebase-debug.log*
26 | dist
27 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "src"
4 | },
5 | "include": ["src"]
6 | }
7 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "material-ui-shell-template",
3 | "version": "1.0.41",
4 | "description": "This project was bootstrapped with [@ecronix/material-ui](https://github.com/ecronix/react-most-wanted)",
5 | "type": "module",
6 | "private": "true",
7 | "scripts": {
8 | "dev": "vite",
9 | "build": "vite build",
10 | "serve": "vite preview"
11 | },
12 | "dependencies": {
13 | "@ecronix/material-ui-shell": "^3.5.54"
14 | },
15 | "devDependencies": {
16 | "@vitejs/plugin-react": "^4",
17 | "vite": "^5"
18 | },
19 | "keywords": [],
20 | "author": "",
21 | "license": "ISC"
22 | }
23 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/material-ui-shell/create-material-ui-shell/template/public/favicon.ico
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/material-ui-shell/create-material-ui-shell/template/public/logo192.png
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/material-ui-shell/create-material-ui-shell/template/public/logo512.png
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Ecronix - React App",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/src/components/CustomPaper/index.jsx:
--------------------------------------------------------------------------------
1 | import Paper from '@mui/material/Paper'
2 | import { styled } from '@mui/material'
3 |
4 | const CustomPaper = styled(Paper)(({ theme }) => {
5 | return {
6 | width: 'auto',
7 | marginLeft: theme.spacing(8),
8 | marginRight: theme.spacing(8),
9 | [theme.breakpoints.up(620)]: {
10 | width: 400,
11 | marginLeft: 'auto',
12 | marginRight: 'auto',
13 | },
14 | marginTop: theme.spacing(8),
15 | display: 'flex',
16 | flexDirection: 'column',
17 | alignItems: 'center',
18 | padding: `18px 18px 18px`,
19 | }
20 | })
21 |
22 | export default CustomPaper
23 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/src/config/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './config'
2 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/src/config/locales/index.js:
--------------------------------------------------------------------------------
1 | const locales = [
2 | {
3 | locale: 'en',
4 | messages: import('./en'),
5 | //loadData: import(`@formatjs/intl-relativetimeformat/dist/locale-data/en`),
6 | },
7 | {
8 | locale: 'ru',
9 | messages: import('./ru'),
10 | //loadData: import(`@formatjs/intl-relativetimeformat/dist/locale-data/ru`),
11 | },
12 | {
13 | locale: 'de',
14 | messages: import('./de'),
15 | //loadData: import(`@formatjs/intl-relativetimeformat/dist/locale-data/de`),
16 | },
17 | ]
18 |
19 | export default locales
20 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/src/config/themes.js:
--------------------------------------------------------------------------------
1 | import red from '@mui/material/colors/red'
2 | import green from '@mui/material/colors/green'
3 | import pink from '@mui/material/colors/pink'
4 |
5 | const themes = [
6 | {
7 | id: 'default',
8 | },
9 | {
10 | id: 'red',
11 | color: red[500],
12 | source: {
13 | palette: {
14 | primary: red,
15 | secondary: pink,
16 | error: red,
17 | },
18 | },
19 | },
20 | {
21 | id: 'green',
22 | color: green[500],
23 | source: {
24 | palette: {
25 | primary: green,
26 | secondary: red,
27 | error: red,
28 | },
29 | },
30 | },
31 | ]
32 |
33 | export default themes
34 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/src/demo-index.jsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from 'react'
2 | import { createRoot } from 'react-dom/client'
3 | import { AppContainer } from '@ecronix/base-shell'
4 | import config from './config'
5 |
6 | createRoot(document.getElementById('root')).render(
7 |
8 |
9 |
10 | )
11 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/src/pages/About/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react'
2 | import { useIntl } from 'react-intl'
3 | import { Page, Scrollbar } from '@ecronix/material-ui-shell'
4 | import ReactMarkdown from 'react-markdown'
5 |
6 | export const AboutPage = () => {
7 | const [source, setSource] = useState(null)
8 | const intl = useIntl()
9 |
10 | const loadData = async () => {
11 | const data = await fetch(
12 | 'https://raw.githubusercontent.com/TarikHuber/react-most-wanted/master/README.md'
13 | )
14 | const text = await data.text()
15 | setSource(text)
16 | }
17 |
18 | useEffect(() => {
19 | loadData()
20 | }, [])
21 |
22 | return (
23 |
26 |
27 |
28 | {source && (
29 |
30 | )}
31 |
32 |
33 |
34 | )
35 | }
36 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/src/pages/Home/index.jsx:
--------------------------------------------------------------------------------
1 | import { Typography } from '@mui/material'
2 | import { Page } from '@ecronix/material-ui-shell'
3 | import React from 'react'
4 | import { useIntl } from 'react-intl'
5 |
6 | export const HomePage = () => {
7 | const intl = useIntl()
8 |
9 | return (
10 |
11 | {intl.formatMessage({ id: 'home' })}
12 |
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/src/pages/LandingPage/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link } from 'react-router-dom'
3 |
4 | export const LandingPage = () => {
5 | return (
6 |
19 |
Cool Landing Page
20 |
21 |
22 | Home
23 |
24 |
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/src/pages/PageNotFound/index.jsx:
--------------------------------------------------------------------------------
1 | import { Button, Paper, Typography } from '@mui/material'
2 | import { Home } from '@mui/icons-material'
3 | import { Page } from '@ecronix/material-ui-shell'
4 | import React from 'react'
5 | import { useIntl } from 'react-intl'
6 |
7 | export const PageNotFound = () => {
8 | const intl = useIntl()
9 |
10 | return (
11 |
12 | t.palette.background.default,
15 | margin: 0,
16 | height: `calc(100vh - 64px)`,
17 | }}
18 | >
19 |
28 | 404
29 |
30 | {intl.formatMessage({ id: 'page_not_found' }) + ' MUI'}
31 |
32 |
40 |
41 |
42 |
43 | )
44 | }
45 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/src/pages/TabsDemo/index.jsx:
--------------------------------------------------------------------------------
1 | import { AppBar, Tab, Tabs } from '@mui/material'
2 | import { Page } from '@ecronix/material-ui-shell'
3 | import React, { useState } from 'react'
4 | import { useIntl } from 'react-intl'
5 |
6 | export const TabsDemoPage = () => {
7 | const [tab, setTab] = useState('one')
8 | const intl = useIntl()
9 |
10 | return (
11 |
18 | setTab(t)}
21 | aria-label="simple tabs example"
22 | centered
23 | textColor="inherit"
24 | indicatorColor="secondary"
25 | >
26 |
27 |
28 |
29 |
30 |
31 | }
32 | >
33 |
34 | {tab === 'one' &&
One
}
35 | {tab === 'two' &&
Two
}
36 | {tab === 'three' &&
Three
}
37 |
38 |
39 | )
40 | }
41 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/src/pages/ToastDemo/index.jsx:
--------------------------------------------------------------------------------
1 | import { Button } from '@mui/material'
2 | import { Page } from '@ecronix/material-ui-shell'
3 | import React from 'react'
4 | import { useIntl } from 'react-intl'
5 | import { useSnackbar } from 'notistack'
6 |
7 | export const ToastDemoPage = () => {
8 | const intl = useIntl()
9 | const { enqueueSnackbar } = useSnackbar()
10 |
11 | return (
12 |
18 |
19 |
32 |
33 | )
34 | }
35 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/create-material-ui-shell/template/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/cypress.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "cypress";
2 |
3 | export default defineConfig({
4 | e2e: {
5 | setupNodeEvents(on, config) {
6 | // implement node event listeners here
7 | },
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/cypress/e2e/spec.cy.js:
--------------------------------------------------------------------------------
1 | describe('My React App', () => {
2 | beforeEach(() => {
3 | cy.visit('http://localhost:5173')
4 | })
5 |
6 | it('renders the app', () => {
7 | cy.get('#root').should('exist')
8 | })
9 |
10 | it('renders "app container top" text', () => {
11 | cy.contains('Cool Landing Page').should('exist')
12 | })
13 | })
14 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
6 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/cypress/screenshots/spec.cy.js/My React App -- renders app container top text (failed).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/material-ui-shell/cypress/screenshots/spec.cy.js/My React App -- renders app container top text (failed).png
--------------------------------------------------------------------------------
/packages/material-ui-shell/cypress/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add('login', (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This will overwrite an existing command --
25 | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
--------------------------------------------------------------------------------
/packages/material-ui-shell/cypress/support/e2e.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/e2e.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
--------------------------------------------------------------------------------
/packages/material-ui-shell/demo.jsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from 'react'
2 | import { createRoot } from 'react-dom/client'
3 | import App from './cra-template-material-ui/template/src/App'
4 |
5 | createRoot(document.getElementById('root')).render(
6 |
7 |
8 |
9 | )
10 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/components/Loading/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import CircularProgress from '@mui/material/CircularProgress'
3 |
4 | /**
5 | * @description Circular loading indicator.
6 | * @returns CircularProgress component with size of 50
7 | */
8 | export default function Loading(): JSX.Element {
9 | return (
10 |
22 |
23 |
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/components/index.ts:
--------------------------------------------------------------------------------
1 | // there are both named and default exports under /components,
2 | // default are used mainly when lazy loading is needed
3 | // named are used when we need to import multiple components conveniently
4 |
5 | export { default as FilterDrawer } from './FilterDrawer'
6 | export { default as Scrollbar } from './Scrollbar'
7 | export { default as MenuHeader } from './MenuHeader'
8 | export { default as QuestionDialog } from './QuestionDialog'
9 | export { default as SearchField } from './SearchField'
10 | export { default as Loading } from './Loading'
11 | export { default as UpdateDialog } from './UpdateDialog'
12 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/containers/Menu/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { ResponsiveMenuContainer } from '@ecronix/material-ui-shell'
3 | import { useConfig } from '@ecronix/base-shell'
4 |
5 | /**
6 | * React component rendering MenuHeader and MenuContent. It loads data from config using useConfig hook.
7 | * It renders MenuHeader and MenuContent component if they are provided in application configuration under
8 | * menu scetion. As main wrapper it sets BaseMenu component defined in app config under menu section
9 | *
10 | * If MenuContainer is not provided it uses ResponsiveMenuContainer from material-ui-shell
11 | *
12 | * @example
13 | * appConfig: {
14 | * components: {
15 | * Menu: MenuContainer
16 | * }
17 | * }
18 | * @see {ResponsiveMenuContainer} - for fallback component
19 | */
20 | export function MenuContainer() {
21 | const { appConfig } = useConfig()
22 | const { menu } = appConfig || {}
23 | const { MenuHeader, MenuContent, BaseMenu } = menu || {}
24 |
25 | const Menu = BaseMenu || ResponsiveMenuContainer
26 |
27 | return (
28 |
32 | )
33 | }
34 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/containers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './ImageUploadDialog'
2 | export * from './LayoutContainer'
3 | export * from './Menu'
4 | export * from './ResponsiveMenu'
5 | export * from './SelectableMenuList'
6 | export * from './UpdateContainer'
7 | export * from './VirtualList'
8 | export type { IPixelCrop } from './ImageUploadDialog/getCropImage'
9 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './components'
2 | export * from './containers'
3 | export * from './providers'
4 | export * from './utils'
5 | export * from './pages'
6 | export * from './common.type'
7 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/pages/LandingPage/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export function LandingPage() {
4 | return Landing Page MUI
5 | }
6 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/pages/PageNotFound/index.tsx:
--------------------------------------------------------------------------------
1 | import { Button, Paper, Typography } from '@mui/material'
2 | import { Home } from '@mui/icons-material'
3 | import { Page } from '@ecronix/material-ui-shell'
4 | import React from 'react'
5 | import { useIntl } from 'react-intl'
6 |
7 | /**
8 | * @description Renders not found page
9 | */
10 | export const NotFoundPage: React.FC = () => {
11 | const intl = useIntl()
12 |
13 | return (
14 |
15 | t.palette.background.default,
18 | margin: 0,
19 | height: `calc(100vh - 64px)`,
20 | }}
21 | >
22 |
31 | 404
32 |
33 | {intl.formatMessage({ id: 'page_not_found' }) + ' MUI'}
34 |
35 |
43 |
44 |
45 |
46 | )
47 | }
48 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/pages/index.ts:
--------------------------------------------------------------------------------
1 | export { Page } from './Page'
2 | export { NotFoundPage } from './PageNotFound'
3 | export { ListPage } from './ListPage'
4 | export { LandingPage } from './LandingPage'
5 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/Dialogs/Question/Context.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export interface DialogsContextType {
4 | /**
5 | * @description Open dialog - sets isOpen to true, and pass additional props
6 | * @param props
7 | */
8 | openDialog: (props: any) => void
9 |
10 | /**
11 | * @description Closes dialog - sets isOpen to false
12 | * @param name
13 | * @param offset
14 | */
15 | closeDialog: () => void
16 | /**
17 | * @description Set processing to true or false
18 | * @param isProcessing
19 | */
20 | setProcessing: (isProcessing: boolean) => void
21 | }
22 |
23 | export const Context = React.createContext(
24 | undefined
25 | )
26 |
27 | export default Context
28 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/Dialogs/Question/Provider.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, Fragment } from 'react'
2 | import Context from './Context'
3 | import QuestionDialog from '../../../components/QuestionDialog'
4 | import { IProviderProps } from '@ecronix/material-ui-shell/common.type'
5 |
6 | const Provider: React.FC = ({ children }) => {
7 | const [state, setState] = useState({ isOpen: false })
8 | const [isProcessing, setIsProcessing] = useState(false)
9 |
10 | const openDialog = (props: any) => {
11 | setState({ isOpen: true, ...props })
12 | }
13 |
14 | const closeDialog = () => {
15 | setState({ isOpen: false })
16 | }
17 |
18 | const setProcessing = (isProcessing: boolean) => {
19 | setIsProcessing(isProcessing)
20 | }
21 |
22 | return (
23 |
24 |
25 | {children}
26 |
31 |
32 |
33 | )
34 | }
35 |
36 | export default Provider
37 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/Dialogs/Question/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react'
2 | import Context, { DialogsContextType } from './Context'
3 | import Provider from './Provider'
4 |
5 | /**
6 | * Custom hook to access the question dialog context.
7 | *
8 | * @function
9 | * @returns {DialogsContextType} The theme context value.
10 | * @throws {Error} If used outside of an QuestionsDialogProvider.
11 | * @example
12 | * const { openDialog, closeDialog, setProcessing } = useQuestionsDialog();
13 | *
14 | * @description Gives you access to questions dialog. It must be used within QuestionsDialogProvider and it provides you
15 | * with methods for opening and closing dialog, as well as handling processing
16 | *
17 | */
18 | function useQuestionsDialog(): DialogsContextType {
19 | const context = useContext(Context)
20 | if (context === undefined) {
21 | throw new Error(
22 | 'useQuestionsDialog must be used within a QuestionsDialogProvider'
23 | )
24 | }
25 | return context
26 | }
27 |
28 | export {
29 | useQuestionsDialog,
30 | Context as QuestionsDialogContext,
31 | Provider as QuestionsDialogProvider,
32 | }
33 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/Filter/fields/index.ts:
--------------------------------------------------------------------------------
1 | import numberField from './number'
2 | import textField from './text'
3 | import boolField from './boolean'
4 | import dateField from './date'
5 | import timeField from './time'
6 |
7 | export { numberField, textField, boolField, dateField, timeField }
8 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/Filter/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react'
2 | import Context from './Context'
3 | import Provider from './Provider'
4 |
5 | function useFilter() {
6 | const context = useContext(Context)
7 |
8 | if (context === undefined) {
9 | throw new Error('useFilter must be used within a FilterProvider')
10 | }
11 | return context
12 | }
13 |
14 | export { useFilter, Context as FilterContext, Provider as FilterProvider }
15 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/Filter/store/types.tsx:
--------------------------------------------------------------------------------
1 | export const ON_FILTER_IS_OPEN = 'filters@ON_FILTER_IS_OPEN'
2 | export const ON_FILTER_IS_CLOSE = 'filters@ON_FILTER_IS_CLOSE'
3 | export const ON_FILTER_SORT_FIELD_CHANGED =
4 | 'filters@ON_FILTER_SORT_FIELD_CHANGED'
5 | export const ON_FILTER_SORT_ORIENTATION_CHANGED =
6 | 'filters@ON_FILTER_SORT_ORIENTATION_CHANGED'
7 | export const ON_ADD_FILTER_QUERY = 'filters@ON_ADD_FILTER_QUERY'
8 | export const ON_EDIT_FILTER_QUERY = 'filters@ON_EDIT_FILTER_QUERY'
9 | export const ON_REMOVE_FILTER_QUERY = 'filters@ON_REMOVE_FILTER_QUERY'
10 | export const ON_SET_SEARCH = 'filters@ON_SET_SEARCH'
11 | export const ON_CLEAR = 'filters@ON_CLEAR'
12 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/Menu/Context.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export enum togglerTypes {
4 | isAuthMenuOpen = 'isAuthMenuOpen',
5 | isMiniMode = 'isMiniMode',
6 | isMenuOpen = 'isMenuOpen',
7 | isMobileMenuOpen = 'isMobileMenuOpen',
8 | isMiniSwitchVisibility = 'isMiniSwitchVisibility',
9 | }
10 |
11 | export type MenuContextType = {
12 | /** Method for updating context values. Use `togglerTypes` enum to access properties. Provide new value to set to specified property */
13 | toggleThis: (value: togglerTypes, newValue?: boolean | null) => void
14 | isDesktop: boolean
15 | isAuthMenuOpen?: boolean
16 | isMiniMode?: boolean
17 | isMenuOpen?: boolean
18 | isMobileMenuOpen?: boolean
19 | isMiniSwitchVisibility?: boolean
20 | }
21 |
22 | export const Context = React.createContext(
23 | undefined
24 | )
25 |
26 | export default Context
27 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/Menu/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react'
2 | import Context, { MenuContextType } from './Context'
3 | import Provider from './Provider'
4 |
5 | /**
6 | * Custom hook to access the menu context.
7 | *
8 | * @function
9 | * @returns {MenuContextType} The menu context value.
10 | * @throws {Error} If used outside of an MenuProvider.
11 | * @example
12 | * const menuContext = useMenu()
13 | *
14 | * @description Gives you access to menu context. Provides you with set of properties and method to update those
15 | * properties. Possible to change properties defined in `togglerTypes` enum.
16 | * Provides you with properties:
17 | * - isDesktop: boolean
18 | * - isAuthMenuOpen?: boolean
19 | * - isMiniMode?: boolean
20 | * - isMenuOpen?: boolean
21 | * - isMobileMenuOpen?: boolean
22 | * - isMiniSwitchVisibility?: boolean
23 | *
24 | * @see {togglerTypes} to check possible values to change with method
25 | */
26 | function useMenu(): MenuContextType {
27 | const context = useContext(Context)
28 |
29 | if (context === undefined) {
30 | throw new Error('useMenu must be used within a MenuProvider')
31 | }
32 | return context
33 | }
34 |
35 | export { useMenu, Context as MenuContext, Provider as MenuProvider }
36 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/Menu/store/reducer.tsx:
--------------------------------------------------------------------------------
1 | import { MenuContextType } from '../Context'
2 | import * as types from './types'
3 |
4 | type ReducerAction = {
5 | type: string
6 | payload: boolean
7 | }
8 |
9 | export default function reducer(
10 | state: Partial = {},
11 | action: ReducerAction
12 | ) {
13 | const { type, payload } = action
14 | switch (type) {
15 | case types.SET_IS_AUTH_MENU_OPEN:
16 | return { ...state, isAuthMenuOpen: payload }
17 | case types.SET_IS_MINI_MODE:
18 | return { ...state, isMiniMode: payload }
19 | case types.SET_IS_MENU_OPEN:
20 | return { ...state, isMenuOpen: payload }
21 | case types.SET_IS_MOBILE_MENU_OPEN:
22 | return { ...state, isMobileMenuOpen: payload }
23 | case types.SET_IS_MINI_SWITCH_VISIBILITY:
24 | return { ...state, isMiniSwitchVisibility: payload }
25 | default:
26 | return state
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/Menu/store/types.tsx:
--------------------------------------------------------------------------------
1 | export const SET_IS_AUTH_MENU_OPEN = 'SET_IS_AUTH_MENU_OPEN'
2 | export const SET_IS_MINI_MODE = 'SET_IS_MINI_MODE'
3 | export const SET_IS_MENU_OPEN = 'SET_IS_MENU_OPEN'
4 | export const SET_IS_MOBILE_MENU_OPEN = 'SET_IS_MOBILE_MENU_OPEN'
5 | export const SET_IS_MINI_SWITCH_VISIBILITY = 'SET_IS_MINI_SWITCH_VISIBILITY'
6 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/Theme/Context.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export interface ThemeContextType {
4 | /**
5 | * @description Changing theme id
6 | * @param auth
7 | */
8 | setThemeID: (val: string) => void
9 | /**
10 | * @description Toggle dark mode ro RTL in this theme
11 | * @param mode - Parameter mode can be 'isRTL' or 'isDarkMode' and accordingly theme parameters will switch for that param
12 | */
13 | toggleThisTheme: (mode: 'isRTL' | 'isDarkMode') => void
14 |
15 | /**
16 | * @description Boolean value definig if dark mode is enabled
17 | */
18 | isDarkMode: boolean
19 |
20 | /**
21 | * @description Boolean value definig if RTL is enabled
22 | */
23 | isRTL: boolean
24 |
25 | /**
26 | * @description Id of theme
27 | */
28 | themeID: string
29 | }
30 |
31 | export const Context = React.createContext(
32 | undefined
33 | )
34 |
35 | export default Context
36 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/Theme/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react'
2 | import Context, { ThemeContextType } from './Context'
3 | import Provider from './Provider'
4 |
5 | /**
6 | * Custom hook to access the theme context.
7 | *
8 | * @function
9 | * @returns {ThemeContextType} The theme context value.
10 | * @throws {Error} If used outside of an ThemeProvider.
11 | * @example
12 | * const theme = useTheme()
13 | *
14 | * @description Gives you access to theme context. Theme context provides you with set of methods and properties that define
15 | * look of the App.
16 | * Default values are provided in application configuration file.
17 | */
18 | function useTheme(): ThemeContextType {
19 | const context = useContext(Context)
20 |
21 | if (context === undefined) {
22 | throw new Error('useTheme must be used within a ThemeProvider')
23 | }
24 | return context
25 | }
26 |
27 | export { useTheme, Context as ThemeContext, Provider as ThemeProvider }
28 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/VirtualLists/Context.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export interface VirtualListsContextType {
4 | /**
5 | * @description Set offset for provided name to provided value
6 | * @param name
7 | * @param offset
8 | */
9 | setOffset: (name: string, offset: any) => void
10 | /**
11 | * @description Toggle dark mode ro RTL in this theme
12 | * @param name - Get offset by name
13 | */
14 | getOffset: (name: string) => void
15 | }
16 |
17 | export const Context = React.createContext(
18 | undefined
19 | )
20 |
21 | export default Context
22 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/VirtualLists/Provider.tsx:
--------------------------------------------------------------------------------
1 | import React, { useReducer } from 'react'
2 | import Context from './Context'
3 | import { IProviderProps } from '@ecronix/material-ui-shell/common.type'
4 |
5 | type ReducerAction = {
6 | type: string
7 | name: string
8 | offset: any
9 | }
10 |
11 | function reducer(state: any, action: ReducerAction) {
12 | const { type, name, offset } = action
13 | switch (type) {
14 | case 'SET_OFFSET':
15 | return { ...state, [name]: offset }
16 | default:
17 | throw new Error()
18 | }
19 | }
20 |
21 | const Provider: React.FC = ({ children }) => {
22 | const [state, dispatch] = useReducer(reducer, {})
23 |
24 | const setOffset = (name: string, offset: any) => {
25 | dispatch({ type: 'SET_OFFSET', name, offset })
26 | }
27 |
28 | const getOffset = (name: string) => {
29 | return state[name] || 0
30 | }
31 |
32 | return (
33 |
34 | {children}
35 |
36 | )
37 | }
38 |
39 | export default Provider
40 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/VirtualLists/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react'
2 | import Context, { VirtualListsContextType } from './Context'
3 | import Provider from './Provider'
4 |
5 | /**
6 | * Custom hook to access virtual lists.
7 | *
8 | * @function
9 | * @returns {VirtualListsContextType} Virtual list context value.
10 | * @throws {Error} If used outside of an VirtualListsProvider.
11 | * @example
12 | * const { getOffset, setOffset } = useVirtualLists()
13 | *
14 | * @description
15 | * This hook provides access to the virtual lists context. It must be used withgin VirutalListsProvider.
16 | * It provides methods for setting and getting offset by name:
17 | * - setOffset
18 | * - getOffset
19 | *
20 | * @see {VirtualListsContextType} for methods reference
21 | */
22 | function useVirtualLists(): VirtualListsContextType {
23 | const context = useContext(Context)
24 |
25 | if (context === undefined) {
26 | throw new Error(
27 | 'useVirtualLists must be used within a VirtualListsProvider'
28 | )
29 | }
30 | return context
31 | }
32 |
33 | export {
34 | useVirtualLists,
35 | Context as VirtualListsContext,
36 | Provider as VirtualListsProvider,
37 | }
38 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/providers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './VirtualLists'
2 | export * from './Theme'
3 | export * from './Menu'
4 | export * from './Dialogs/Question'
5 | export * from './Filter'
6 | export { togglerTypes } from './Menu/Context'
7 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | import { createTheme } from '@mui/material/styles'
2 | import { ThemeType } from '../common.type'
3 |
4 | export const getThemeSource = (
5 | id: string,
6 | ts: ThemeType[],
7 | isDarkMode: boolean,
8 | isRTL: boolean
9 | ) => {
10 | if (ts) {
11 | for (let i = 0; i < ts.length; i++) {
12 | if (ts[i]['id'] === id) {
13 | const source = ts[i]['source']
14 | const palette = source != null ? source.palette : {}
15 | return createTheme({
16 | ...source,
17 | palette: { ...palette, mode: isDarkMode ? 'dark' : 'light' },
18 | direction: isRTL ? 'rtl' : 'ltr',
19 | })
20 | }
21 | }
22 | }
23 |
24 | return createTheme({
25 | palette: { mode: isDarkMode ? 'dark' : 'light' },
26 | direction: isRTL ? 'rtl' : 'ltr',
27 | })
28 | }
29 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../base-tsconfig.json",
3 | "compilerOptions": {
4 | "paths": {
5 | "@ecronix/material-ui-shell": ["./src"],
6 | "@ecronix/material-ui-shell/*": ["./src/*"]
7 | },
8 | "declarationDir": "./dist/types"
9 | },
10 | "include": ["src/**/*"],
11 | "exclude": ["node_modules"]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/material-ui-shell/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 | import path from 'path'
4 | import { visualizer } from 'rollup-plugin-visualizer'
5 | import { externalizeDeps } from 'vite-plugin-externalize-deps'
6 |
7 | // https://vitejs.dev/config/
8 | export default defineConfig({
9 | plugins: [react(), visualizer(), externalizeDeps()],
10 | resolve: {
11 | alias: {
12 | '@ecronix/material-ui-shell': path.resolve(__dirname, 'src'),
13 | },
14 | extensions: ['.js', '.ts', '.jsx', '.tsx'],
15 | },
16 | build: {
17 | minify: false,
18 | lib: {
19 | entry: path.resolve(__dirname, 'src/index.ts'),
20 | name: 'material-ui-shell',
21 | formats: ['es'],
22 | },
23 | },
24 | })
25 |
--------------------------------------------------------------------------------
/packages/rmw-shell/.gitignore:
--------------------------------------------------------------------------------
1 | /coverage
2 | /dist
3 | /node_modules
4 | /umd
5 | npm-debug.log*
6 | stats.html
7 |
--------------------------------------------------------------------------------
/packages/rmw-shell/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Prerequisites
2 |
3 | [Node.js](http://nodejs.org/) >= 10 must be installed.
4 |
5 | ## Installation
6 |
7 | - Running `npm install` in the component's root directory will install everything you need for development.
8 |
9 | ## Demo Development Server
10 |
11 | - `npm start` will run a development server with the component's demo app at [http://localhost:3000](http://localhost:3000) with hot module reloading.
12 |
13 | ## Running Tests
14 |
15 | - `npm test` will run the tests once.
16 |
17 | - `npm run test:coverage` will run the tests and produce a coverage report in `coverage/`.
18 |
19 | - `npm run test:watch` will run the tests on every change.
20 |
21 | ## Building
22 |
23 | - `npm run build` will build the component for publishing to npm and also bundle the demo app.
24 |
25 | - `npm run clean` will delete built resources.
26 |
--------------------------------------------------------------------------------
/packages/rmw-shell/README.md:
--------------------------------------------------------------------------------
1 | # my-component
2 |
3 | [![Travis][build-badge]][build]
4 | [![npm package][npm-badge]][npm]
5 | [![Coveralls][coveralls-badge]][coveralls]
6 |
7 | Describe my-component here.
8 |
9 | [build-badge]: https://img.shields.io/travis/user/repo/master.png?style=flat-square
10 | [build]: https://travis-ci.org/user/repo
11 |
12 | [npm-badge]: https://img.shields.io/npm/v/npm-package.png?style=flat-square
13 | [npm]: https://www.npmjs.org/package/npm-package
14 |
15 | [coveralls-badge]: https://img.shields.io/coveralls/user/repo/master.png?style=flat-square
16 | [coveralls]: https://coveralls.io/github/user/repo
17 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@ecronix/create-rmw-shell",
3 | "version": "1.0.40",
4 | "description": "A template to create new projects based on @ecronix/rmw-shell",
5 | "bin": {
6 | "create-my-template": "index.js"
7 | },
8 | "main": "index.js",
9 | "devDependencies": {
10 | "rmw-shell-template": "^1.0.43"
11 | },
12 | "scripts": {
13 | "start": "node index.js",
14 | "sync": "node sync-peer-deps.js"
15 | },
16 | "keywords": [
17 | "ecronix",
18 | "rmw-shell",
19 | "react-most-wanted"
20 | ],
21 | "author": "Abdallah",
22 | "license": "MIT"
23 | }
24 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/.firebaserc:
--------------------------------------------------------------------------------
1 | {
2 | "projects": {
3 | "default": "react-most-wanted-dev",
4 | "prod": "react-most-wanted-3b1b2",
5 | "dev": "react-most-wanted-dev"
6 | }
7 | }
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "database": {
3 | "rules": "firebase/database.rules.json"
4 | },
5 | "firestore": {
6 | "rules": "firebase/firestore.rules",
7 | "indexes": "firebase/firestore.indexes.json"
8 | },
9 | "functions": {
10 | "source": "firebase/functions"
11 | },
12 | "hosting": {
13 | "public": "build",
14 | "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
15 | "rewrites": [
16 | {
17 | "source": "**",
18 | "destination": "/index.html"
19 | }
20 | ],
21 | "headers": [
22 | {
23 | "source": "/service-worker.js",
24 | "headers": [
25 | {
26 | "key": "Cache-Control",
27 | "value": "no-cache"
28 | }
29 | ]
30 | }
31 | ]
32 | },
33 | "storage": {
34 | "rules": "firebase/storage.rules"
35 | },
36 | "emulators": {
37 | "functions": {
38 | "port": 5001
39 | },
40 | "firestore": {
41 | "port": 8080
42 | },
43 | "database": {
44 | "port": 9000
45 | },
46 | "hosting": {
47 | "port": 5000
48 | },
49 | "pubsub": {
50 | "port": 8085
51 | },
52 | "ui": {
53 | "enabled": true
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/firestore.indexes.json:
--------------------------------------------------------------------------------
1 | {
2 | "indexes": [],
3 | "fieldOverrides": []
4 | }
5 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | .runtimeconfig.json
3 | .firebase-debug.log
4 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/db/admins/onWrite.f.js:
--------------------------------------------------------------------------------
1 | import * as functions from 'firebase-functions'
2 | import admin from 'firebase-admin'
3 | import { setClaim, removeClaim } from '../../utils/customClaims'
4 |
5 | export default functions
6 | .region('europe-west1')
7 | .database.ref('admins/{uid}/')
8 | .onWrite(async (snap, context) => {
9 | const value = snap.after.val()
10 | const uid = context.params.uid
11 |
12 | if (value) {
13 | await admin.firestore().doc(`/admins/${uid}/`).set({ isAdmin: value })
14 | await setClaim(uid, 'admin')
15 | } else {
16 | await admin.firestore().doc(`/admins/${uid}/`).delete()
17 | await removeClaim(uid, 'admin')
18 | }
19 |
20 | return
21 | })
22 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/db/groupChats/members/onCreate.f.js:
--------------------------------------------------------------------------------
1 | import { database } from 'firebase-functions'
2 | import admin from 'firebase-admin'
3 |
4 | export default database
5 | .ref('/group_chats/{groupUid}/members/{uid}')
6 | .onCreate(async (snapshot, context) => {
7 | const { uid, groupUid } = context.params
8 |
9 | const chatSnap = await admin
10 | .database()
11 | .ref(`group_chats/${groupUid}`)
12 | .once('value')
13 |
14 | const { name = 'Grooup chat' } = chatSnap.val() || {}
15 |
16 | await admin
17 | .database()
18 | .ref(`user_chats/${uid}/${groupUid}`)
19 | .update({
20 | displayName: name,
21 | path: `group_chat_messages/${groupUid}`,
22 | lastMessage: 'Group chat',
23 | })
24 |
25 | return
26 | })
27 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/db/groupChats/members/onDelete.f.js:
--------------------------------------------------------------------------------
1 | import { database } from 'firebase-functions'
2 | import admin from 'firebase-admin'
3 |
4 | export default database
5 | .ref('/group_chats/{groupUid}/members/{uid}')
6 | .onDelete(async (snapshot, context) => {
7 | const { uid, groupUid } = context.params
8 |
9 | await admin.database().ref(`user_chats/${uid}/${groupUid}`).set(null)
10 |
11 | return
12 | })
13 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/db/groupChats/name/onUpdate.f.js:
--------------------------------------------------------------------------------
1 | import { database } from 'firebase-functions'
2 | import admin from 'firebase-admin'
3 |
4 | export default database
5 | .ref('/group_chats/{groupUid}/name')
6 | .onUpdate(async (snapshot, context) => {
7 | const { groupUid } = context.params
8 |
9 | const chatSnap = await admin
10 | .database()
11 | .ref(`group_chats/${groupUid}`)
12 | .once('value')
13 |
14 | const { members = {} } = chatSnap.val() || {}
15 |
16 | const name = snapshot.after.val() || ''
17 | const keys = []
18 | Object.keys(members).map((m) => {
19 | keys.push(m)
20 | })
21 |
22 | for (let i = 0; i < keys.length; i++) {
23 | const key = keys[i]
24 |
25 | await admin.database().ref(`user_chats/${key}/${groupUid}`).update({
26 | displayName: name,
27 | })
28 | }
29 |
30 | return
31 | })
32 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/db/publicChats/onCreate.f.js:
--------------------------------------------------------------------------------
1 | import { database } from 'firebase-functions'
2 | import admin from 'firebase-admin'
3 |
4 | export default database
5 | .ref('/public_chats/{taskUid}')
6 | .onCreate((eventSnapshot, context) => {
7 | const authorName = eventSnapshot.child('authorName').val()
8 | const authorPhotoUrl = eventSnapshot.child('authorPhotoUrl').val()
9 |
10 | return admin
11 | .database()
12 | .ref(`/notification_tokens`)
13 | .once('value')
14 | .then(nTokens => {
15 | let registrationTokens = []
16 |
17 | nTokens.forEach(user => {
18 | user.forEach(token => {
19 | registrationTokens.push(token.key)
20 | })
21 | })
22 |
23 | const payload = {
24 | notification: {
25 | title: `${authorName || 'UserName'}`,
26 | body: eventSnapshot.child('message').val(),
27 | icon: authorPhotoUrl || '/apple-touch-icon.png',
28 | click_action: 'https://www.react-most-wanted.com/public_chats',
29 | tag: 'public_chat',
30 | },
31 | }
32 |
33 | if (registrationTokens.length) {
34 | return admin.messaging().sendToDevice(registrationTokens, payload)
35 | } else {
36 | console.log('Not tokens registered')
37 | }
38 |
39 | return null
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/db/roles/onWrite.f.js:
--------------------------------------------------------------------------------
1 | import { database } from 'firebase-functions'
2 | import admin from 'firebase-admin'
3 |
4 | export default database
5 | .ref('/roles/{roleUid}')
6 | .onWrite((eventSnap, context) => {
7 | // Exit when the data is not deleted.
8 | if (eventSnap.after.exists()) {
9 | return null
10 | }
11 |
12 | const roleUid = context.params.roleUid
13 |
14 | return admin
15 | .database()
16 | .ref(`role_grants/${roleUid}`)
17 | .remove()
18 | })
19 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/db/triggers/onCreate.f.js:
--------------------------------------------------------------------------------
1 | import { database } from 'firebase-functions'
2 |
3 | export default database.ref('/triggers/{uid}').onWrite(snap => {
4 | return snap.after.ref.set(null)
5 | })
6 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/db/userChatMessages/onUpdate.f.js:
--------------------------------------------------------------------------------
1 | import { database } from 'firebase-functions'
2 | import admin from 'firebase-admin'
3 |
4 | export default database
5 | .ref('/user_chat_messages/{senderUid}/{receiverUid}/{messageUid}')
6 | .onUpdate(async (data, context) => {
7 | const { authType, params, timestamp } = context
8 | const { senderUid, receiverUid, messageUid } = params
9 |
10 | if (authType === 'ADMIN') {
11 | return
12 | }
13 |
14 | if (data.after.child('isRead').val() === true) {
15 | await admin
16 | .database()
17 | .ref(`/user_chat_messages/${receiverUid}/${senderUid}/${messageUid}`)
18 | .update({
19 | isRead: timestamp,
20 | })
21 |
22 | await admin
23 | .database()
24 | .ref(`/user_chats/${senderUid}/${receiverUid}`)
25 | .update({ isRead: timestamp })
26 |
27 | await admin
28 | .database()
29 | .ref(`/user_chats/${receiverUid}/${senderUid}`)
30 | .update({ isRead: timestamp })
31 | }
32 |
33 | return
34 | })
35 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/db/userGrants/onWrite.f.js:
--------------------------------------------------------------------------------
1 | import * as functions from 'firebase-functions'
2 | import admin from 'firebase-admin'
3 | import { setClaim, removeClaim } from '../../utils/customClaims'
4 |
5 | const wait = (t) => {
6 | return new Promise((resolve, reject) => {
7 | setTimeout(() => resolve(), t)
8 | })
9 | }
10 |
11 | const random = (min, max) => {
12 | return Math.random() * (max - min) + min
13 | }
14 |
15 | export default functions
16 | .region('europe-west1')
17 | .database.ref('user_grants/{uid}/{grant}')
18 | .onWrite(async (snap, context) => {
19 | const value = snap.after.val()
20 | const { uid, grant } = context.params
21 |
22 | await admin
23 | .firestore()
24 | .doc(`/user_grants/${uid}/`)
25 | .set(
26 | { [grant]: value ? value : admin.firestore.FieldValue.delete() },
27 | { merge: true }
28 | )
29 |
30 | console.log('Waiting....')
31 | await wait(random(1000, 4000))
32 |
33 | if (snap.after.exists() && value.indexOf('storage') !== -1) {
34 | await setClaim(uid, grant)
35 | } else {
36 | await removeClaim(uid, grant)
37 | }
38 |
39 | const user = await admin.auth().getUser(uid)
40 |
41 | console.log('customClaims', Object.keys(user.customClaims).length)
42 | console.log('customClaims', user.customClaims)
43 |
44 | return
45 | })
46 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/db/userRoles/onWrite.f.js:
--------------------------------------------------------------------------------
1 | import { database } from 'firebase-functions'
2 | import admin from 'firebase-admin'
3 |
4 | exports = module.exports = database
5 | .ref('/user_roles/{userUid}/{roleUid}')
6 | .onWrite((eventSnapshot, context) => {
7 | const userUid = context.params.userUid
8 | const roleUid = context.params.roleUid
9 |
10 | const roleGrantsRef = admin.database().ref(`role_grants/${roleUid}`)
11 |
12 | return roleGrantsRef.once('value').then(snapshot => {
13 | let promises = []
14 |
15 | snapshot.forEach(grant => {
16 | let grantRef = false
17 |
18 | console.log('User role changed:', eventSnapshot.after.val())
19 |
20 | if (eventSnapshot.after.val()) {
21 | grantRef = admin
22 | .database()
23 | .ref(`user_grants/${userUid}/${grant.key}`)
24 | .set(true)
25 | } else {
26 | grantRef = admin
27 | .database()
28 | .ref(`user_grants/${userUid}/${grant.key}`)
29 | .remove()
30 | }
31 |
32 | promises.push(grantRef)
33 | })
34 |
35 | return Promise.all(promises)
36 | })
37 | })
38 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/db/users/onWrite.f.js:
--------------------------------------------------------------------------------
1 | import { database } from 'firebase-functions'
2 | import admin from 'firebase-admin'
3 | import splitStringToArray from '../../utils/splitStringToArray'
4 |
5 | exports = module.exports = database
6 | .ref('/users/{userUid}')
7 | .onWrite(async (eventSnapshot, context) => {
8 | const { userUid } = context.params
9 | if (eventSnapshot.after.exists()) {
10 | const { displayName = '', photoURL = '' } =
11 | eventSnapshot.after.val() || {}
12 | await admin
13 | .firestore()
14 | .doc(`/users/${userUid}`)
15 | .set(
16 | {
17 | displayName: displayName || '',
18 | photoURL: photoURL || '',
19 | search: splitStringToArray(displayName || ''),
20 | },
21 | { merge: true }
22 | )
23 | } else {
24 | await admin.firestore().doc(`/users/${userUid}/`).delete()
25 | }
26 | })
27 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | npm-debug.log*
6 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/https/admin/onCall.f.js:
--------------------------------------------------------------------------------
1 | import * as functions from 'firebase-functions'
2 | import admin from 'firebase-admin'
3 |
4 | export default functions.https.onCall(async (data, context) => {
5 | const { auth } = context
6 | if (!auth) {
7 | throw new functions.https.HttpsError(
8 | 'failed-precondition',
9 | 'The function must be called ' + 'while authenticated.'
10 | )
11 | }
12 |
13 | const { uid } = auth
14 |
15 | console.log('uid', uid)
16 | console.log('auth', auth)
17 |
18 | try {
19 | await admin.database().ref(`admins/${uid}`).set(true)
20 | return { message: 'OK' }
21 | } catch (error) {
22 | return error
23 | }
24 | })
25 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/https/messages/onCall.f.js:
--------------------------------------------------------------------------------
1 | import * as functions from 'firebase-functions'
2 | import admin from 'firebase-admin'
3 |
4 | export default functions.https.onCall(async (data, context) => {
5 | if (!context.auth) {
6 | throw new functions.https.HttpsError(
7 | 'failed-precondition',
8 | 'The function must be called ' + 'while authenticated.'
9 | )
10 | }
11 |
12 | const { payload } = data
13 | console.log('payload', payload)
14 |
15 | try {
16 | const response = await admin.messaging().send(payload)
17 | return { response }
18 | } catch (error) {
19 | return error
20 | }
21 | })
22 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/index.js:
--------------------------------------------------------------------------------
1 | const loadFunctions = require('firebase-function-tools')
2 | const functions = require('firebase-functions')
3 | const admin = require('firebase-admin')
4 | const config = functions.config().firebase
5 |
6 | admin.initializeApp(config)
7 |
8 | loadFunctions(__dirname, exports, true)
9 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "functions",
3 | "description": "Cloud Functions for Firebase",
4 | "scripts": {
5 | "serve": "firebase emulators:start --only functions",
6 | "shell": "firebase functions:shell",
7 | "start": "npm run shell",
8 | "deploy": "firebase deploy --only functions",
9 | "logs": "firebase functions:log"
10 | },
11 | "engines": {
12 | "node": "14"
13 | },
14 | "main": "index.js",
15 | "dependencies": {
16 | "axios": "^0.27.2",
17 | "babel-runtime": "^6.26.0",
18 | "camelcase": "^6.0.0",
19 | "child-process-promise": "^2.2.1",
20 | "firebase-admin": "^10.0.0",
21 | "firebase-function-tools": "^2.0.1",
22 | "firebase-functions": "^3.22.0",
23 | "glob": "^7.1.6",
24 | "mkdirp-promise": "^5.0.1",
25 | "moment": "^2.29.4",
26 | "nodemailer": "^6.7.8",
27 | "request": "^2.88.2",
28 | "request-promise": "^4.2.6",
29 | "uuid": "^8.3.0"
30 | },
31 | "devDependencies": {
32 | "firebase-functions-test": "^0.3.3",
33 | "path": "^0.12.7"
34 | },
35 | "private": true
36 | }
37 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/storage/onFinalize.f.js:
--------------------------------------------------------------------------------
1 | import * as functions from 'firebase-functions'
2 | import admin from 'firebase-admin'
3 | import thumbnails from './thumbnails'
4 |
5 | export default functions
6 | .region('europe-west1')
7 | .storage.object()
8 | .onFinalize(async (object, context) => {
9 | const { name, contentType } = object
10 |
11 | if (name.startsWith('users/') && contentType.startsWith('image')) {
12 | return thumbnails(object)
13 | }
14 |
15 | return null
16 | })
17 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/storage/thumbnails.js:
--------------------------------------------------------------------------------
1 | import admin from 'firebase-admin'
2 | import createThumbnail from 'firebase-function-tools/lib/thumbnail'
3 |
4 | export default async function(object) {
5 | const thumbnail = await createThumbnail(object)
6 |
7 | if (thumbnail) {
8 | const { fileDir, downloadURL } = thumbnail
9 |
10 | await admin
11 | .database()
12 | .ref(fileDir)
13 | .update({ thumbnail: downloadURL })
14 | }
15 |
16 | return
17 | }
18 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/utils/customClaims.js:
--------------------------------------------------------------------------------
1 | import admin from 'firebase-admin'
2 |
3 | const setClaim = async (uid, name, value = true) => {
4 | const user = await admin.auth().getUser(uid)
5 |
6 | const { [name]: claimName, ...rest } = user.customClaims || {}
7 |
8 | await admin.auth().setCustomUserClaims(uid, { ...rest, [name]: value })
9 | }
10 |
11 | const removeClaim = async (uid, name) => {
12 | const user = await admin.auth().getUser(uid)
13 |
14 | const { [name]: claimName, ...rest } = user.customClaims || {}
15 |
16 | await admin.auth().setCustomUserClaims(uid, { ...rest })
17 | }
18 |
19 | export { setClaim, removeClaim }
20 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/utils/splitStringToArray.js:
--------------------------------------------------------------------------------
1 | const MAPPING_TABLE = {
2 | à: 'a',
3 | á: 'a',
4 | â: 'a',
5 | ã: 'a',
6 | å: 'a',
7 | æ: 'ae',
8 | ç: 'c',
9 | è: 'e',
10 | é: 'e',
11 | ê: 'e',
12 | ë: 'e',
13 | ì: 'i',
14 | í: 'i',
15 | î: 'i',
16 | ï: 'i',
17 | ñ: 'n',
18 | ò: 'o',
19 | ó: 'o',
20 | ô: 'o',
21 | õ: 'o',
22 | ù: 'u',
23 | ú: 'u',
24 | û: 'u',
25 | ý: 'y',
26 | ÿ: 'y',
27 | }
28 |
29 | function splitStringToArray(stringToSplit) {
30 | const listCharacters = stringToSplit.split('')
31 | var output = []
32 | //replace special Characters
33 | for (var i = 0; i < listCharacters.length; i++) {
34 | if (MAPPING_TABLE[listCharacters[i]] != null) {
35 | listCharacters[i] = MAPPING_TABLE[listCharacters[i]]
36 | }
37 | }
38 | for (var i = 0; i < listCharacters.length; i++) {
39 | var temp = [listCharacters[i]]
40 | for (var j = i + 1; j < listCharacters.length; j++) {
41 | temp.push(listCharacters[j])
42 | const joinedString = temp.join('').toLowerCase()
43 | if (joinedString.length > 2) {
44 | output.push(joinedString)
45 | }
46 | }
47 | }
48 | return output
49 | }
50 |
51 | export default splitStringToArray
52 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/functions/utils/users.js:
--------------------------------------------------------------------------------
1 | const admin = require('firebase-admin')
2 |
3 | // Source: https://firebase.google.com/docs/auth/admin/manage-users
4 | const listAllUsers = (userIds = [], nextPageToken) => {
5 | // List batch of users, 1000 at a time.
6 | return admin
7 | .auth()
8 | .listUsers(1000, nextPageToken)
9 | .then(function (resp) {
10 | if (resp.pageToken) {
11 | // List next batch of users.
12 | return listAllUsers(userIds.concat(resp.users), resp.pageToken)
13 | }
14 | return userIds.concat(resp.users)
15 | })
16 | .catch(function (error) {
17 | console.log('Error listing users:', error)
18 | })
19 | }
20 |
21 | export { listAllUsers }
22 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/firebase/storage.rules:
--------------------------------------------------------------------------------
1 | rules_version = '2';
2 | service firebase.storage {
3 | match /b/{bucket}/o {
4 | match /{allPaths=**} {
5 | allow read, write: if request.auth!=null;
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "src"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rmw-shell-template",
3 | "version": "1.0.43",
4 | "description": "This project was bootstrapped with [@ecronix/rmw-shell](https://github.com/ecronix/react-most-wanted)",
5 | "private": "true",
6 | "type": "module",
7 | "scripts": {
8 | "dev": "vite",
9 | "build": "vite build",
10 | "serve": "vite preview"
11 | },
12 | "dependencies": {
13 | "@ecronix/rmw-shell": "^11.2.82"
14 | },
15 | "devDependencies": {
16 | "@vitejs/plugin-react": "^4",
17 | "vite": "^5"
18 | },
19 | "keywords": [],
20 | "author": "",
21 | "license": "ISC"
22 | }
23 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/public/background.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/rmw-shell/create-rmw-shell/template/public/background.webp
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/public/bottom.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/rmw-shell/create-rmw-shell/template/public/bottom.jpg
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/rmw-shell/create-rmw-shell/template/public/favicon.ico
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/public/firebase-messaging-sw.js:
--------------------------------------------------------------------------------
1 | // Import and configure the Firebase SDK
2 | // These scripts are made available when the app is served or deployed on Firebase Hosting
3 | // If you do not serve/host your project using Firebase Hosting see https://firebase.google.com/docs/web/setup
4 | importScripts('/__/firebase/7.18.0/firebase-app.js')
5 | importScripts('/__/firebase/7.18.0/firebase-messaging.js')
6 | importScripts('/__/firebase/init.js')
7 |
8 | const messaging = firebase.messaging()
9 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/public/firebase.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/rmw-shell/create-rmw-shell/template/public/firebase.png
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/rmw-shell/create-rmw-shell/template/public/logo192.png
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/rmw-shell/create-rmw-shell/template/public/logo512.png
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "RMW",
3 | "name": "React Most Wanted",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | },
20 | {
21 | "src": "maskable_icon.png",
22 | "sizes": "512x512",
23 | "type": "image/png",
24 | "purpose": "any maskable"
25 | }
26 | ],
27 | "start_url": ".",
28 | "display": "standalone",
29 | "theme_color": "#000000",
30 | "background_color": "#ffffff"
31 | }
32 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/public/maskable_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/rmw-shell/create-rmw-shell/template/public/maskable_icon.png
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/public/material-ui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/rmw-shell/create-rmw-shell/template/public/material-ui.png
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/public/react.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecronix/react-most-wanted/ac59f70f22ad329c127bcf206883651cdee73e4d/packages/rmw-shell/create-rmw-shell/template/public/react.png
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/components/Forms/Company.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { TextField } from 'mui-rff'
3 |
4 | // eslint-disable-next-line
5 | export default function ({ handleSubmit }) {
6 | return (
7 |
32 | )
33 | }
34 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/config/grants.jsx:
--------------------------------------------------------------------------------
1 | export const grants = ['create_company', 'edit_company', 'delete_company', 'read_companies']
2 |
3 | export default grants
4 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/config/index.jsx:
--------------------------------------------------------------------------------
1 | export { default } from "./config";
2 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/config/locales/de.js:
--------------------------------------------------------------------------------
1 | import { defineMessages } from 'react-intl'
2 |
3 | const messages = defineMessages({
4 | app_name: 'React Meist Gesucht',
5 | sign_in: 'Anmelden',
6 | sign_out: 'Abmelden',
7 | username: 'Nutzername',
8 | password: 'Passwort',
9 | about: 'Über',
10 | home: 'Startseite',
11 | page_not_found: 'Seite nicht gefunden',
12 | settings: 'Einstellungen',
13 | theme: 'Thema',
14 | default: 'Standard',
15 | red: 'Rot',
16 | green: 'Grün',
17 | language: 'Sprache',
18 | en: 'Englisch',
19 | de: 'Deutsch',
20 | ru: 'Russisch',
21 | menu: 'Menü',
22 | menu_mini_mode: 'Mini-Menü',
23 | offline: 'Offline',
24 | tasks: 'Aufgaben',
25 | companies: 'Unternehmen',
26 | })
27 |
28 | export default messages
29 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/config/locales/en.js:
--------------------------------------------------------------------------------
1 | import { defineMessages } from 'react-intl'
2 |
3 | const messages = defineMessages({
4 | app_name: 'React Most Wanted',
5 | sign_in: 'Sign in',
6 | sign_out: 'Sign out',
7 | username: 'Username',
8 | password: 'Password',
9 | about: 'About',
10 | home: 'Home',
11 | page_not_found: 'Page not found',
12 | settings: 'Settings',
13 | theme: 'Theme',
14 | default: 'Default',
15 | red: 'Red',
16 | green: 'Green',
17 | language: 'Language',
18 | en: 'English',
19 | de: 'German',
20 | ru: 'Russian',
21 | menu: 'Menu',
22 | menu_mini_mode: 'Mini menu',
23 | offline: 'Offline',
24 | })
25 |
26 | export default messages
27 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/config/locales/index.js:
--------------------------------------------------------------------------------
1 | const locales = [
2 | {
3 | locale: 'en',
4 | messages: import('./en'),
5 | //loadData: import(`@formatjs/intl-relativetimeformat/dist/locale-data/en`),
6 | },
7 | {
8 | locale: 'ru',
9 | messages: import('./ru'),
10 | //loadData: import(`@formatjs/intl-relativetimeformat/dist/locale-data/ru`),
11 | },
12 | {
13 | locale: 'de',
14 | messages: import('./de'),
15 | //loadData: import(`@formatjs/intl-relativetimeformat/dist/locale-data/de`),
16 | },
17 | ]
18 |
19 | export default locales
20 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/config/locales/ru.js:
--------------------------------------------------------------------------------
1 | import { defineMessages } from 'react-intl'
2 |
3 | const messages = defineMessages({
4 | app_name: 'React Most Wanted',
5 | sign_in: 'Вход',
6 | sign_out: 'Выход',
7 | username: 'Имя пользователя',
8 | password: 'Пароль',
9 | about: 'О нас',
10 | home: 'Главная',
11 | page_not_found: 'Страница не найдена',
12 | settings: 'Настройки',
13 | theme: 'Тема',
14 | default: 'По умолчанию',
15 | red: 'Красная',
16 | green: 'Зелёная',
17 | language: 'Язык',
18 | en: 'English',
19 | de: 'Deutsch',
20 | ru: 'Русский',
21 | menu: 'Меню',
22 | menu_mini_mode: 'Мини меню',
23 | offline: 'Офлайн',
24 | })
25 |
26 | export default messages
27 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/config/themes.jsx:
--------------------------------------------------------------------------------
1 | import red from '@mui/material/colors/red'
2 | import pink from '@mui/material/colors/pink'
3 | import green from '@mui/material/colors/green'
4 |
5 | const themes = [
6 | {
7 | id: 'default',
8 | source: {
9 | palette: {
10 | primary: { main: '#343434' },
11 | secondary: {
12 | main: '#c62828',
13 | },
14 | },
15 | },
16 | },
17 | {
18 | id: 'red',
19 | color: red[500],
20 | source: {
21 | palette: {
22 | primary: red,
23 | secondary: pink,
24 | error: red,
25 | },
26 | },
27 | },
28 | {
29 | id: 'green',
30 | color: green[500],
31 | source: {
32 | palette: {
33 | primary: green,
34 | secondary: red,
35 | error: red,
36 | },
37 | },
38 | },
39 | {
40 | id: 'standard',
41 | },
42 | ]
43 |
44 | export default themes
45 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/demo-index.jsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from "react";
2 | import { createRoot } from "react-dom/client";
3 | import { AppContainer } from "@ecronix/base-shell";
4 | import config from "./config";
5 | import * as serviceWorkerRegistration from "./serviceWorkerRegistration";
6 |
7 | createRoot(document.getElementById("root")).render(
8 |
9 |
10 | ,
11 | );
12 |
13 | serviceWorkerRegistration.register({
14 | onUpdate: (reg) => {
15 | window.update = () => {
16 | try {
17 | reg.waiting.postMessage({ type: "SKIP_WAITING" });
18 | window.location.reload();
19 | } catch (error) {
20 | console.warn("error", error);
21 | }
22 | };
23 | },
24 | });
25 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/pages/About/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { MarkdownPageContainer } from "@ecronix/rmw-shell";
3 | import { useIntl } from "react-intl";
4 |
5 | export default function AboutPage() {
6 | const intl = useIntl();
7 | return (
8 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/pages/LandingPage/Footer.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import AppBar from "@mui/material/AppBar";
3 |
4 | export default function Footer() {
5 | return (
6 |
7 |
22 |
41 |
42 | );
43 | }
44 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/pages/LandingPage/messages/bs.json:
--------------------------------------------------------------------------------
1 | {
2 | "signin": "Register",
3 | "intro": "React Starter-Kit with all Most Wanted features ",
4 | "title": " REACT MOST WANTED ",
5 | "start": "GET STARTED",
6 | "instal": "Installation",
7 | "run": "Just run this script to start:",
8 | "more": "Learn More",
9 | "usage": "Usage",
10 | "set": "Set your configuration to the App component:",
11 | "what": "What is this?",
12 | "this": "This is a OPEN SOURCE demo application that demonstartes the usage of the rmw-shell library with react, Material-UI and firebase.",
13 | "demo": "This demo has no purpose to do something as an app. It is here just to show how everthing works together."
14 | }
15 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/pages/LandingPage/messages/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "intro": "React Starterkit mit allen Meist Gesucht Ausstattungen",
3 | "title": "REACT MEIST GESUCHT",
4 | "start": "STARTEN",
5 | "instal": "Installation",
6 | "run": "Einfach dieses Skript starten:",
7 | "more": "Mehr",
8 | "usage": "Nutzung",
9 | "set": "Deine Einschtellungen einfach in die App Componente setzten",
10 | "what": "Was ist das?",
11 | "this": "This is a OPEN SOURCE demo application that demonstartes the usage of the rmw-shell library with react, Material-UI and firebase.",
12 | "demo": "This demo has no purpose to do something as an app. It is here just to show how everthing works together.",
13 | "signin": "Anmelden",
14 | "new_users": "Neue Benutzer",
15 | "companies": "Unternehmen",
16 | "about": "Über",
17 | "team": "Team",
18 | "try_it_out": "Probier es aus",
19 | "about_text": "React Most Wanted is just a DEMO applications. Don't try to find something usefull to do with this DEMO. The focus here is only on the code and how to build react applications using Material-UI and Firebase."
20 | }
21 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/pages/LandingPage/messages/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "intro": "React Starter-Kit with all Most Wanted features ",
3 | "title": " REACT MOST WANTED ",
4 | "start": "GET STARTED",
5 | "instal": "Installation",
6 | "run": "Just run this script to start:",
7 | "more": "Learn More",
8 | "usage": "Usage",
9 | "set": "Set your configuration to the App component:",
10 | "what": "What is this?",
11 | "this": "This is a OPEN SOURCE demo application that demonstartes the usage of the rmw-shell library with react, Material-UI and firebase.",
12 | "demo": "This demo has no purpose to do something as an app. It is here just to show how everthing works together.",
13 | "signin": "Signin",
14 | "new_users": "New users",
15 | "companies": "Companies",
16 | "try_it_out": "Try it out",
17 | "about": "About",
18 | "team": "Team",
19 | "about_text": "React Most Wanted is just a DEMO applications. Don't try to find something usefull to do with this DEMO. The focus here is only on the code and how to build react applications using Material-UI and Firebase."
20 | }
21 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/pages/LandingPage/messages/es.json:
--------------------------------------------------------------------------------
1 | {
2 | "signin": "Register",
3 | "intro": "React Starter-Kit with all Most Wanted features ",
4 | "title": " REACT MOST WANTED ",
5 | "start": "GET STARTED",
6 | "instal": "Installation",
7 | "run": "Just run this script to start:",
8 | "more": "Learn More",
9 | "usage": "Usage",
10 | "set": "Set your configuration to the App component:",
11 | "what": "What is this?",
12 | "this": "This is a OPEN SOURCE demo application that demonstartes the usage of the rmw-shell library with react, Material-UI and firebase.",
13 | "demo": "This demo has no purpose to do something as an app. It is here just to show how everthing works together."
14 | }
15 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/pages/LandingPage/messages/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "intro": "React Starter-Kit avec toutes les fonctionnalités les plus recherchées",
3 | "title": " REACT MOST WANTED ",
4 | "start": "COMMENCER",
5 | "instal": "Installation",
6 | "run": "Il suffit d'exécuter ce script pour commencer:",
7 | "more": "Apprendre encore plus",
8 | "usage": "Usage",
9 | "set": "Définissez votre configuration sur le composant App:",
10 | "what": "Qu'est-ce que c'est?",
11 | "this": "Il s'agit d'une application de démonstration OPEN SOURCE qui montre l'utilisation de la bibliothèque rmw-shell avec react, Material-UI et firebase.",
12 | "demo": "Cette démo n'a pas pour but de faire quelque chose en tant qu'application. C'est juste pour montrer comment tout fonctionne ensemble.",
13 | "signin": "Se connecter",
14 | "new_users": "Nouveaux utilisateurs",
15 | "companies": "Entreprises",
16 | "try_it_out": "Essaye le",
17 | "about": "À propos",
18 | "team": "Équipe",
19 | "about_text": "React Most Wanted n'est qu'une application DEMO. N'essayez pas de trouver quelque chose d'utile à faire avec cette DÉMO. Ici, l'accent est uniquement mis sur le code et sur la façon de créer des applications React à l'aide de Material-UI et Firebase."
20 | }
21 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/pages/LandingPage/messages/index.js:
--------------------------------------------------------------------------------
1 | import { parseLanguages, formatMessage } from "@ecronix/rmw-shell";
2 | import messages_de from "./de.json";
3 | import messages_en from "./en.json";
4 | import messages_bs from "./bs.json";
5 | import messages_es from "./es.json";
6 | import messages_ru from "./ru.json";
7 | import messages_it from "./it.json";
8 | import messages_fr from "./fr.json";
9 | import messages_pt from "./pt.json";
10 |
11 | const messageSources = {
12 | de: messages_de,
13 | bs: messages_bs,
14 | es: messages_es,
15 | en: messages_en,
16 | ru: messages_ru,
17 | it: messages_it,
18 | fr: messages_fr,
19 | pt: messages_pt,
20 | };
21 |
22 | const match = parseLanguages(
23 | ["en", "es", "bs", "ru", "de", "it", "fr", "pt"],
24 | "en",
25 | );
26 |
27 | const messages = messageSources[match];
28 |
29 | const format = (uid) => {
30 | return formatMessage(messages, uid);
31 | };
32 |
33 | export default format;
34 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/pages/LandingPage/messages/it.json:
--------------------------------------------------------------------------------
1 | {
2 | "signin": "Registrati",
3 | "intro": "React Starter-Kit con le features Most Wanted ",
4 | "title": " REACT MOST WANTED ",
5 | "start": "INIZIA ADESSO",
6 | "instal": "Installazione",
7 | "run": "Esegui solo questo script per iniziare:",
8 | "more": "Scopri di più",
9 | "usage": "Utilizzo",
10 | "set": "Imposta la configurazione al componente App:",
11 | "what": "Cos'è questo?",
12 | "this": "E una applicazione demo OPEN SOURCE che mostra l'utilizzo della libreria rmw-shell con React, Material-UI e Firebase.",
13 | "demo": "Questa demo non ha lo scopo di svolgere qualcosa come App. E' qui solo per mostrarti che tutto funziona :)",
14 | "new_users": "Nuovi Utenti",
15 | "companies": "Aziende",
16 | "try_it_out": "Prova",
17 | "about": "Informazioni",
18 | "team": "Squadra",
19 | "about_text": "React Most Wanted è solo una domanda DEMO. Non cercare di trovare qualcosa di utile da fare con questa DEMO. Il focus qui è solo sul codice e su come costruire applicazioni di reazione usando Material-UI e Firebase."
20 |
21 | }
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/pages/LandingPage/messages/pt.json:
--------------------------------------------------------------------------------
1 | {
2 | "intro": "React Starter-Kit com todos os recursos mais procurados ",
3 | "title": " REACT MOST WANTED ",
4 | "start": "GET STARTED",
5 | "instal": "Instalação",
6 | "run": "Execute esse script para iniciar:",
7 | "more": "Saiba mais",
8 | "usage": "Uso",
9 | "set": "Defina sua configuração para componente de aplicativo:",
10 | "what": "O que é isso?",
11 | "this": "Esse é uma aplicação de demonstração com código fonte aberto, que demonstra o uso da biblioteca rmw-shell com React, Material-UI e Firebase.",
12 | "demo": "Esta demonstração não tem nenhum propósito de realizar algo como um aplicativo. Ela está aqui só para demonstrar como tudo funciona junto.",
13 | "signin": "Entrar",
14 | "new_users": "Novos usuários",
15 | "companies": "Empresas",
16 | "try_it_out": "Experimentar",
17 | "about": "Sobre",
18 | "team": "Time",
19 | "about_text": "React Most Wanted é apenas uma aplicação de demonstração, não tente encontrar algo útil para fazer com ela. O foco aqui é somente o código e como construir aplicações React com Material-UI e Firebase."
20 | }
21 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/pages/LandingPage/messages/ru.json:
--------------------------------------------------------------------------------
1 | {
2 | "intro": "Стартовый Реакт со всеми наиболее востребованными функциями ",
3 | "title": "React самый популярный",
4 | "start": "Начать",
5 | "instal": "Установка",
6 | "run": "Просто запустите этот скрипт, чтобы начать:",
7 | "more": "Узнай Больше",
8 | "usage": "Использование",
9 | "set": "Установите конфигурацию для компонента приложения:",
10 | "what": "Что это такое?",
11 | "this": "Это демонстрационное приложение с открытым исходным кодом, которое демонстрирует использование библиотеки rmw-shell с react, Material-UI и firebase.",
12 | "demo": "Эта демонстрация не имеет цели сделать что-то в качестве приложения. Она здесь только для того, чтобы показать, как все работает вместе.",
13 | "companies": "Компании",
14 | "signin": "Вход",
15 | "new_users": "Новый Пользовател",
16 | "about": "О нас",
17 | "team": "Команда",
18 | "try_it_out": "Попробуйте",
19 | "about_text": "React самый популярный это всего лишь демонстрация приложения. Не пытайтесь сделать что-то полезное, с этой демонстрацией. Основное внимание здесь уделяется только коду и тому, как создавать приложения React с использованием Material-UI и Firebase."
20 | }
21 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/src/pages/PageNotFound/index.jsx:
--------------------------------------------------------------------------------
1 | import { Button, Paper, Typography } from "@mui/material";
2 | import { Home } from "@mui/icons-material";
3 | import { Page } from "@ecronix/material-ui-shell";
4 | import React from "react";
5 | import { useIntl } from "react-intl";
6 |
7 | export function NotFoundPage() {
8 | const intl = useIntl();
9 |
10 | return (
11 |
12 | t.palette.background.default,
15 | margin: 0,
16 | height: `calc(100vh - 64px)`,
17 | }}
18 | >
19 |
28 | 404
29 |
30 | {intl.formatMessage({ id: "page_not_found" }) + " MUI"}
31 |
32 |
40 |
41 |
42 |
43 | );
44 | }
45 |
--------------------------------------------------------------------------------
/packages/rmw-shell/create-rmw-shell/template/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import react from "@vitejs/plugin-react";
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/packages/rmw-shell/cypress.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "cypress";
2 |
3 | export default defineConfig({
4 | e2e: {
5 | setupNodeEvents(on, config) {
6 | // implement node event listeners here
7 | },
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/packages/rmw-shell/cypress/e2e/spec.cy.js:
--------------------------------------------------------------------------------
1 | describe("My React App", () => {
2 | beforeEach(() => {
3 | cy.visit("http://localhost:5173");
4 | });
5 |
6 | it("renders the app", () => {
7 | cy.get("#root").should("exist");
8 | });
9 |
10 | it('renders "app container top" text', () => {
11 | cy.contains("React Starter-Kit with all the Most Wanted features").should(
12 | "exist"
13 | );
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/packages/rmw-shell/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
6 |
--------------------------------------------------------------------------------
/packages/rmw-shell/cypress/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add('login', (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This will overwrite an existing command --
25 | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
--------------------------------------------------------------------------------
/packages/rmw-shell/cypress/support/e2e.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/e2e.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
--------------------------------------------------------------------------------
/packages/rmw-shell/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/components/FormFields/index.tsx:
--------------------------------------------------------------------------------
1 | import { Autocomplete } from "./Autocomplete";
2 | import { KeyboardDatePicker } from "./KeyboardDatePicker";
3 | import { TextField } from "./TextField";
4 | import { DatePicker } from "./DatePicker";
5 | import { AvatarImage } from "./AvatarImage";
6 |
7 | export { Autocomplete, KeyboardDatePicker, TextField, DatePicker, AvatarImage };
8 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/components/Forms/Role.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { TextField } from "mui-rff";
3 |
4 | export function FormsRole({ handleSubmit }: { handleSubmit: () => void }) {
5 | return (
6 |
32 | );
33 | }
34 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/components/Forms/index.tsx:
--------------------------------------------------------------------------------
1 | export * from "./Role.jsx";
2 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/components/Icons/FacebookIcon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import SvgIcon from "@mui/material/SvgIcon";
3 |
4 | const FacebookIcon = (props: any) => {
5 | return (
6 |
13 |
19 |
26 |
27 | );
28 | };
29 |
30 | export default FacebookIcon;
31 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/components/Icons/GitHubIcon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import SvgIcon from "@mui/material/SvgIcon";
3 |
4 | const GitHubIcon = (props: any) => {
5 | return (
6 |
7 |
12 |
13 | );
14 | };
15 |
16 | export default GitHubIcon;
17 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/components/Icons/GoogleIcon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import SvgIcon from "@mui/material/SvgIcon";
3 |
4 | const GoogleIcon = (props: any) => {
5 | return (
6 |
7 |
8 |
9 | );
10 | };
11 |
12 | export default GoogleIcon;
13 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/components/Icons/ReduxIcon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import SvgIcon from "@mui/material/SvgIcon";
3 |
4 | const GitHubIcon = (props: any) => {
5 | return (
6 |
7 |
12 |
17 |
22 |
23 | );
24 | };
25 |
26 | export default GitHubIcon;
27 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/components/Icons/TwitterIcon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import SvgIcon from "@mui/material/SvgIcon";
3 |
4 | const TwitterIcon = (props: any) => {
5 | return (
6 |
7 |
8 |
9 | );
10 | };
11 |
12 | export default TwitterIcon;
13 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/components/Icons/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as GitHubIcon } from "./GitHubIcon";
2 | export { default as ReduxIcon } from "./ReduxIcon";
3 | export { default as GoogleIcon } from "./GoogleIcon";
4 | export { default as TwitterIcon } from "./TwitterIcon";
5 | export { default as FacebookIcon } from "./FacebookIcon";
6 | export { default as RMWIcon } from "./RMWIcon";
7 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/components/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./ChatMessage";
2 | export * from "./FormFields";
3 | export * from "./Forms";
4 | export * from "./Icons";
5 | export * from "./SnackMessage";
6 | export * from "./UserRow";
7 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/containers/AuthUI/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useCallback } from "react";
2 | import { useIntl } from "react-intl";
3 | import * as firebaseui from "firebaseui";
4 | import { getAuth } from "firebase/auth";
5 |
6 | let authUi: firebaseui.auth.AuthUI | null = null;
7 |
8 | /*eslint-disable */
9 | export function AuthUIContainer({
10 | uiConfig,
11 | }: {
12 | uiConfig: firebaseui.auth.Config | null;
13 | }) {
14 | if (!uiConfig) {
15 | return null;
16 | }
17 |
18 | const intl = useIntl();
19 | const locale = intl.locale;
20 |
21 | const auth = getAuth();
22 |
23 | const initAuth = useCallback(async () => {
24 | try {
25 | if (!firebaseui.auth.AuthUI.getInstance()) {
26 | authUi = new firebaseui.auth.AuthUI(auth);
27 | } else {
28 | authUi = firebaseui.auth.AuthUI.getInstance();
29 | }
30 | } catch (err) {
31 | console.warn(err);
32 | }
33 |
34 | try {
35 | authUi?.start("#firebaseui-auth", uiConfig);
36 | } catch (error) {
37 | console.warn(error);
38 | }
39 | }, [locale]);
40 |
41 | useEffect(() => {
42 | initAuth();
43 |
44 | return () => {
45 | try {
46 | if (authUi) {
47 | authUi.reset();
48 | }
49 | } catch (err) {
50 | console.warn(err);
51 | }
52 | };
53 | }, [initAuth, authUi]);
54 |
55 | return (
56 |
59 | );
60 | }
61 |
62 | /*eslint-enable */
63 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/containers/Layout/index.tsx:
--------------------------------------------------------------------------------
1 | import { LayoutContainer as MaterialUiLayoutContainer } from "@ecronix/material-ui-shell";
2 | import { FirebaseContainer } from "@ecronix/rmw-shell";
3 | import React from "react";
4 |
5 | export function LayoutContainer({ children }: { children: React.ReactNode }) {
6 | return (
7 |
8 | {children}
9 |
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/containers/Page/MarkdownPage.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import ReactMarkdown from "react-markdown";
3 | import { Scrollbar, Page } from "@ecronix/material-ui-shell";
4 |
5 | const loadData = async (path: string): Promise => {
6 | const data = await fetch(path);
7 | const text = await data.text();
8 | return text;
9 | };
10 |
11 | type MarkdownProps = {
12 | path: string;
13 | pageProps: any;
14 | };
15 | // eslint-disable-next-lin
16 | export function MarkdownPageContainer({ path, pageProps }: MarkdownProps) {
17 | const [source, setSource] = useState(null);
18 |
19 | useEffect(() => {
20 | loadData(path).then((text) => {
21 | setSource(text);
22 | });
23 | }, [path]);
24 |
25 | return (
26 |
27 |
28 |
29 | {source && (
30 |
31 | )}
32 |
33 |
34 |
35 | );
36 | }
37 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/containers/Page/index.tsx:
--------------------------------------------------------------------------------
1 | export * from "./ListPage";
2 | export * from "./FormPage";
3 | export * from "./MarkdownPage";
4 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/containers/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./AuthUI";
2 | export * from "./Chat";
3 | export * from "./Chat/Input";
4 | export * from "./Firebase";
5 | export * from "./Firebase/From";
6 | export * from "./GrantsList";
7 | export * from "./ImageUploadDialog";
8 | export * from "./ImageViewer";
9 | export * from "./Layout";
10 | export * from "./Page";
11 | export * from "./ResponsiveMenu";
12 | export * from "./RolesList";
13 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Theme } from "@mui/material/styles";
2 |
3 | export * from "./providers";
4 | export * from "./pages";
5 | export * from "./utils";
6 | export * from "./containers";
7 | export * from "./components";
8 |
9 | declare module "@mui/styles/defaultTheme" {
10 | interface DefaultTheme extends Theme {}
11 | }
12 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/pages/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./Chats";
2 |
3 | export * from "./CreateChat";
4 |
5 | export * from "./EditAdmins";
6 |
7 | export * from "./EditMembers";
8 |
9 | export * from "./GroupChat";
10 |
11 | export * from "./MyAccount";
12 |
13 | export * from "./Roles";
14 | export * from "./Roles/Role";
15 |
16 | export * from "./SignIn";
17 |
18 | export * from "./Users";
19 | export * from "./Users/User";
20 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/providers/Firebase/Cols/Context.tsx:
--------------------------------------------------------------------------------
1 | import { CollectionReference, DocumentData } from "firebase/firestore";
2 | import React from "react";
3 |
4 | export type FirebaseColsContextType = {
5 | watchCol: (reference: string, alias: string) => void;
6 | unwatchCol: (
7 | reference: CollectionReference
8 | ) => void;
9 | getCol: (path: string) => void;
10 | clearCol: (reference: string) => void;
11 | clearAllCols: () => void;
12 | isColLoading: (path: string) => boolean;
13 | hasColError: (path: string) => void;
14 | getColError: (path: string) => void;
15 | };
16 | export const Context = React.createContext(
17 | undefined
18 | );
19 |
20 | export default Context;
21 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/providers/Firebase/Cols/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import Context from "./Context";
3 | import Provider from "./Provider";
4 |
5 | function useFirebaseCols() {
6 | const context = useContext(Context);
7 |
8 | if (context === undefined) {
9 | throw new Error(
10 | "useFirebaseCols must be used within a FirebaseColsContext"
11 | );
12 | }
13 | return context;
14 | }
15 |
16 | export {
17 | useFirebaseCols,
18 | Provider as FirebaseColsProvider,
19 | Context as FirebaseColsContext,
20 | };
21 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/providers/Firebase/Docs/Context.tsx:
--------------------------------------------------------------------------------
1 | import { DocumentData } from "firebase/firestore";
2 | import React from "react";
3 |
4 | export type DocsContextType = {
5 | watchDoc: (reference: string | string[], alias: string) => void;
6 | unwatchDoc: (reference: string) => void;
7 | getDoc: (path: string, defaultValue: string | DocumentData) => void;
8 | clearDoc: (reference: string) => void;
9 | clearAllDocs: () => void;
10 | isDocLoading: (path: string) => void;
11 | hasDocError: (path: string) => void;
12 | getDocError: (path: string) => void;
13 | };
14 | export const Context = React.createContext(
15 | undefined
16 | );
17 |
18 | export default Context;
19 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/providers/Firebase/Docs/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import Context from "./Context.js";
3 | import Provider from "./Provider.jsx";
4 |
5 | function useFirebaseDocs() {
6 | const context = useContext(Context);
7 |
8 | if (context === undefined) {
9 | throw new Error(
10 | "useFirebaseDocs must be used within a FirebaseDocsContext"
11 | );
12 | }
13 | return context;
14 | }
15 |
16 | export {
17 | useFirebaseDocs,
18 | Provider as FirebaseDocsProvider,
19 | Context as FirebaseDocsContext,
20 | };
21 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/providers/Firebase/Lists/Context.tsx:
--------------------------------------------------------------------------------
1 | import { DatabaseReference, Query } from "firebase/database";
2 | import React from "react";
3 | export type ListsContextType = {
4 | watchList: (
5 | reference: string | DatabaseReference | Query,
6 | alias?: string
7 | ) => void;
8 | unwatchList: (reference: string) => void;
9 | getList: (path: string) => any[];
10 | clearList: (reference: string) => void;
11 | clearAllLists: () => void;
12 | isListLoading: (path: string) => void;
13 | hasListError: (path: string) => void;
14 | getListError: (path: string) => void;
15 | };
16 | export const Context = React.createContext(
17 | undefined
18 | );
19 |
20 | export default Context;
21 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/providers/Firebase/Lists/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import Context from "./Context";
3 | import Provider from "./Provider";
4 |
5 | function useFirebaseLists() {
6 | const context = useContext(Context);
7 |
8 | if (context === undefined) {
9 | throw new Error(
10 | "useFirebaseLists must be used within a FirebaseListsContext"
11 | );
12 | }
13 | return context;
14 | }
15 |
16 | export {
17 | useFirebaseLists,
18 | Provider as FirebaseListsProvider,
19 | Context as FirebaseListsContext,
20 | };
21 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/providers/Firebase/Messaging/Context.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | export type ListsContextType = {
3 | requestPermission: (p?: { onDismiss: () => void }) => void;
4 | token: string | null;
5 | };
6 | export const Context = React.createContext(
7 | undefined
8 | );
9 |
10 | export default Context;
11 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/providers/Firebase/Messaging/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import Context from "./Context";
3 | import Provider from "./Provider";
4 |
5 | function useFirebaseMessaging() {
6 | const context = useContext(Context);
7 |
8 | if (context === undefined) {
9 | throw new Error(
10 | "useFirebaseMessaging must be used within a FirebaseMessagingContext"
11 | );
12 | }
13 | return context;
14 | }
15 |
16 | export {
17 | useFirebaseMessaging,
18 | Provider as FirebaseMessagingProvider,
19 | Context as FirebaseMessagingContext,
20 | };
21 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/providers/Firebase/Paths/Context.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | export type PathsContextType = {
3 | watchPath: (
4 | path: string,
5 | onChange?: (data: Object | string | number | boolean | null) => void
6 | ) => any;
7 | unwatchPath: (path: string) => void;
8 | getPath: (path: string, defaultValue?: any) => any;
9 | clearPath: (path: string) => void;
10 | clearAllPaths: () => void;
11 | isPathLoading: (path: string) => void;
12 | hasPathError: (path: string) => void;
13 | getPathError: (path: string) => void;
14 | };
15 | export const Context = React.createContext(
16 | undefined
17 | );
18 |
19 | export default Context;
20 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/providers/Firebase/Paths/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import Context from "./Context";
3 | import Provider from "./Provider";
4 |
5 | function useFirebasePaths() {
6 | const context = useContext(Context);
7 |
8 | if (context === undefined) {
9 | throw new Error(
10 | "useFirebasePaths must be used within a FirebasePathsContext"
11 | );
12 | }
13 | return context;
14 | }
15 |
16 | export {
17 | useFirebasePaths,
18 | Provider as FirebasePathsProvider,
19 | Context as FirebasePathsContext,
20 | };
21 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/providers/Firebase/Storage/Context.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | StringFormat,
3 | UploadMetadata,
4 | UploadResult,
5 | UploadTask,
6 | UploadTaskSnapshot,
7 | } from "firebase/storage";
8 | import React from "react";
9 |
10 | export type OnUploadedType = (
11 | downloadURL: string,
12 | snapshot: UploadTaskSnapshot | UploadResult
13 | ) => void;
14 |
15 | export type StorageContextType = {
16 | uploadFile: (
17 | alias: string,
18 | path: string,
19 | file: Blob | Uint8Array | ArrayBuffer,
20 | metadata: UploadMetadata,
21 | onUploaded: OnUploadedType
22 | ) => void;
23 | uploadString: (
24 | alias: string,
25 | path: string,
26 | string: string,
27 | type: StringFormat,
28 | metadata: UploadMetadata,
29 | onUploaded: OnUploadedType
30 | ) => void;
31 | uploadTask: (
32 | alias: string,
33 | uploadTask: UploadTask,
34 | onUploaded: OnUploadedType
35 | ) => void;
36 | isUploading: (path: string) => boolean;
37 | getDownloadURL: (path: string) => string | null;
38 | clearUpload: (path: string) => void;
39 | clearAllUploads: () => void;
40 | hasUploadError: (path: string) => boolean;
41 | getUploadError: (path: string) => string | Error;
42 | getUploadProgress: (path: string) => number;
43 | };
44 | export const Context = React.createContext(
45 | undefined
46 | );
47 |
48 | export default Context;
49 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/providers/Firebase/Storage/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import Context from "./Context.js";
3 | import Provider from "./Provider.jsx";
4 |
5 | function useFirebaseStorage() {
6 | const context = useContext(Context);
7 |
8 | if (context === undefined) {
9 | throw new Error(
10 | "useFirebaseStorage must be used within a FirebaseStorageContext"
11 | );
12 | }
13 | return context;
14 | }
15 |
16 | export {
17 | useFirebaseStorage,
18 | Provider as FirebaseStorageProvider,
19 | Context as FirebaseStorageContext,
20 | };
21 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/providers/index.ts:
--------------------------------------------------------------------------------
1 | import { DocumentData } from "firebase/firestore";
2 |
3 | export * from "./Firebase/Cols";
4 | export * from "./Firebase/Lists";
5 | export * from "./Firebase/Storage";
6 | export * from "./Firebase/Messaging";
7 | export * from "./Firebase/Docs";
8 | export * from "./Firebase/Paths";
9 | export type ActionTypeBase = {
10 | payload?: any;
11 | value?: string | DocumentData;
12 | isLoading?: boolean;
13 | error?: Error;
14 | hasError?: boolean;
15 | path: string;
16 | };
17 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./auth";
2 | export * from "./locale";
3 | export * from "./location";
4 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/utils/locale.tsx:
--------------------------------------------------------------------------------
1 | const getUsersPreferredLanguages = () => {
2 | if (navigator.languages !== undefined) {
3 | return navigator.languages;
4 | } else if (navigator.language !== undefined) {
5 | return [navigator.language];
6 | } else {
7 | return undefined;
8 | }
9 | };
10 |
11 | const parseLanguages = (acceptedLangs: string, defaultLang = false) => {
12 | const userPref = getUsersPreferredLanguages();
13 |
14 | const match = userPref
15 | ? userPref.find((lang) => acceptedLangs.includes(lang))
16 | : undefined;
17 |
18 | if (match === undefined && defaultLang !== false) {
19 | return defaultLang;
20 | }
21 |
22 | return match;
23 | };
24 |
25 | const formatMessage = (messages = [], id: number) => {
26 | return messages[id] || id;
27 | };
28 |
29 | export { formatMessage, parseLanguages };
30 |
--------------------------------------------------------------------------------
/packages/rmw-shell/src/utils/location.tsx:
--------------------------------------------------------------------------------
1 | export const getGeocodeAddress = (
2 | address: any,
3 | onSuccess: (data: any, results: any, status: any) => void,
4 | onError: (status: any) => void
5 | ) => {
6 | //@ts-ignore
7 | let geocoder = new window.google.maps.Geocoder();
8 | geocoder.geocode({ address }, (results: any[], status: string) => {
9 | if (status === "OK" && onSuccess && onSuccess instanceof Function) {
10 | onSuccess(
11 | {
12 | lat: results[0].geometry.location.lat(),
13 | lng: results[0].geometry.location.lng(),
14 | },
15 | results,
16 | status
17 | );
18 | } else {
19 | if (onError && onError instanceof Function) {
20 | onError(status);
21 | }
22 | }
23 | });
24 | };
25 |
26 | export const getLocation = (
27 | config?: PositionOptions
28 | ): Promise<{ coords: { latitude: number; longitude: number } }> => {
29 | return new Promise((resolve, reject) => {
30 | navigator.geolocation.getCurrentPosition(resolve, reject, {
31 | enableHighAccuracy: true,
32 | timeout: 5000,
33 | maximumAge: 3000,
34 | ...config,
35 | });
36 | });
37 | };
38 |
--------------------------------------------------------------------------------
/packages/rmw-shell/tests/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "mocha": true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/packages/rmw-shell/tests/index.test.js:
--------------------------------------------------------------------------------
1 | import expect from 'expect'
2 | import React from 'react'
3 | import {render, unmountComponentAtNode} from 'react-dom'
4 |
5 | import Component from 'src/'
6 |
7 | describe('Component', () => {
8 | let node
9 |
10 | beforeEach(() => {
11 | node = document.createElement('div')
12 | })
13 |
14 | afterEach(() => {
15 | unmountComponentAtNode(node)
16 | })
17 |
18 | it('displays a welcome message', () => {
19 | render(, node, () => {
20 | expect(node.innerHTML).toContain('Welcome to React components')
21 | })
22 | })
23 | })
24 |
--------------------------------------------------------------------------------
/packages/rmw-shell/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../base-tsconfig.json",
3 | "compilerOptions": {
4 | "paths": {
5 | "@ecronix/rmw-shell": ["./src"],
6 | "@ecronix/rmw-shell/*": ["./src/*"]
7 | },
8 | "declarationDir": "./dist/types"
9 | },
10 | "include": ["src/**/*"],
11 | "exclude": ["node_modules"]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/rmw-shell/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import path from "path";
4 | import { visualizer } from "rollup-plugin-visualizer";
5 | import { externalizeDeps } from "vite-plugin-externalize-deps";
6 |
7 | // https://vitejs.dev/config/
8 | export default defineConfig({
9 | plugins: [
10 | react(),
11 | visualizer(),
12 | externalizeDeps({
13 | devDeps: true,
14 | }),
15 | ],
16 | resolve: {
17 | alias: {
18 | "@ecronix/rmw-shell": path.resolve(__dirname, "src"),
19 | },
20 | extensions: ['.js', '.ts', '.jsx', '.tsx'],
21 | },
22 | build: {
23 | minify: false,
24 | lib: {
25 | entry: path.resolve(__dirname, "src/index.ts"),
26 | name: "rmw-shell",
27 | formats: ["es"],
28 | },
29 | },
30 | });
31 |
--------------------------------------------------------------------------------