diff --git a/.gitignore b/.gitignore index 93da049aca..708ae74171 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,6 @@ dist *.sublime-settings *.db .nyc_output +.history /.idea/ app/public/img/docs/* diff --git a/app/src/interfaces/m2a-builder/m2a-builder.vue b/app/src/interfaces/m2a-builder/m2a-builder.vue index 3a73d6e0e6..f77c870bcb 100644 --- a/app/src/interfaces/m2a-builder/m2a-builder.vue +++ b/app/src/interfaces/m2a-builder/m2a-builder.vue @@ -249,30 +249,33 @@ export default defineComponent({ const junctionRowMap = ref([]); const previewValues = computed(() => { + // Need to wait until junctionRowMap got properly populated + if (junctionRowMap.value.length < 1) { + return []; + } + // Convert all string/number junction rows into junction row records from the map so we can inject the // related values - const values = cloneDeep(props.value || []) - .map((val, index) => { - const junctionKey = isPlainObject(val) ? val[o2mRelation.value.many_primary] : val; + const values = cloneDeep(props.value || []).map((val, index) => { + const junctionKey = isPlainObject(val) ? val[o2mRelation.value.many_primary] : val; - const savedValues = junctionRowMap.value.find( - (junctionRow) => junctionRow[o2mRelation.value.many_primary] === junctionKey - ); + const savedValues = junctionRowMap.value.find( + (junctionRow) => junctionRow[o2mRelation.value.many_primary] === junctionKey + ); - if (isPlainObject(val)) { - return { - ...savedValues, - ...val, - $index: index, - }; - } else { - return { - ...savedValues, - $index: index, - }; - } - }) - .filter((val) => val); + if (isPlainObject(val)) { + return { + ...savedValues, + ...val, + $index: index, + }; + } else { + return { + ...savedValues, + $index: index, + }; + } + }); return values .map((val) => { @@ -528,6 +531,10 @@ export default defineComponent({ }, }; + if (props.sortField) { + editsAtStart.value[props.sortField] = junctionRow[props.sortField]; + } + relatedPrimaryKey.value = relatedKey || '+'; currentlyEditing.value = item; return; diff --git a/docs/reference/sdk-js.md b/docs/reference/sdk-js.md index 6f10edfe4d..8c00ad548f 100644 --- a/docs/reference/sdk-js.md +++ b/docs/reference/sdk-js.md @@ -11,6 +11,10 @@ API from a JavaScript powered project. npm install @directus/sdk-js ``` +## TypeScript + +If you are using TypeScript, the JS SDK requires TypeScript 3.8 or newer. + ## Usage ```js diff --git a/packages/sdk-js/src/handlers/auth.ts b/packages/sdk-js/src/handlers/auth.ts index f12461f308..01079343e4 100644 --- a/packages/sdk-js/src/handlers/auth.ts +++ b/packages/sdk-js/src/handlers/auth.ts @@ -41,7 +41,7 @@ export class AuthHandler { this.accessTokenInitId = this.axios.interceptors.request.use((config) => this.initializeAccessToken(config)); if (this.autoRefresh) { - this.refresh(true); + this.refresh(); } } @@ -75,7 +75,7 @@ export class AuthHandler { await this.storage.setItem('directus_refresh_token', data.refresh_token); } if (this.autoRefresh) { - this.refresh(true); + this.refresh(); } return response.data; @@ -84,17 +84,15 @@ export class AuthHandler { /** * Refresh access token 10 seconds before expiration */ - async refresh(isInitialInvoke: Boolean): Promise<{ data: AuthResponse } | undefined> { + async refresh(): Promise<{ data: AuthResponse } | undefined> { this.removeTimeout(); this.expiresAt = await this.storage.getItem('directus_access_token_expires'); if (!this.expiresAt) return; if (Date.now() + 10000 < this.expiresAt && this.autoRefresh) { - this.autoRefreshTimeout = setTimeout(() => this.refresh(false), this.expiresAt - Date.now() - 10000); - if (!isInitialInvoke) { - return; - } + this.autoRefreshTimeout = setTimeout(() => this.refresh(), this.expiresAt - Date.now() - 10000); + return; } const payload: Record = { mode: this.mode }; @@ -120,7 +118,7 @@ export class AuthHandler { } if (this.autoRefresh) { - this.autoRefreshTimeout = setTimeout(() => this.refresh(false), data.expires - 10000); + this.autoRefreshTimeout = setTimeout(() => this.refresh(), data.expires - 10000); } return response.data; } @@ -132,6 +130,12 @@ export class AuthHandler { data.refresh_token = await this.storage.getItem('directus_refresh_token'); } await this.axios.post('/auth/logout', data); + + await this.storage.removeItem('directus_access_token'); + await this.storage.removeItem('directus_access_token_expires'); + if (this.mode === 'json') { + await this.storage.removeItem('directus_refresh_token'); + } this.token = null; } diff --git a/packages/sdk-js/src/types.ts b/packages/sdk-js/src/types.ts index d4c6d8fd6c..7091bd6980 100644 --- a/packages/sdk-js/src/types.ts +++ b/packages/sdk-js/src/types.ts @@ -49,4 +49,5 @@ export type FilterOperator = export type AuthStorage = { getItem: (key: string) => Promise; setItem: (key: string, value: any) => Promise; + removeItem: (key: string) => Promise; }; diff --git a/packages/sdk-js/src/utils/browser-store.ts b/packages/sdk-js/src/utils/browser-store.ts index 0c00136e9a..8434c9adc3 100644 --- a/packages/sdk-js/src/utils/browser-store.ts +++ b/packages/sdk-js/src/utils/browser-store.ts @@ -8,4 +8,8 @@ export class BrowserStore implements AuthStorage { async setItem(key: string, value: any): Promise { window.localStorage.setItem(key, value); } + + async removeItem(key: string): Promise { + window.localStorage.removeItem(key); + } } diff --git a/packages/sdk-js/src/utils/memory-store.ts b/packages/sdk-js/src/utils/memory-store.ts index 054e3e201f..7a86733c96 100644 --- a/packages/sdk-js/src/utils/memory-store.ts +++ b/packages/sdk-js/src/utils/memory-store.ts @@ -10,4 +10,8 @@ export class MemoryStore implements AuthStorage { async setItem(key: string, value: any): Promise { this.values[key] = value; } + + async removeItem(key: string): Promise { + delete this.values[key]; + } }