Browse Source

Merge branch 'master' of github.com:nocodb/nocodb

pull/559/head
Pranav C 3 years ago
parent
commit
04113d4f5e
  1. 47
      README.md
  2. 5
      cypress.json
  3. 93
      cypress/integration/common/_pre_configurations.js
  4. 157
      cypress/integration/common/share_view.js
  5. 51
      cypress/integration/ncTest.spec.js
  6. 57
      cypress/integration/user_role_spec.js
  7. 15
      cypress/support/commands.js
  8. 69
      cypress/support/page_objects/mainPage.js
  9. 35
      cypress/support/page_objects/navigation.js
  10. 65
      cypress/support/page_objects/projectConstants.js
  11. 27
      markdown/launch/brand-migration.md
  12. 91
      markdown/launch/ph.md
  13. 33
      markdown/plugins/google-auth.md
  14. 29
      markdown/plugins/s3.md
  15. 202
      packages/nc-gui/components/project/spreadsheet/components/spreadsheetNavDrawer.vue
  16. 38
      packages/nc-gui/layouts/default.vue
  17. 27
      packages/nc-gui/package-lock.json
  18. 12
      packages/nc-gui/store/users.js
  19. 23
      packages/noco-docs/content/en/developer-resources/api-tokens.md
  20. 13
      packages/noco-docs/content/en/developer-resources/webhooks.md
  21. 32
      packages/noco-docs/content/en/getting-started/installation.md
  22. 3611
      packages/nocodb/package-lock.json
  23. BIN
      static/google-oauth/1.png
  24. BIN
      static/google-oauth/10.png
  25. BIN
      static/google-oauth/2.png
  26. BIN
      static/google-oauth/3.png
  27. BIN
      static/google-oauth/4.png
  28. BIN
      static/google-oauth/5.png
  29. BIN
      static/google-oauth/6.png
  30. BIN
      static/google-oauth/7.png
  31. BIN
      static/google-oauth/8.png
  32. BIN
      static/google-oauth/9.png
  33. BIN
      static/nocodb/1.png
  34. BIN
      static/nocodb/10.png
  35. BIN
      static/nocodb/11.png
  36. BIN
      static/nocodb/2.png
  37. BIN
      static/nocodb/3.png
  38. BIN
      static/nocodb/4.png
  39. BIN
      static/nocodb/5.png
  40. BIN
      static/nocodb/6.png
  41. BIN
      static/nocodb/7.png
  42. BIN
      static/nocodb/8.png
  43. BIN
      static/nocodb/9.png
  44. BIN
      static/open-source-airtable-alternative/OpenSourceAirtableAlternative-old.png
  45. BIN
      static/open-source-airtable-alternative/OpenSourceAirtableAlternative.gif
  46. BIN
      static/open-source-airtable-alternative/OpenSourceAirtableAlternative.png
  47. BIN
      static/s3/1.png
  48. BIN
      static/s3/2.png
  49. BIN
      static/s3/3.png
  50. BIN
      static/s3/4.png
  51. BIN
      static/s3/5.png
  52. BIN
      static/s3/6.png
  53. BIN
      static/s3/7.png
  54. BIN
      static/s3/8.png
  55. BIN
      static/s3/9.png
  56. BIN
      static/screenshots/googleoauth/1.png
  57. BIN
      static/screenshots/googleoauth/10.png
  58. BIN
      static/screenshots/googleoauth/2.png
  59. BIN
      static/screenshots/googleoauth/3.png
  60. BIN
      static/screenshots/googleoauth/4.png
  61. BIN
      static/screenshots/googleoauth/5.png
  62. BIN
      static/screenshots/googleoauth/6.png
  63. BIN
      static/screenshots/googleoauth/7.png
  64. BIN
      static/screenshots/googleoauth/8.png
  65. BIN
      static/screenshots/googleoauth/9.png
  66. BIN
      static/screenshots/s3/Screenshot 2021-03-18 at 3.00.10 PM.png
  67. BIN
      static/screenshots/s3/Screenshot 2021-03-18 at 3.12.57 PM.png
  68. BIN
      static/screenshots/s3/Screenshot 2021-03-18 at 3.13.17 PM.png
  69. BIN
      static/screenshots/s3/Screenshot 2021-03-18 at 3.14.12 PM.png
  70. BIN
      static/screenshots/s3/Screenshot 2021-03-18 at 3.23.48 PM.png
  71. BIN
      static/screenshots/s3/Screenshot 2021-03-18 at 3.24.13 PM.png
  72. BIN
      static/screenshots/s3/Screenshot 2021-03-18 at 3.24.26 PM.png
  73. BIN
      static/screenshots/s3/Screenshot 2021-03-18 at 3.24.43 PM.png
  74. BIN
      static/screenshots/s3/Screenshot 2021-03-18 at 3.26.34 PM.png
  75. BIN
      static/screenshots/s3/Screenshot 2021-03-18 at 3.26.54 PM.png

47
README.md

@ -22,15 +22,13 @@ Turns any MySQL, PostgreSQL, SQL Server, SQLite & MariaDB into a smart-spreadshe
<a href="https://twitter.com/nocodb"><b>Twitter</b></a>
</p>
<p align="center">
<img src="static/open-source-airtable-alternative/OpenSourceAirtableAlternative.png" width="100%">
<br/><br/>
</p>
![OpenSourceAirtableAlternative](https://user-images.githubusercontent.com/5435402/133762127-e94da292-a1c3-4458-b09a-02cd5b57be53.png)
<img src="https://static.scarf.sh/a.png?x-pxid=c12a77cc-855e-4602-8a0f-614b2d0da56a" />
<a href="https://www.producthunt.com/posts/nocodb?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-nocodb" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=297536&theme=dark" alt="NocoDB - The Open Source Airtable alternative | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
# Quick try
### 1-Click Deploy
@ -78,29 +76,43 @@ Access Dashboard using : [http://localhost:8080/dashboard](http://localhost:8080
<br>
# Screenshots
<img src="static/nocodb/2.png"/>
<br>
<img src="static/nocodb/1.png"/>
![2](https://user-images.githubusercontent.com/5435402/133759229-4275b934-873b-4a9b-9f23-96470fec9775.png)
<br>
<img src="static/nocodb/7.png"/>
![1](https://user-images.githubusercontent.com/5435402/133759218-f8b0bffc-707f-451c-82f2-b5ba2573d6a6.png)
<br>
<img src="static/nocodb/5.png"/>
![7](https://user-images.githubusercontent.com/5435402/133759245-a536165b-55f1-46a8-a74e-1964e7e481c6.png)
<br>
<img src="static/nocodb/6.png"/>
![5](https://user-images.githubusercontent.com/5435402/133759240-dd3f2509-aab7-4bd1-9a58-4c2dff08f2f2.png)
<br>
<img src="static/nocodb/3.png"/>
![6](https://user-images.githubusercontent.com/5435402/133759242-2311a127-17c8-406c-b865-1a2e9c8ee398.png)
<br>
<img src="static/nocodb/4.png"/>
![3](https://user-images.githubusercontent.com/5435402/133759234-9b539029-be36-4a35-b55a-bee3ebd0e010.png)
<br>
<img src="static/nocodb/11.png"/>
![4](https://user-images.githubusercontent.com/5435402/133759236-dc182129-3768-4e23-874e-98f5f32e962c.png)
<br>
<img src="static/nocodb/10.png"/>
![11](https://user-images.githubusercontent.com/5435402/133759253-bb9bc729-ee28-4f86-ab95-7d112c0815f2.png)
<br>
<img src="static/nocodb/8.png"/>
![10](https://user-images.githubusercontent.com/5435402/133759250-ebd75ecf-31db-4a17-b2d7-2c43af78a54e.png)
<br>
<img src="static/nocodb/9.png"/>
![8](https://user-images.githubusercontent.com/5435402/133759248-3a7141e0-4b7d-4079-a5f9-cf8611d00bc5.png)
<br>
![9](https://user-images.githubusercontent.com/5435402/133759249-8c1a85c2-a55c-48f6-bd58-aa6b4195cce7.png)
@ -291,3 +303,6 @@ Our mission is to provide the most powerful no-code interface for databases whic
<!-- ALL-CONTRIBUTORS-LIST:END -->

5
cypress.json

@ -1,10 +1,11 @@
{
"baseUrl": "http://localhost:3000",
"baseUrl": "http://localhost:3000/",
"defaultCommandTimeout": 13000,
"pageLoadTimeout": 600000,
"viewportWidth": 1980,
"viewportHeight": 1000,
"video": false,
"retries": 2,
"screenshotOnRunFailure": false
"screenshotOnRunFailure": false,
"numTestsKeptInMemory": 5
}

93
cypress/integration/common/_pre_configurations.js

@ -0,0 +1,93 @@
// Cypress test suite: project pre-configurations
//
import { loginPage, projectsPage } from "../../support/page_objects/navigation"
import { mainPage } from "../../support/page_objects/mainpage"
import { staticProjects, roles } from "../../support/page_objects/projectConstants"
describe(`Project pre-configurations`, () => {
it('Admin SignUp', ()=> {
cy.waitForSpinners();
cy.signinOrSignup(roles.owner.credentials)
cy.wait(2000)
})
const createProject = (proj) => {
it(`Create ${proj.basic.name} project`, () => {
// click home button
mainPage.toolBarTopLeft(mainPage.HOME).click()
// create requested project
projectsPage.createProject( proj.basic, proj.config )
})
}
createProject(staticProjects.sampleREST)
createProject(staticProjects.sampleGQL)
createProject(staticProjects.externalREST)
createProject(staticProjects.externalGQL)
})
describe('Static user creations (different roles)', () => {
beforeEach(()=> {
loginPage.signIn(roles.owner.credentials)
projectsPage.openProject(staticProjects.sampleREST.basic.name)
})
const addUser = (user) => {
it(`RoleType: ${user.name}`, () => {
mainPage.addNewUserToProject(user.credentials, user.name)
})
}
addUser(roles.creator)
addUser(roles.editor)
addUser(roles.commenter)
addUser(roles.viewer)
})
describe('Static users- add to other static projects', () => {
const addUserToProject = (proj) => {
it(`Add users to ${proj.basic.name}`, () => {
loginPage.signIn(roles.owner.credentials)
projectsPage.openProject(proj.basic.name)
mainPage.addExistingUserToProject(roles.creator.credentials.username, roles.creator.name)
mainPage.addExistingUserToProject(roles.editor.credentials.username, roles.editor.name)
mainPage.addExistingUserToProject(roles.commenter.credentials.username, roles.commenter.name)
mainPage.addExistingUserToProject(roles.viewer.credentials.username, roles.viewer.name)
})
}
addUserToProject(staticProjects.sampleGQL)
addUserToProject(staticProjects.externalREST)
addUserToProject(staticProjects.externalGQL)
})
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Raju Udava <sivadstala@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

157
cypress/integration/common/share_view.js

@ -0,0 +1,157 @@
import { loginPage, projectsPage } from "../../support/page_objects/navigation"
const shareViewWithPwd = (pwdCorrect, pwd) => {
cy.get('.v-navigation-drawer__content > .container')
.find('.v-list > .v-list-item')
.contains('Share View')
.click()
// No password- unprotected link
if(''==pwd) {
// copy link text, visit URL
cy.getActiveModal().find('.share-link-box')
.contains('http', {timeout: 2000})
.then(($obj) => {
let linkText = $obj.text()
cy.log(linkText)
cy.visit(linkText)
// wait for share view page to load!
cy.wait(5000)
cy.get('body').find('.v-dialog.v-dialog--active').should('not.exist')
})
// password protected link
} else {
// enable checkbox & feed pwd, save
cy.getActiveModal().find('[role="switch"][type="checkbox"]').click( {force: true} )
cy.getActiveModal().find('input[type="password"]').type('123456')
cy.getActiveModal().find('button:contains("Save password")').click()
// copy link text, visit URL
cy.getActiveModal().find('.share-link-box')
.then(($obj) => {
let linkText = $obj.text()
cy.log(linkText)
cy.visit(linkText)
// wait for share view page to load!
cy.wait(5000)
// feed password
cy.getActiveModal().find('input[type="password"]').type(pwd)
cy.getActiveModal().find('button:contains("Unlock")').click()
cy.wait(1000)
// if pwd is incorrect, active modal requesting to feed in password again
// will remain
if(pwdCorrect) {
cy.get('body').find('.v-dialog.v-dialog--active').should('not.exist')
}
else {
cy.get('body').find('.v-dialog.v-dialog--active').should('exist')
}
})
}
}
// delete created views
//
const deleteCreatedViews = () => {
cy.get('.v-navigation-drawer__content > .container')
.find('.v-list > .v-list-item')
.contains('Share View')
.parent().find('button.mdi-dots-vertical').click()
cy.getActiveMenu().find('.v-list-item').contains('Views List').click()
cy.get(1000)
cy.get('th:contains("View Link")').parent().parent()
.next().find('tr').each((tableRow) => {
cy.wrap(tableRow).find('button').last().click()
cy.wait(1000)
})
}
const genTest = (type) => {
describe(`${type.toUpperCase()} api - Clipboard access`, () => {
let projectName
// create project with default credentials to work with
//
before( () => {
loginPage.signIn({ username: 'user@nocodb.com', password: 'Password123.' })
if(type == 'rest')
projectName = projectsPage.createDefaulRestProject()
else
projectName = projectsPage.createDefaultGraphQlProject()
})
// Run once before test- create project (rest/graphql)
//
beforeEach(() => {
loginPage.signIn({ username: 'user@nocodb.com', password: 'Password123.' })
projectsPage.openProject(projectName)
cy.openTableTab('City');
})
it('Share view without password', () => {
shareViewWithPwd(true, '')
})
it('Share view with correct password', () => {
shareViewWithPwd(true, '123456')
})
it('Share view with incorrect password', () => {
shareViewWithPwd(false, 'abc')
})
it('Delete view', deleteCreatedViews )
// clean up
after( () => {
loginPage.signIn({ username: 'user@nocodb.com', password: 'Password123.' })
projectsPage.deleteProject(projectName)
})
})
}
genTest('rest')
genTest('graphql')
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Pranav C Balan <pranavxc@gmail.com>
* @author Raju Udava <sivadstala@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

51
cypress/integration/ncTest.spec.js

@ -1,10 +1,3 @@
/**
* file: ncTest.Spec.js
* purpose: test-suite-1
* author: raju udava
* date: 06 Sep 2020
*
**/
import { loginPage, projectsPage } from "../support/page_objects/navigation"
@ -45,9 +38,53 @@ describe('Login & project page', () => {
projectsPage.deleteProject(projectName)
})
it('3. Create project: NC_DB_EXTERNAL, NC_REST', () => {
const projectParams = { dbType: 1, apiType: 1, name: 'externalREST' }
const databaseParams = {
databaseType: 0,
hostAddress: 'localhost',
portNumber: '3306',
username: 'root',
password: 'password',
databaseName: 'sakila'
}
projectName = projectsPage.createProject(projectParams, databaseParams)
})
it('3a. Delete project: NC_DB_EXTERNAL, NC_REST', () => {
projectsPage.deleteProject(projectName)
})
// Needs to be conditionally triggered if required
//
// it('N. Clean up: Delete call projects', () => {
// projectsPage.deleteAllProject()
// })
})
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Raju Udava <sivadstala@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

57
cypress/integration/user_role_spec.js

@ -38,63 +38,6 @@ const roles = {
}
// add new user to specified role
//
const addUser = (userCred, role) => {
let linkText
// click on New User button, feed details
cy.get('button:contains("New User")').first().click()
cy.get('label:contains(Email)').next('input').type(userCred.username).trigger('input')
cy.get('label:contains(Select User roles)').click()
// opt-in requested role & submit
// note that, 'editor' is set by default
//
cy.getActiveMenu().contains(role).click()
cy.getActiveMenu().contains('editor').click()
cy.get('.mdi-menu-down').click()
cy.get('.nc-invite-or-save-btn').click()
// get URL, invoke
cy.getActiveModal().find('.v-alert').then(($obj) => {
linkText = $obj.text()
cy.log(linkText)
cy.visit(linkText)
})
// SignUp is taken care under userRoleCreation()
// wait for some time to ensure screen is loaded
//
cy.wait(2000)
}
const userRoleCreation = (roleType) => {
it(`User creation: ${roleType}`, () => {
loginPage.signIn(roles.owner.credentials)
projectsPage.openProject('sakilaDb')
// Team & Auth tab is open by default
//
addUser(roles[roleType].credentials, roleType)
// Redirected to new URL, feed details
//
cy.get('input[type="text"]').type(roles[roleType].credentials.username)
cy.get('input[type="password"]').type(roles[roleType].credentials.password)
cy.get('button:contains("SIGN UP")').click()
cy.url({ timeout: 6000 }).should('contain', '#/project')
cy.wait(1000)
projectsPage.openProject('sakilaDb')
})
}
describe('Test project creation, user creation', () => {
let projectName = ''

15
cypress/support/commands.js

@ -37,7 +37,10 @@ Cypress.Commands.add('waitForSpinners', () => {
})
cy.get('#nuxt-loading', {timeout: 10_0000}).should('have.length', 0)
})
Cypress.Commands.add('signinOrSignup', () => {
Cypress.Commands.add('signinOrSignup', (_args) => {
const args = Object.assign({username: 'user@nocodb.com', password: 'Password123.'}, _args)
// signin/signup
cy.get('body').then(($body) => {
@ -49,21 +52,21 @@ Cypress.Commands.add('signinOrSignup', () => {
cy.wait(8000);
cy.get('body').trigger('mousemove');
cy.contains('Let\'s Begin').click();
cy.get('input[type="text"]', {timeout: 12000}).type('user@nocodb.com');
cy.get('input[type="password"]').type('Password123.');
cy.get('input[type="text"]', { timeout: 12000 }).type(args.username);
cy.get('input[type="password"]').type(args.password);
cy.get('button:contains("SIGN UP")').click()
// handle signin
} else {
cy.get('input[type="text"]').type('user@nocodb.com');
cy.get('input[type="password"]').type('Password123.');
cy.get('input[type="text"]', { timeout: 12000 }).type(args.username);
cy.get('input[type="password"]').type(args.password);
cy.get('button:contains("SIGN IN")').click()
}
}
})
})
});
// for opening/creating a rest project
Cypress.Commands.add('openOrCreateRestProject', (_args) => {
const args = Object.assign({new: false}, _args)

69
cypress/support/page_objects/mainPage.js

@ -26,18 +26,11 @@ export class _mainPage {
}
toolBarTopLeft(toolBarItem) {
cy.get('header.v-toolbar').eq(0).find('a').then((obj) => {
cy.wrap(obj).eq(toolBarItem).click()
})
return cy.get('header.v-toolbar').eq(0).find('a').eq(toolBarItem)
}
toolBarTopRight(toolBarItem) {
cy.get('header.v-toolbar').eq(0).find('button').then((obj) => {
cy.wrap(obj).eq(toolBarItem).click()
cy.wait(500)
})
return cy.get('header.v-toolbar').eq(0).find('button').eq(toolBarItem)
}
@ -47,6 +40,64 @@ export class _mainPage {
else
return cy.get('.nc-nav-drawer').find('.v-list > .v-list-item').eq(item)
}
// add new user to specified role
//
addNewUserToProject = (userCred, roleType) => {
let linkText
// click on New User button, feed details
cy.get('button:contains("New User")').first().click()
cy.get('label:contains("Email")').next('input').type(userCred.username).trigger('input')
cy.get('label:contains("Select User roles")').click()
// opt-in requested role & submit
// note that, 'editor' is set by default
//
cy.getActiveMenu().contains(roleType).click()
cy.getActiveMenu().contains('editor').click()
cy.get('.mdi-menu-down').click()
cy.get('.nc-invite-or-save-btn').click()
// get URL, invoke
cy.getActiveModal().find('.v-alert').then(($obj) => {
linkText = $obj.text()
cy.log(linkText)
cy.visit(linkText)
cy.wait(3000)
// Redirected to new URL, feed details
//
cy.get('input[type="text"]').type(userCred.username)
cy.get('input[type="password"]').type(userCred.password)
cy.get('button:contains("SIGN UP")').click()
cy.url({ timeout: 6000 }).should('contain', '#/project')
cy.wait(1000)
})
}
addExistingUserToProject = (emailId, role) => {
cy.get('.v-list-item:contains("Team & Auth")').click()
cy.get(`tr:contains(${emailId})`).find('.mdi-plus', {timeout: 2000}).click()
cy.get(`tr:contains(${emailId})`).find('.mdi-pencil-outline', {timeout: 2000}).click()
cy.get('label:contains(Select User roles)').click()
// opt-in requested role & submit
// note that, 'editor' is set by default
//
cy.getActiveMenu().contains(role).click()
cy.getActiveMenu().contains('editor').click()
cy.get('.mdi-menu-down').click()
cy.get('.nc-invite-or-save-btn').click()
cy.wait(1000)
}
}

35
cypress/support/page_objects/navigation.js

@ -1,3 +1,6 @@
import { defaultDbParams } from "./projectConstants"
///////////////////////////////////////////////////////////
// Sign in/ Sign up page
@ -23,7 +26,7 @@ export class _loginPage {
signIn(userCredentials) {
this.go(urlPool.ncUrlSignIn)
cy.get('input[type="text"]').type(userCredentials.username)
cy.get('input[type="text"]', {timeout: 6000}).type(userCredentials.username)
cy.get('input[type="password"]').type(userCredentials.password)
cy.get('button:contains("SIGN IN")').click()
@ -35,7 +38,7 @@ export class _loginPage {
signUp(userCredentials) {
this.go(urlPool.ncUrlSignUp)
cy.get('input[type="text"]').type(userCredentials.username)
cy.get('input[type="text"]', {timeout: 6000}).type(userCredentials.username)
cy.get('input[type="password"]').type(userCredentials.password)
cy.get('button:contains("SIGN UP")').click()
@ -54,15 +57,6 @@ export class _loginPage {
///////////////////////////////////////////////////////////
// Projects page
// DB type
const NC_DB_NONE = 0
const NC_DB_EXISTING = 1
// API type
const NC_REST = 0
const NC_GQL = 1
export class _projectsPage {
// Project creation options
@ -103,7 +97,7 @@ export class _projectsPage {
// click on "New Project"
cy.get(':nth-child(5) > .v-btn').click()
if (NC_DB_NONE == projectData.dbType) {
if ('none' == projectData.dbType) {
// Subsequent form, select (+ Create) option
cy.get('.nc-create-xc-db-project').click({ force: true })
@ -112,7 +106,7 @@ export class _projectsPage {
cy.get('.nc-metadb-project-name').type(projectName)
// Radio button: defaults to NC_REST
if (NC_GQL == projectData.apiType) {
if ('GQL' == projectData.apiType) {
cy.contains('GRAPHQL APIs').closest('label').click();
}
@ -124,6 +118,8 @@ export class _projectsPage {
return projectName
}
// dbType == 'external'
else {
// Subsequent form, select (+ Create by connection to external database) option
@ -134,7 +130,7 @@ export class _projectsPage {
cy.contains('Enter Project Name').parent().find('input').clear().type(projectName)
// Radio button: defaults to NC_REST
if (NC_GQL == projectData.apiType) {
if ('GQL' == projectData.apiType) {
cy.contains('GRAPHQL APIs').closest('label').click();
}
@ -162,6 +158,17 @@ export class _projectsPage {
}
}
// create REST default project (sakila DB)
//
createDefaulRestProject() {
return this.createProject({ dbType: 1, apiType: 0, name: '' }, defaultDbParams )
}
// create GraphQL default project (sakila DB)
//
createDefaultGraphQlProject() {
return this.createProject({ dbType: 1, apiType: 1, name: '' }, defaultDbParams )
}
// Click on refresh key on projects page
//

65
cypress/support/page_objects/projectConstants.js

@ -0,0 +1,65 @@
export const defaultDbParams = {
databaseType: 0, // MySQL
hostAddress: 'localhost',
portNumber: '3306',
username: 'root',
password: 'password',
databaseName: 'sakila'
}
// database
// validation details
// advSettings: left navigation bar (audit, metadata, auth, transient view modes)
// editSchema: create table, add/update/delete column
// editData: add/ update/ delete row, cell contents
// editComment: add comment
// shareView: right navigation bar (share options)
export const roles = {
owner: {
name: 'owner',
credentials: { username: 'user@nocodb.com', password: 'Password123.' },
validations: { advSettings: true, editSchema: true, editData: true, editComment: true, shareView: true }
},
creator: {
name: 'creator',
credentials: { username: 'creator@nocodb.com', password: 'Password123.' },
validations: { advSettings: true, editSchema: true, editData: true, editComment: true, shareView: true }
},
editor: {
name: 'editor',
credentials: { username: 'editor@nocodb.com', password: 'Password123.' },
validations: { advSettings: false, editSchema: false, editData: true, editComment: true, shareView: false }
},
commenter: {
name: 'commenter',
credentials: { username: 'commenter@nocodb.com', password: 'Password123.' },
validations: { advSettings: false, editSchema: false, editData: false, editComment: true, shareView: false }
},
viewer: {
name: 'viewer',
credentials: { username: 'viewer@nocodb.com', password: 'Password123.' },
validations: { advSettings: false, editSchema: false, editData: false, editComment: false, shareView: false }
}
}
// default projects
//
export const staticProjects = {
sampleREST: {
basic: { dbType: 'none', apiType: 'REST', name: 'sampleREST' },
config: {}
},
sampleGQL: {
basic: { dbType: 'none', apiType: 'GQL', name: 'sampleGQL' },
config: {}
},
externalREST: {
basic: { dbType: 'external', apiType: 'REST', name: 'externalREST' },
config: defaultDbParams
},
externalGQL: {
basic: { dbType: 'external', apiType: 'GQL', name: 'externalGQL' },
config: defaultDbParams
}
}

27
markdown/launch/brand-migration.md

@ -1,27 +0,0 @@
# Start
# Social Media
- Twitter
- Youtube
- Discord
# Github
## Github org rename
- rename xgenecloud into nocodb
## Create xgenecloud organisation
- migrate repos :
- xc-seed-rest, xc-seed-gql, xc-desktop-app
- xgenecloud
## Incorporate xmysql to nocodb
- Move xmysql to nocodb
- rename it to nocodb
- make a commit mentioning xmysql will be nocodb
- commit xgenecloud-ts into nocodb
- create roadmap
- remove/close issues
- remove/close pull requests
- headings

91
markdown/launch/ph.md

@ -1,91 +0,0 @@
Hey Everybody, Hey Everybody 👋 👋
We are thrilled to open source NocoDB today.
<a><b>NocoDB is an open source Airtable alternative.</b></a>
Github : <a href="https://github.com/nocodb/nocodb"><b>https://github.com/nocodb/nocodb </b></a>
NocoDB works by connecting to any relational databases and transforming them into a smart spreadsheet interface! This allows you to build no-code applications collaboratively with teams. NocoDB currently works with MySQL,PostgreSQL, SQL Server, SQLite, Amazon Aurora & MariaDB databases.
Also NocoDB's app store allows you to build business workflows on views with combination of Slack, Microsoft Teams, Discord, Twilio, Whatsapp, Email to name a few. Plus NocoDB's provides programmatic access to APIs so that you can build integrations with Zapier / Integromat and custom applications too.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
<b> FEATURES : </b>
<b>Rich Spreadsheet Interface</b>
⚡ Sort, search, filter, hide columns with ease
⚡ Create Views : Grid, Gallery, Kanban, Gantt, Form
⚡ Share Views : public & password protected
⚡ Personal & locked Views
⚡ Upload images to cells (Works with <i>S3, Minio, GCP, Azure & many more</i>)!!
⚡ Roles : Owner, Creator, Editor, Commenter, Viewer, Commenter, Custom.
⚡ Access Control : Fine-grained access control even to column level.
⚡ API tokens to integrate with <i>Zapier / Integromat.</i>
<b>Automations & App store : </b>
⚡ Chat :<i>Microsoft Teams, Slack, Discord, Mattermost</i>
⚡ Email : <i> SMTP, SES, Mailchimp</i>
⚡ SMS : <i>Twilio</i>
<i>Whatsapp</i>
⚡ Any 3rd Party APIs
<b>Programmatic API access via </b>
⚡ REST APIs (Swagger)
⚡ GraphQL APIs.
⚡ Includes JWT Authentication & Social Auth
<b>Coming Soon </b>: <i>Page designer, Mobile Apps, Amazing++ things.</i>
<a href="github.com/nocodb/nocodb"><b>Follow our roadmap on Github : </b>Star us / watch us / fork us </a>
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
🎯 &nbsp;<b>Why we building this ?</b>
Most internet businesses equip themselves with either spreadsheet or a database to solve their business needs. Spreadsheets are used by a Billion+ humans collaboratively every single day. However, we are way off working at same speed on databases which are way more powerful tools when it comes to computing. Attempts to solve this with SaaS offerings have meant horrible access controls, vendor lockin, data lockin, abrupt price changes & mostly importantly a glass ceiling on what's possible in future.
<b> &nbsp; Our Mission : </b>
Our mission is to provide the most powerful no-code tool for databases as open source to every single internet business in the world. This would not only democratise collaborative app building but also bring forth a revolution where a billion+ people will have radical <i>tinkering-and-building</i> abilities on internet.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
🔦 &nbsp;<b>Also how it all began .. </b>
We open sourced two API repos before NocoDB :
⚡ A no-code REST APIs generator for any MySQL DB. ~200,000 Docker pulls. This was a hobby project & had no GUI. 📈
⚡ A low-code REST-GraphQL APIs generator for any database with GUI. Used by 100s of companies. Including fortune 500s & publicly trading companies. 📈
The thing that surprised us the most was that even non-developers started using our API products & rooting for us. 🚀 🚀 &nbsp;Whilst everybody loved instant API access to databases, it was slow-and-painful for them to build UI and collaborate with their teams. 💔 💔 ... This made us to rethink, radically re-combine the power of our 2 API products and transform them into something better.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
💊 &nbsp;<b>And ... There is ... One last thing ... this is insanely good :</b>
NocoDB can be boiled down to just SIX lines of node.js. So just one file. With six lines of <i>voodoo</i> in it. So, it can run even on a smallest of servers with minimal setup!! Hope you liked it.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Join our community on :
📣 &nbsp; Github : <a>https://github.com/nocodb/nocodb</a>
📣 &nbsp; Discord : <a>https://discord.gg/5RgZmkW</a>
📣 &nbsp; Twitter : <a>https://twitter.com/nocodb</a>
Would love to hear your usecases & feedbacks. 🙌
Happy hackery,
Team NocoDB
## Images
Todo
- Prepare images with headings
- Rich spreadsheet
- Upload images
- Various views
- Connect to any API
- How it works
- Web Hooks
- Headless APIs
- Prepare GIFS with headings
- Prepare short youtube video

33
markdown/plugins/google-auth.md

@ -1,25 +1,12 @@
# Google Oauth
![Step 1](../../static/google-oauth/1.png)
![Step 2](../../static/google-oauth/2.png)
![Step 3](../../static/google-oauth/3.png)
![Step 4](../../static/google-oauth/4.png)
![Step 1](../../static/google-oauth/1.png)
![Step 5](../../static/google-oauth/5.png)
![Step 6](../../static/google-oauth/6.png)
![Step 7](../../static/google-oauth/7.png)
![Step 8](../../static/google-oauth/8.png)
![Step 9](../../static/google-oauth/9.png)
![Step 10](../../static/google-oauth/10.png)
<img width="1676" alt="1" src="https://user-images.githubusercontent.com/5435402/133758867-5976b85c-00c6-496f-874e-2a5cf6e0c882.png">
<img width="579" alt="2" src="https://user-images.githubusercontent.com/5435402/133758880-bd8bf544-4366-4c22-8381-2237a8109424.png">
<img width="838" alt="3" src="https://user-images.githubusercontent.com/5435402/133758883-bab5ef0b-3b53-46c7-b602-1329f91e3c7f.png">
<img width="1667" alt="4" src="https://user-images.githubusercontent.com/5435402/133758885-ac057a97-b3e5-480f-bcb8-9d08039a1f7c.png">
<img width="1208" alt="5" src="https://user-images.githubusercontent.com/5435402/133758888-606a0565-d76a-436d-9300-f0424425589e.png">
<img width="1329" alt="6" src="https://user-images.githubusercontent.com/5435402/133758891-c9fdcc93-4450-4df8-a869-39e95d063467.png">
<img width="1125" alt="7" src="https://user-images.githubusercontent.com/5435402/133758894-b1dc612e-49e2-4956-b4e4-4a46cd37a4c4.png">
<img width="1288" alt="8" src="https://user-images.githubusercontent.com/5435402/133758897-24feb534-279d-4d6c-b6e3-8b6827204896.png">
<img width="929" alt="9" src="https://user-images.githubusercontent.com/5435402/133758899-453299cb-3759-42b8-8904-136a9f86ac43.png">
<img width="559" alt="10" src="https://user-images.githubusercontent.com/5435402/133758900-9979daf7-4db0-46c5-87da-6af5589e638a.png">

29
markdown/plugins/s3.md

@ -1,22 +1,11 @@
# AWS S3
![Step 1](../../static/s3/1.png)
![Step 2](../../static/s3/2.png)
![Step 3](../../static/s3/3.png)
![Step 4](../../static/s3/4.png)
![Step 1](../../static/s3/1.png)
![Step 5](../../static/s3/5.png)
![Step 6](../../static/s3/6.png)
![Step 7](../../static/s3/7.png)
![Step 8](../../static/s3/8.png)
![Step 9](../../static/s3/9.png)
<img width="1674" alt="1" src="https://user-images.githubusercontent.com/5435402/133758975-3c56e136-1f0d-40d8-a835-4a039826bb09.png">
<img width="849" alt="2" src="https://user-images.githubusercontent.com/5435402/133758989-9a3769c4-5bc1-4541-9871-0b99dc775a80.png">
<img width="815" alt="3" src="https://user-images.githubusercontent.com/5435402/133758993-29c0da2d-b216-4e35-84c3-14a51b1407cc.png">
<img width="842" alt="4" src="https://user-images.githubusercontent.com/5435402/133758998-f9a56453-dacd-48ab-bd5b-50a50ebd6715.png">
<img width="1651" alt="5" src="https://user-images.githubusercontent.com/5435402/133759000-32a29de8-e00c-49a1-8410-1fb67ffa17f8.png">
<img width="1671" alt="6" src="https://user-images.githubusercontent.com/5435402/133759001-be3fbf95-ce8a-43ee-b44f-cc35fd4ce021.png">
<img width="1670" alt="7" src="https://user-images.githubusercontent.com/5435402/133759003-fe8220a6-b9f8-402d-a7e2-8675fc2be9d8.png">
<img width="1660" alt="8" src="https://user-images.githubusercontent.com/5435402/133759004-aa8f40be-56fa-431d-9ba7-d4d63a3fa8b5.png">
<img width="1523" alt="9" src="https://user-images.githubusercontent.com/5435402/133759009-24b2829c-35d0-4c3e-b144-74e934d383d6.png">

202
packages/nc-gui/components/project/spreadsheet/components/spreadsheetNavDrawer.vue

@ -189,94 +189,94 @@
{{ $t('nav_drawer.virtual_views.gallery.create') }}
</v-tooltip>
<v-tooltip bottom>
<template #activator="{ on }">
<v-list-item
dense
class="body-2"
v-on="on"
@click="enableDummyFeat ? openCreateViewDlg('calendar') : comingSoon()"
>
<v-list-item-icon class="mr-n1">
<v-icon x-small>
mdi-calendar
</v-icon>
</v-list-item-icon>
<v-list-item-title>
<span class="font-weight-regular">
<!-- Calendar -->
{{ $t('nav_drawer.virtual_views.calendar.title') }}
</span>
</v-list-item-title>
<v-spacer />
<v-icon class="mr-1" small>
mdi-plus
</v-icon>
</v-list-item>
</template>
<!-- Add Calendar View -->
{{ $t('nav_drawer.virtual_views.calendar.create') }}
</v-tooltip>
<v-tooltip bottom>
<template #activator="{ on }">
<v-list-item
dense
open-class="body-2"
v-on="on"
@click="enableDummyFeat ? openCreateViewDlg('kanban') : comingSoon()"
>
<v-list-item-icon class="mr-n1">
<v-icon x-small>
mdi-tablet-dashboard
</v-icon>
</v-list-item-icon>
<v-list-item-title>
<span class="font-weight-regular">
<!-- Kanban -->
{{ $t('nav_drawer.virtual_views.kanban.title') }}
</span>
</v-list-item-title>
<v-spacer />
<v-icon class="mr-1" small>
mdi-plus
</v-icon>
</v-list-item>
</template>
<!-- Add Kanban View -->
{{ $t('nav_drawer.virtual_views.kanban.create') }}
</v-tooltip>
<v-tooltip bottom>
<template #activator="{ on }">
<v-list-item
dense
class="body-2"
v-on="on"
@click="$toast.info('Coming soon').goAway(3000)"
>
<v-list-item-icon class="mr-n1">
<v-icon x-small class="mt-n1">
mdi-form-select
</v-icon>
</v-list-item-icon>
<v-list-item-title>
<span class="font-weight-regular">
<!-- Form -->
{{ $t('nav_drawer.virtual_views.form.title') }}
</span>
</v-list-item-title>
<v-spacer />
<v-icon class="mr-1" small>
mdi-plus
</v-icon>
</v-list-item>
</template>
<!-- Add Form View -->
{{ $t('nav_drawer.virtual_views.form.create') }}
</v-tooltip>
<!-- <v-tooltip bottom>-->
<!-- <template #activator="{ on }">-->
<!-- <v-list-item-->
<!-- dense-->
<!-- class="body-2"-->
<!-- v-on="on"-->
<!-- @click="enableDummyFeat ? openCreateViewDlg('calendar') : comingSoon()"-->
<!-- >-->
<!-- <v-list-item-icon class="mr-n1">-->
<!-- <v-icon x-small>-->
<!-- mdi-calendar-->
<!-- </v-icon>-->
<!-- </v-list-item-icon>-->
<!-- <v-list-item-title>-->
<!-- <span class="font-weight-regular">-->
<!-- &lt;!&ndash; Calendar &ndash;&gt;-->
<!-- {{ $t('nav_drawer.virtual_views.calendar.title') }}-->
<!-- </span>-->
<!-- </v-list-item-title>-->
<!-- <v-spacer />-->
<!-- <v-icon class="mr-1" small>-->
<!-- mdi-plus-->
<!-- </v-icon>-->
<!-- </v-list-item>-->
<!-- </template>-->
<!-- &lt;!&ndash; Add Calendar View &ndash;&gt;-->
<!-- {{ $t('nav_drawer.virtual_views.calendar.create') }}-->
<!-- </v-tooltip>-->
<!-- <v-tooltip bottom>-->
<!-- <template #activator="{ on }">-->
<!-- <v-list-item-->
<!-- dense-->
<!-- open-class="body-2"-->
<!-- v-on="on"-->
<!-- @click="enableDummyFeat ? openCreateViewDlg('kanban') : comingSoon()"-->
<!-- >-->
<!-- <v-list-item-icon class="mr-n1">-->
<!-- <v-icon x-small>-->
<!-- mdi-tablet-dashboard-->
<!-- </v-icon>-->
<!-- </v-list-item-icon>-->
<!-- <v-list-item-title>-->
<!-- <span class="font-weight-regular">-->
<!-- &lt;!&ndash; Kanban &ndash;&gt;-->
<!-- {{ $t('nav_drawer.virtual_views.kanban.title') }}-->
<!-- </span>-->
<!-- </v-list-item-title>-->
<!-- <v-spacer />-->
<!-- <v-icon class="mr-1" small>-->
<!-- mdi-plus-->
<!-- </v-icon>-->
<!-- </v-list-item>-->
<!-- </template>-->
<!-- &lt;!&ndash; Add Kanban View &ndash;&gt;-->
<!-- {{ $t('nav_drawer.virtual_views.kanban.create') }}-->
<!-- </v-tooltip>-->
<!-- <v-tooltip bottom>-->
<!-- <template #activator="{ on }">-->
<!-- <v-list-item-->
<!-- dense-->
<!-- class="body-2"-->
<!-- v-on="on"-->
<!-- @click="$toast.info('Coming soon').goAway(3000)"-->
<!-- >-->
<!-- <v-list-item-icon class="mr-n1">-->
<!-- <v-icon x-small class="mt-n1">-->
<!-- mdi-form-select-->
<!-- </v-icon>-->
<!-- </v-list-item-icon>-->
<!-- <v-list-item-title>-->
<!-- <span class="font-weight-regular">-->
<!-- &lt;!&ndash; Form &ndash;&gt;-->
<!-- {{ $t('nav_drawer.virtual_views.form.title') }}-->
<!-- </span>-->
<!-- </v-list-item-title>-->
<!-- <v-spacer />-->
<!-- <v-icon class="mr-1" small>-->
<!-- mdi-plus-->
<!-- </v-icon>-->
<!-- </v-list-item>-->
<!-- </template>-->
<!-- &lt;!&ndash; Add Form View &ndash;&gt;-->
<!-- {{ $t('nav_drawer.virtual_views.form.create') }}-->
<!-- </v-tooltip>-->
</v-list>
</template>
</div>
@ -378,19 +378,19 @@
</v-menu>
</v-list-item>
<!-- <v-tooltip bottom>-->
<!-- <template #activator="{ on }">-->
<!-- <v-list-item v-on="on" @click="copyapiUrlToClipboard">-->
<!-- <v-icon x-small class="mr-2">-->
<!-- mdi-content-copy-->
<!-- </v-icon>-->
<!-- &lt;!&ndash; Copy API URL &ndash;&gt;-->
<!-- <span class="caption">{{ $t('nav_drawer.advanced.views_list') }}</span>-->
<!-- </v-list-item>-->
<!-- </template>-->
<!-- &lt;!&ndash; Copy API URL &ndash;&gt;-->
<!-- {{ $t('nav_drawer.advanced.views_list') }}-->
<!-- </v-tooltip>-->
<v-tooltip bottom>
<template #activator="{ on }">
<v-list-item v-on="on" @click="copyapiUrlToClipboard">
<v-icon x-small class="mr-2">
mdi-content-copy
</v-icon>
<!-- Copy API URL -->
<span class="caption">{{ $t('nav_drawer.advanced.views_list') }}</span>
</v-list-item>
</template>
<!-- Copy API URL -->
{{ $t('nav_drawer.advanced.views_list') }}
</v-tooltip>
<template v-if="_isUIAllowed('model')">
<v-divider class="advance-menu-divider" />
<slot />

38
packages/nc-gui/layouts/default.vue

@ -320,19 +320,30 @@
</v-list-item-title>
</v-list-item>-->
<v-list-item v-ge="['Sign Out','']" dense>
<v-list-item-title>
<v-icon small>
mdi-at
</v-icon>&nbsp; <span class="font-weight-bold">{{ userEmail }}</span>
</v-list-item-title>
</v-list-item>
<v-list-item
<v-divider></v-divider>
<v-list-item v-if="isDashboard"
v-clipboard="$store.state.users.token"
dense
@click.stop="$toast.success('Auth token copied to clipboard').goAway(3000)"
>
<v-list-item-title>
<v-icon key="terminal-dash" small>
mdi-console
mdi-content-copy
</v-icon>&nbsp;
<span class="font-weight-regular">Copy auth token</span>
</v-list-item-title>
</v-list-item>
<!--
<v-list-item dense @click.stop="projectInfoTabAdd">
<v-list-item-title>
@ -357,23 +368,25 @@
{{ isGql ? 'GraphQL APIs' : 'Swagger APIs Doc' }}</span>
</v-list-item-title>
</v-list-item>
<v-divider></v-divider>
<v-list-item v-if="isDashboard" v-ge="['Sign Out','']" dense @click="copyProjectInfo">
<v-list-item-title>
<v-icon small>
mdi-information-outline
</v-icon>&nbsp; <span class="font-weight-regular">Copy Project info</span>
</v-list-item-title>
</v-list-item>
<v-list-item dense @click.stop="settingsTabAdd">
<v-list-item dense @click.stop="settingsTabAdd" v-if="isDashboard">
<v-list-item-title>
<v-icon key="terminal-dash" small>
mdi-cog
mdi-palette
</v-icon>&nbsp;
<span class="font-weight-regular">Themes</span>
</v-list-item-title>
</v-list-item>
<v-list-item v-if="isDashboard" v-ge="['Sign Out','']" dense @click="copyProjectInfo">
<v-list-item-title>
<v-icon small>
info
</v-icon>&nbsp; <span class="font-weight-regular">Copy Project info</span>
</v-list-item-title>
</v-list-item>
<v-divider v-if="isDashboard"></v-divider>
<v-list-item v-ge="['Sign Out','']" dense @click="MtdSignOut">
<v-list-item-title>
@ -626,7 +639,8 @@ export default {
isGql: 'project/GtrProjectIsGraphql',
isRest: 'project/GtrProjectIsRest',
isGrpc: 'project/GtrProjectIsGrpc',
role: 'users/GtrRole'
role: 'users/GtrRole',
userEmail: 'users/GtrUserEmail'
}),
user() {
return this.$store.getters['users/GtrUser']

27
packages/nc-gui/package-lock.json generated

@ -3337,6 +3337,15 @@
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
},
"bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"optional": true,
"requires": {
"file-uri-to-path": "1.0.0"
}
},
"blob": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
@ -6375,6 +6384,12 @@
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
},
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"optional": true
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@ -8524,6 +8539,12 @@
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
},
"nan": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
"optional": true
},
"nano-assign": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/nano-assign/-/nano-assign-1.0.1.tgz",
@ -13044,7 +13065,11 @@
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"optional": true
"optional": true,
"requires": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
}
},
"glob-parent": {
"version": "3.1.0",

12
packages/nc-gui/store/users.js

@ -49,6 +49,9 @@ export const getters = {
return state.paidUser
},
GtrIsAuthenticated(state, getters, rootState) {
return rootState.project.projectInfo &&
(rootState.project.projectInfo.authType === 'none' ||
@ -88,7 +91,14 @@ export const getters = {
'creator',
'editor',
'viewer'].find(r => state.user.roles[r]) || Object.keys(state.user.roles)[0])
}
},
GtrUserEmail(state) {
if(state.user && state.user.email)
return state.user.email;
else
return '';
},
}

23
packages/noco-docs/content/en/developer-resources/api-tokens.md

@ -0,0 +1,23 @@
---
title: 'API Tokens'
description: 'API Tokens'
position: 500
category: 'Developer Resources'
menuTitle: 'API Tokens'
---
## API Tokens
NocoDB allows creating API tokens which allow it to be integrated seamlessly with 3rd party apps.
### Creating API tokens
![1](https://user-images.githubusercontent.com/5435402/133734223-49bb1567-6cd2-43e5-bdda-aaccda741070.png)
![2](https://user-images.githubusercontent.com/5435402/133734234-5ca542b1-5843-46f7-b97b-9e686c6bf7ac.png)
![3](https://user-images.githubusercontent.com/5435402/133734238-33d5bdd0-5c97-4dbe-8e49-744193c3ac20.png)
![4](https://user-images.githubusercontent.com/5435402/133734239-7b530235-3352-497b-b23c-3a701290a569.png)
![5](https://user-images.githubusercontent.com/5435402/133734241-0f25bbd0-ab92-430a-9987-cc745d5b1b47.png)
![6](https://user-images.githubusercontent.com/5435402/133734243-6dc8527e-573d-45e2-8cd8-13a8beea0dfa.png)
### Using API Tokens
Invoke NocoDB APIs with ```xc-token``` header

13
packages/noco-docs/content/en/developer-resources/webhooks.md

@ -7,14 +7,15 @@ menuTitle: 'Webhooks'
---
## Triggers available
Webhooks allows user to trigger on certain operations on following database operations
- AFTER INSERT
- AFTER UPDATE
- AFTER DELETE
Webhooks allows user to trigger certain operation on following database operations
- INSERT
- UPDATE
- DELETE
The hook can trigger `before` or `after` a certain operation and the triggers will trigger asynchronously without blocking the actual operation.
The triggers will trigger asynchronously without blocking the actual operation.
## Available Triggers
## Trigger to following applications/services
| Trigger | Details |
|-------|-------|

32
packages/noco-docs/content/en/getting-started/installation.md

@ -134,6 +134,25 @@ And connection params for this database can be specified in `NC_DB` environment
</code-block>
</code-group>
### Environment variables
| Variable | Mandatory | Comments | If absent |
|-------------------------|-----------|----------------------------------------------------------------------------------|--------------------------------------------|
| NC_DB | Yes | See our database URLs | A local SQLite will be created in root folder |
| DATABASE_URL | No | JDBC URL Format. Can be used instead of NC_DB. Used in 1-Click Heroku deployment| |
| DATABASE_URL_FILE | No | path to file containing JDBC URL Format. Can be used instead of NC_DB. Used in 1-Click Heroku deployment| |
| NC_PUBLIC_URL | Yes | Used for sending Email invitations | Best guess from http request params |
| NC_AUTH_JWT_SECRET | Yes | JWT secret used for auth and storing other secrets | A Random secret will be generated |
| NC_SENTRY_DSN | No | For Sentry monitoring | |
| NC_CONNECT_TO_EXTERNAL_DB_DISABLED | No | Disable Project creation with external database | |
| NC_DISABLE_TELE | No | Disable telemetry | |
| NC_BACKEND_URL | No | Custom Backend URL | ``http://localhost:8080`` will be used |
| AWS_ACCESS_KEY_ID | No | For Litestream - S3 access key id | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 |
| AWS_SECRET_ACCESS_KEY | No | For Litestream - S3 secret access key | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 |
| AWS_BUCKET | No | For Litestream - S3 bucket | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 |
| AWS_BUCKET_PATH | No | For Litestream - S3 bucket path (like folder within S3 bucket) | If Litestream is configured and NC_DB is not present. SQLite gets backed up to S3 |
### Docker Compose
<code-group>
@ -261,19 +280,6 @@ aws ecs create-service \
If your service fails to start, you may check the logs in ECS console or in Cloudwatch. Generally it fails due to the connection between ECS container and NC_DB. Make sure the security groups have the correct inbound and outbound rules.
</alert>
# Environment variables
| Variable | Mandatory | Comments | If absent |
|-------------------------|-----------|----------------------------------------------------------------------------------|--------------------------------------------|
| NC_DB | Yes | See our database URLs | A local SQLite will be created in root folder |
| DATABASE_URL | No | JDBC URL Format. Can be used instead of NC_DB. Used in 1-Click Heroku deployment| |
| DATABASE_URL_FILE | No | path to file containing JDBC URL Format. Can be used instead of NC_DB. Used in 1-Click Heroku deployment| |
| NC_PUBLIC_URL | Yes | Used for sending Email invitations | Best guess from http request params |
| NC_AUTH_JWT_SECRET | Yes | JWT secret used for auth and storing other secrets | A Random secret will be generated |
| NC_SENTRY_DSN | No | For Sentry monitoring | |
| NC_CONNECT_TO_EXTERNAL_DB_DISABLED | No | Disable Project creation with external database | |
| NC_DISABLE_TELE | No | Disable telemetry | |
| NC_BACKEND_URL | No | Custom Backend URL | ``http://localhost:8080`` will be used |
## Sample Demos

3611
packages/nocodb/package-lock.json generated

File diff suppressed because it is too large Load Diff

BIN
static/google-oauth/1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

BIN
static/google-oauth/10.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

BIN
static/google-oauth/2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

BIN
static/google-oauth/3.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

BIN
static/google-oauth/4.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

BIN
static/google-oauth/5.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

BIN
static/google-oauth/6.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

BIN
static/google-oauth/7.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

BIN
static/google-oauth/8.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

BIN
static/google-oauth/9.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 205 KiB

BIN
static/nocodb/1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 605 KiB

BIN
static/nocodb/10.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

BIN
static/nocodb/11.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

BIN
static/nocodb/2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

BIN
static/nocodb/3.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

BIN
static/nocodb/4.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

BIN
static/nocodb/5.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

BIN
static/nocodb/6.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 373 KiB

BIN
static/nocodb/7.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 KiB

BIN
static/nocodb/8.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 KiB

BIN
static/nocodb/9.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

BIN
static/open-source-airtable-alternative/OpenSourceAirtableAlternative-old.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 892 KiB

BIN
static/open-source-airtable-alternative/OpenSourceAirtableAlternative.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 MiB

BIN
static/open-source-airtable-alternative/OpenSourceAirtableAlternative.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 KiB

BIN
static/s3/1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 385 KiB

BIN
static/s3/2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 KiB

BIN
static/s3/3.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 368 KiB

BIN
static/s3/4.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

BIN
static/s3/5.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 594 KiB

BIN
static/s3/6.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 300 KiB

BIN
static/s3/7.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 KiB

BIN
static/s3/8.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 KiB

BIN
static/s3/9.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 KiB

BIN
static/screenshots/googleoauth/1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 277 KiB

BIN
static/screenshots/googleoauth/10.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

BIN
static/screenshots/googleoauth/2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

BIN
static/screenshots/googleoauth/3.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

BIN
static/screenshots/googleoauth/4.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

BIN
static/screenshots/googleoauth/5.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 KiB

BIN
static/screenshots/googleoauth/6.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 277 KiB

BIN
static/screenshots/googleoauth/7.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

BIN
static/screenshots/googleoauth/8.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 303 KiB

BIN
static/screenshots/googleoauth/9.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 240 KiB

BIN
static/screenshots/s3/Screenshot 2021-03-18 at 3.00.10 PM.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 545 KiB

BIN
static/screenshots/s3/Screenshot 2021-03-18 at 3.12.57 PM.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 KiB

BIN
static/screenshots/s3/Screenshot 2021-03-18 at 3.13.17 PM.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 KiB

BIN
static/screenshots/s3/Screenshot 2021-03-18 at 3.14.12 PM.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

BIN
static/screenshots/s3/Screenshot 2021-03-18 at 3.23.48 PM.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 697 KiB

BIN
static/screenshots/s3/Screenshot 2021-03-18 at 3.24.13 PM.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 378 KiB

BIN
static/screenshots/s3/Screenshot 2021-03-18 at 3.24.26 PM.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 KiB

BIN
static/screenshots/s3/Screenshot 2021-03-18 at 3.24.43 PM.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 526 KiB

BIN
static/screenshots/s3/Screenshot 2021-03-18 at 3.26.34 PM.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 261 KiB

BIN
static/screenshots/s3/Screenshot 2021-03-18 at 3.26.54 PM.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

Loading…
Cancel
Save