diff --git a/cookbook/serializer.py b/cookbook/serializer.py
index 0100d2f60..c62fdc407 100644
--- a/cookbook/serializer.py
+++ b/cookbook/serializer.py
@@ -232,6 +232,7 @@ class FoodInheritFieldSerializer(UniqueFieldsMixin, WritableNestedModelSerialize
class UserFileSerializer(serializers.ModelSerializer):
+ created_by = UserSerializer(read_only=True)
file = serializers.FileField(write_only=True)
file_download = serializers.SerializerMethodField('get_download_link')
preview = serializers.SerializerMethodField('get_preview_link')
@@ -277,12 +278,13 @@ class UserFileSerializer(serializers.ModelSerializer):
class Meta:
model = UserFile
- fields = ('id', 'name', 'file', 'file_download', 'preview', 'file_size_kb')
- read_only_fields = ('id', 'file_size_kb')
+ fields = ('id', 'name', 'file', 'file_download', 'preview', 'file_size_kb', 'created_by', 'created_at')
+ read_only_fields = ('id', 'file_download', 'preview', 'file_size_kb', 'created_by', 'created_at')
extra_kwargs = {"file": {"required": False, }}
class UserFileViewSerializer(serializers.ModelSerializer):
+ created_by = UserSerializer(read_only=True)
file_download = serializers.SerializerMethodField('get_download_link')
preview = serializers.SerializerMethodField('get_preview_link')
@@ -307,8 +309,8 @@ class UserFileViewSerializer(serializers.ModelSerializer):
class Meta:
model = UserFile
- fields = ('id', 'name', 'file_download', 'preview')
- read_only_fields = ('id', 'file')
+ fields = ('id', 'name', 'file_download', 'preview', 'file_size_kb', 'created_by', 'created_at')
+ read_only_fields = ('id', 'file', 'file_download', 'file_size_kb', 'preview', 'created_by', 'created_at')
class SpaceSerializer(WritableNestedModelSerializer):
diff --git a/cookbook/views/api.py b/cookbook/views/api.py
index 4f8e0233b..f2e5fafe6 100644
--- a/cookbook/views/api.py
+++ b/cookbook/views/api.py
@@ -428,7 +428,7 @@ class SpaceViewSet(viewsets.ModelViewSet):
@decorators.action(detail=False, pagination_class=None, methods=['GET'], serializer_class=SpaceSerializer, )
def current(self, request):
self.queryset.filter(id=self.request.space.id)
- return Response(self.serializer_class(self.request.space, many=False).data)
+ return Response(self.serializer_class(self.request.space, many=False, context={'request': self.request}).data)
# TODO what is internal_note for?
@@ -1714,6 +1714,7 @@ class LocalizationViewSet(viewsets.GenericViewSet):
def get_queryset(self):
return None
+
def list(self, request, *args, **kwargs):
langs = []
for l in settings.LANGUAGES:
diff --git a/vue3/package.json b/vue3/package.json
index 1c66dc6e8..08503703d 100644
--- a/vue3/package.json
+++ b/vue3/package.json
@@ -24,7 +24,7 @@
"vuetify": "^3.6.13"
},
"devDependencies": {
- "@fortawesome/fontawesome-free": "^6.5.2",
+ "@fortawesome/fontawesome-free": "^6.6.0",
"@tsconfig/node18": "^18.2.4",
"@types/jsdom": "^21.1.1",
"@types/node": "^18.17.5",
diff --git a/vue3/src/components/inputs/UserFileField.vue b/vue3/src/components/inputs/UserFileField.vue
new file mode 100644
index 000000000..315946280
--- /dev/null
+++ b/vue3/src/components/inputs/UserFileField.vue
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+ {{ $t('select_file') }}
+ {{ model.name }}
+
+
+
+
+
+
+
+
+ {{ $t('Files') }}
+
+ Preview
+ New
+ Browse
+
+
+
+
+
+
+ {{ model.name }}
+
+
+ {{ $n(model.fileSizeKb / 1000) }} MB
+ {{ model.createdBy.displayName }}
+ {{ DateTime.fromJSDate(model.createdAt).toLocaleString(DateTime.DATETIME_SHORT) }}
+
+
+
+
+
+ {{ $t('Download') }}
+
+ {{ $t('Delete') }}
+
+
+
+
+
+
+
+
+
+ TODO file List
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vue3/src/components/settings/SpaceSettings.vue b/vue3/src/components/settings/SpaceSettings.vue
index 236135767..12851a911 100644
--- a/vue3/src/components/settings/SpaceSettings.vue
+++ b/vue3/src/components/settings/SpaceSettings.vue
@@ -29,7 +29,10 @@
-
+
+
+
+
@@ -44,6 +47,7 @@ import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
import {onMounted, ref} from "vue";
import {ApiApi, Space} from "@/openapi";
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
+import UserFileField from "@/components/inputs/UserFileField.vue";
const space = ref({} as Space)
diff --git a/vue3/src/openapi/apis/ApiApi.ts b/vue3/src/openapi/apis/ApiApi.ts
index de5670439..ab0325586 100644
--- a/vue3/src/openapi/apis/ApiApi.ts
+++ b/vue3/src/openapi/apis/ApiApi.ts
@@ -1551,6 +1551,8 @@ export interface ApiUserFileCreateRequest {
fileDownload: string;
preview: string;
fileSizeKb: number;
+ createdBy: User;
+ createdAt: Date;
id?: number;
}
@@ -1575,6 +1577,8 @@ export interface ApiUserFilePartialUpdateRequest {
fileDownload?: string;
preview?: string;
fileSizeKb?: number;
+ createdBy?: User;
+ createdAt?: Date;
}
export interface ApiUserFileRetrieveRequest {
@@ -1588,6 +1592,8 @@ export interface ApiUserFileUpdateRequest {
fileDownload: string;
preview: string;
fileSizeKb: number;
+ createdBy: User;
+ createdAt: Date;
id2?: number;
}
@@ -11554,6 +11560,20 @@ export class ApiApi extends runtime.BaseAPI {
);
}
+ if (requestParameters['createdBy'] == null) {
+ throw new runtime.RequiredError(
+ 'createdBy',
+ 'Required parameter "createdBy" was null or undefined when calling apiUserFileCreate().'
+ );
+ }
+
+ if (requestParameters['createdAt'] == null) {
+ throw new runtime.RequiredError(
+ 'createdAt',
+ 'Required parameter "createdAt" was null or undefined when calling apiUserFileCreate().'
+ );
+ }
+
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
@@ -11600,6 +11620,14 @@ export class ApiApi extends runtime.BaseAPI {
formParams.append('file_size_kb', requestParameters['fileSizeKb'] as any);
}
+ if (requestParameters['createdBy'] != null) {
+ formParams.append('created_by', new Blob([JSON.stringify(UserToJSON(requestParameters['createdBy']))], { type: "application/json", }));
+ }
+
+ if (requestParameters['createdAt'] != null) {
+ formParams.append('created_at', requestParameters['createdAt'] as any);
+ }
+
const response = await this.request({
path: `/api/user-file/`,
method: 'POST',
@@ -11760,6 +11788,14 @@ export class ApiApi extends runtime.BaseAPI {
formParams.append('file_size_kb', requestParameters['fileSizeKb'] as any);
}
+ if (requestParameters['createdBy'] != null) {
+ formParams.append('created_by', new Blob([JSON.stringify(UserToJSON(requestParameters['createdBy']))], { type: "application/json", }));
+ }
+
+ if (requestParameters['createdAt'] != null) {
+ formParams.append('created_at', requestParameters['createdAt'] as any);
+ }
+
const response = await this.request({
path: `/api/user-file/{id}/`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))),
method: 'PATCH',
@@ -11858,6 +11894,20 @@ export class ApiApi extends runtime.BaseAPI {
);
}
+ if (requestParameters['createdBy'] == null) {
+ throw new runtime.RequiredError(
+ 'createdBy',
+ 'Required parameter "createdBy" was null or undefined when calling apiUserFileUpdate().'
+ );
+ }
+
+ if (requestParameters['createdAt'] == null) {
+ throw new runtime.RequiredError(
+ 'createdAt',
+ 'Required parameter "createdAt" was null or undefined when calling apiUserFileUpdate().'
+ );
+ }
+
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
@@ -11904,6 +11954,14 @@ export class ApiApi extends runtime.BaseAPI {
formParams.append('file_size_kb', requestParameters['fileSizeKb'] as any);
}
+ if (requestParameters['createdBy'] != null) {
+ formParams.append('created_by', new Blob([JSON.stringify(UserToJSON(requestParameters['createdBy']))], { type: "application/json", }));
+ }
+
+ if (requestParameters['createdAt'] != null) {
+ formParams.append('created_at', requestParameters['createdAt'] as any);
+ }
+
const response = await this.request({
path: `/api/user-file/{id}/`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))),
method: 'PUT',
diff --git a/vue3/src/openapi/models/UserFile.ts b/vue3/src/openapi/models/UserFile.ts
index 3e7810870..9f411ce91 100644
--- a/vue3/src/openapi/models/UserFile.ts
+++ b/vue3/src/openapi/models/UserFile.ts
@@ -13,6 +13,13 @@
*/
import { mapValues } from '../runtime';
+import type { User } from './User';
+import {
+ UserFromJSON,
+ UserFromJSONTyped,
+ UserToJSON,
+} from './User';
+
/**
*
* @export
@@ -55,6 +62,18 @@ export interface UserFile {
* @memberof UserFile
*/
readonly fileSizeKb: number;
+ /**
+ *
+ * @type {User}
+ * @memberof UserFile
+ */
+ readonly createdBy: User;
+ /**
+ *
+ * @type {Date}
+ * @memberof UserFile
+ */
+ readonly createdAt: Date;
}
/**
@@ -66,6 +85,8 @@ export function instanceOfUserFile(value: object): boolean {
if (!('fileDownload' in value)) return false;
if (!('preview' in value)) return false;
if (!('fileSizeKb' in value)) return false;
+ if (!('createdBy' in value)) return false;
+ if (!('createdAt' in value)) return false;
return true;
}
@@ -85,6 +106,8 @@ export function UserFileFromJSONTyped(json: any, ignoreDiscriminator: boolean):
'fileDownload': json['file_download'],
'preview': json['preview'],
'fileSizeKb': json['file_size_kb'],
+ 'createdBy': UserFromJSON(json['created_by']),
+ 'createdAt': (new Date(json['created_at'])),
};
}
diff --git a/vue3/src/openapi/models/UserFileView.ts b/vue3/src/openapi/models/UserFileView.ts
index 620dc4a2c..91bcded8b 100644
--- a/vue3/src/openapi/models/UserFileView.ts
+++ b/vue3/src/openapi/models/UserFileView.ts
@@ -13,6 +13,13 @@
*/
import { mapValues } from '../runtime';
+import type { User } from './User';
+import {
+ UserFromJSON,
+ UserFromJSONTyped,
+ UserToJSON,
+} from './User';
+
/**
*
* @export
@@ -43,6 +50,24 @@ export interface UserFileView {
* @memberof UserFileView
*/
readonly preview: string;
+ /**
+ *
+ * @type {number}
+ * @memberof UserFileView
+ */
+ readonly fileSizeKb: number;
+ /**
+ *
+ * @type {User}
+ * @memberof UserFileView
+ */
+ readonly createdBy: User;
+ /**
+ *
+ * @type {Date}
+ * @memberof UserFileView
+ */
+ readonly createdAt: Date;
}
/**
@@ -52,6 +77,9 @@ export function instanceOfUserFileView(value: object): boolean {
if (!('name' in value)) return false;
if (!('fileDownload' in value)) return false;
if (!('preview' in value)) return false;
+ if (!('fileSizeKb' in value)) return false;
+ if (!('createdBy' in value)) return false;
+ if (!('createdAt' in value)) return false;
return true;
}
@@ -69,6 +97,9 @@ export function UserFileViewFromJSONTyped(json: any, ignoreDiscriminator: boolea
'name': json['name'],
'fileDownload': json['file_download'],
'preview': json['preview'],
+ 'fileSizeKb': json['file_size_kb'],
+ 'createdBy': UserFromJSON(json['created_by']),
+ 'createdAt': (new Date(json['created_at'])),
};
}
diff --git a/vue3/yarn.lock b/vue3/yarn.lock
index 83458fed4..7a2f5ca8d 100644
--- a/vue3/yarn.lock
+++ b/vue3/yarn.lock
@@ -127,10 +127,10 @@
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c"
integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==
-"@fortawesome/fontawesome-free@^6.5.2":
- version "6.5.2"
- resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.2.tgz#310fe90cb5a8dee9698833171b98e7835404293d"
- integrity sha512-hRILoInAx8GNT5IMkrtIt9blOdrqHOnPBH+k70aWUAqPZPgopb9G5EQJFpaBx/S8zp2fC+mPW349Bziuk1o28Q==
+"@fortawesome/fontawesome-free@^6.6.0":
+ version "6.6.0"
+ resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz#0e984f0f2344ee513c185d87d77defac4c0c8224"
+ integrity sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow==
"@intlify/core-base@9.13.1":
version "9.13.1"