Browse Source

Merge branch 'develop' into feat/pnpm

pull/5903/head
Wing-Kam Wong 1 year ago
parent
commit
7aa67a7c74
  1. 4
      packages/nc-gui/components/account/Token.vue
  2. 13
      packages/nc-gui/components/smartsheet/Pagination.vue
  3. 9
      packages/nc-gui/lang/en.json
  4. 14
      packages/nc-gui/pages/account/index.vue
  5. 140
      packages/noco-docs/content/en/developer-resources/upload-via-api

4
packages/nc-gui/components/account/Token.vue

@ -101,7 +101,7 @@ const descriptionInput: VNodeRef = (el) => (el as HTMLInputElement)?.focus()
<template> <template>
<div class="h-full overflow-y-scroll scrollbar-thin-dull pt-2"> <div class="h-full overflow-y-scroll scrollbar-thin-dull pt-2">
<div class="max-w-[900px] mx-auto p-4" data-testid="nc-token-list"> <div class="max-w-[900px] mx-auto p-4" data-testid="nc-token-list">
<div class="text-xl my-4 text-left font-weight-bold">Token Management</div> <div class="text-xl my-4 text-left font-weight-bold">{{ $t('title.tokenManagement') }}</div>
<div class="py-2 flex gap-4 items-center"> <div class="py-2 flex gap-4 items-center">
<div class="flex-grow"></div> <div class="flex-grow"></div>
<component :is="iconMap.reload" class="cursor-pointer" @click="loadTokens" /> <component :is="iconMap.reload" class="cursor-pointer" @click="loadTokens" />
@ -114,7 +114,7 @@ const descriptionInput: VNodeRef = (el) => (el as HTMLInputElement)?.focus()
> >
<div class="flex items-center gap-1"> <div class="flex items-center gap-1">
<component :is="iconMap.plus" /> <component :is="iconMap.plus" />
Add new token {{ $t('title.addNewToken') }}
</div> </div>
</a-button> </a-button>
</div> </div>

13
packages/nc-gui/components/smartsheet/Pagination.vue

@ -1,10 +1,13 @@
<script setup lang="ts"> <script setup lang="ts">
import { ChangePageInj, PaginationDataInj, computed, iconMap, inject } from '#imports' import { ChangePageInj, PaginationDataInj, computed, iconMap, inject, isRtlLang, useI18n } from '#imports'
import type { Language } from '~/lib'
const props = defineProps<{ const props = defineProps<{
alignCountOnRight?: boolean alignCountOnRight?: boolean
}>() }>()
const { locale } = useI18n()
const paginatedData = inject(PaginationDataInj)! const paginatedData = inject(PaginationDataInj)!
const changePage = inject(ChangePageInj)! const changePage = inject(ChangePageInj)!
@ -19,6 +22,8 @@ const page = computed({
changePage?.(p) changePage?.(p)
}, },
}) })
const isRTLLanguage = computed(() => isRtlLang(locale.value as keyof typeof Language))
</script> </script>
<template> <template>
@ -39,6 +44,7 @@ const page = computed({
v-model:page-size="size" v-model:page-size="size"
size="small" size="small"
class="!text-xs !m-1 nc-pagination" class="!text-xs !m-1 nc-pagination"
:class="{ 'rtl-pagination': isRTLLanguage }"
:total="count" :total="count"
show-less-items show-less-items
:show-size-changer="false" :show-size-changer="false"
@ -77,4 +83,9 @@ const page = computed({
:deep(.ant-pagination-item-link) { :deep(.ant-pagination-item-link) {
@apply text-gray-500 flex items-center justify-center; @apply text-gray-500 flex items-center justify-center;
} }
:deep(.rtl-pagination .ant-pagination-prev .ant-pagination-item-link),
:deep(.rtl-pagination .ant-pagination-next .ant-pagination-item-link) {
@apply transform rotate-180;
}
</style> </style>

9
packages/nc-gui/lang/en.json

@ -211,7 +211,14 @@
"codeSnippet": "Code Snippet", "codeSnippet": "Code Snippet",
"keyboardShortcut": "Keyboard Shortcuts", "keyboardShortcut": "Keyboard Shortcuts",
"generateRandomName": "Generate Random Name", "generateRandomName": "Generate Random Name",
"findRowByScanningCode": "Find row by scanning a QR or Barcode" "findRowByScanningCode": "Find row by scanning a QR or Barcode",
"tokenManagement": "Token Management",
"addNewToken": "Add new token",
"accountSettings": "Account Settings",
"resetPasswordMenu": "Reset Password",
"tokens": "Tokens",
"userManagement": "User Management",
"licence": "Licence"
}, },
"labels": { "labels": {
"createdBy": "Created By", "createdBy": "Created By",

14
packages/nc-gui/pages/account/index.vue

@ -30,7 +30,7 @@ const openKeys = ref([/^\/account\/users/.test($route.fullPath) && 'users'])
class="tabs-menu h-full" class="tabs-menu h-full"
mode="inline" mode="inline"
> >
<div class="text-xs text-gray-500 ml-4 pt-4 pb-2 font-weight-bold">Account Settings</div> <div class="text-xs text-gray-500 ml-4 pt-4 pb-2 font-weight-bold">{{ $t('title.accountSettings') }}</div>
<a-sub-menu key="users" class="!bg-white"> <a-sub-menu key="users" class="!bg-white">
<template #icon> <template #icon>
@ -44,10 +44,10 @@ const openKeys = ref([/^\/account\/users/.test($route.fullPath) && 'users'])
class="text-xs" class="text-xs"
@click="navigateTo('/account/users/list')" @click="navigateTo('/account/users/list')"
> >
<span class="ml-4">User Management</span> <span class="ml-4">{{ $t('title.userManagement') }}</span>
</a-menu-item> </a-menu-item>
<a-menu-item key="password-reset" class="text-xs" @click="navigateTo('/account/users/password-reset')"> <a-menu-item key="password-reset" class="text-xs" @click="navigateTo('/account/users/password-reset')">
<span class="ml-4">Reset Password</span> <span class="ml-4">{{ $t('title.resetPasswordMenu') }}</span>
</a-menu-item> </a-menu-item>
<a-menu-item <a-menu-item
v-if="isUIAllowed('superAdminAppSettings')" v-if="isUIAllowed('superAdminAppSettings')"
@ -55,7 +55,7 @@ const openKeys = ref([/^\/account\/users/.test($route.fullPath) && 'users'])
class="text-xs" class="text-xs"
@click="navigateTo('/account/users/settings')" @click="navigateTo('/account/users/settings')"
> >
<span class="ml-4">Settings</span> <span class="ml-4">{{ $t('activity.settings') }}</span>
</a-menu-item> </a-menu-item>
</a-sub-menu> </a-sub-menu>
@ -67,7 +67,7 @@ const openKeys = ref([/^\/account\/users/.test($route.fullPath) && 'users'])
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<MdiShieldKeyOutline /> <MdiShieldKeyOutline />
<div class="select-none">Tokens</div> <div class="select-none">{{ $t('title.tokens') }}</div>
</div> </div>
</a-menu-item> </a-menu-item>
<a-menu-item <a-menu-item
@ -79,7 +79,7 @@ const openKeys = ref([/^\/account\/users/.test($route.fullPath) && 'users'])
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<component :is="iconMap.appStore" /> <component :is="iconMap.appStore" />
<div class="select-none">App Store</div> <div class="select-none">{{ $t('title.appStore') }}</div>
</div> </div>
</a-menu-item> </a-menu-item>
<a-menu-item <a-menu-item
@ -91,7 +91,7 @@ const openKeys = ref([/^\/account\/users/.test($route.fullPath) && 'users'])
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<component :is="iconMap.key" /> <component :is="iconMap.key" />
<div class="select-none">License</div> <div class="select-none">{{ $t('title.licence') }}</div>
</div> </div>
</a-menu-item> </a-menu-item>
</a-menu> </a-menu>

140
packages/noco-docs/content/en/developer-resources/upload-via-api

@ -0,0 +1,140 @@
---
title: 'Upload via API'
description: 'Upload files locally present or from public remote URL via API'
position: 1600
category: 'Developer Resources'
menuTitle: 'Upload via API'
---
Sample code to upload files via API is listed below.
Assumes `http://localhost:8080/` as the base URL for the API calls.
# Upload local file
```
let axios = require("axios").default;
let FormData = require('form-data');
let fs = require('fs');
// Configurations
//
const project_id = '<Project Identifier>';
const table_id = '<Table Identifier>';
const xc_token = '<Auth Token>';
const file_path = '<Local File Path>';
// Insert Image
// @param image_path : local file path
// @return : JSON object to be used in insert record API for attachment field
//
async function insertImage (path) {
const formData = new FormData();
formData.append("file", fs.createReadStream(path));
const data = await axios({
url: 'http://localhost:8080/api/v1/db/storage/upload',
data: formData,
headers:{
'Content-Type':`multipart/form-data;`,
'xc-auth': xc_token
},
method: 'post',
// Optional : storage file path
params: {"path": "somePath"}
});
return data;
}
// Insert record with attachment
// Assumes a table with two columns :
// 'Title' of type SingleLineText and
// 'Attachment' of type Attachment
//
async function uploadFileExample() {
let response = await insertImage(file_path);
let row = {
"Title": "2",
"Attachment": response.data
};
await axios({
method: 'POST',
url: `http://localhost:8080/api/v1/db/data/noco/${project_id}/${table_id}`,
data: row,
headers: {
'xc-auth': xc_token
}
});
}
(async () => {
await uploadFileExample();
})();
```
# Upload via URL
```
let axios = require("axios").default;
let FormData = require('form-data');
let fs = require('fs');
// Configurations
//
const project_id = '<Project Identifier>';
const table_id = '<Table Identifier>';
const xc_token = '<Auth Token>';
// URL array : URLs of files to be uploaded
const URLs = [{ url: '<URL1>' }, { url: '<URL2>' }];
// Insert Image
// @param URLs : [] containing public URL for files to be uploaded
// @return : JSON object to be used in insert record API for attachment field
//
async function insertImageByURL (URL_array) {
const data = await axios({
url: 'http://localhost:8080/api/v1/db/storage/upload-by-url',
data: URL_array,
headers: {
'xc-auth': xc_token
},
method: 'post',
// Optional : storage file path
params: {"path": "somePath"}
});
return data;
}
// Insert record with attachment
// Assumes a table with two columns :
// 'Title' of type SingleLineText and
// 'Attachment' of type Attachment
//
async function uploadByUrlExample() {
let response = await insertImageByURL(URLs);
// Update two columns : Title and Attachment
let row = {
"Title": "3",
"Attachment": response.data
};
await axios({
method: 'POST',
url: `http://localhost:8080/api/v1/db/data/noco/${project_id}/${table_id}`,
data: row,
headers: {
'xc-auth': xc_auth
}
});
}
(async () => {
await uploadByUrlExample();
})();
```
Loading…
Cancel
Save