mirror of
https://github.com/directus/directus.git
synced 2026-02-10 21:45:02 -05:00
Merge branch 'main' of https://github.com/directus/next into main
This commit is contained in:
@@ -4,9 +4,12 @@ import ActivityService from '../services/activity';
|
||||
import MetaService from '../services/meta';
|
||||
import { Action } from '../types';
|
||||
import { ForbiddenException } from '../exceptions';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.use(useCollection('directus_activity'));
|
||||
|
||||
router.get(
|
||||
'/',
|
||||
asyncHandler(async (req, res, next) => {
|
||||
|
||||
@@ -9,9 +9,12 @@ import { pick } from 'lodash';
|
||||
import { Transformation } from '../types/assets';
|
||||
import storage from '../storage';
|
||||
import PayloadService from '../services/payload';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.use(useCollection('directus_Files'));
|
||||
|
||||
router.get(
|
||||
'/:pk',
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import ms from 'ms';
|
||||
import cookieParser from 'cookie-parser';
|
||||
import env from '../env';
|
||||
import UsersService from '../services/users';
|
||||
import { respond } from '../middleware/respond';
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
||||
@@ -7,9 +7,12 @@ import { InvalidPayloadException, ForbiddenException } from '../exceptions';
|
||||
import Joi from 'joi';
|
||||
import { Field } from '../types/field';
|
||||
import { types } from '../types';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.use(useCollection('directus_fields'));
|
||||
|
||||
router.get(
|
||||
'/',
|
||||
asyncHandler(async (req, res, next) => {
|
||||
|
||||
@@ -11,9 +11,12 @@ import Joi from 'joi';
|
||||
import { InvalidPayloadException, ForbiddenException } from '../exceptions';
|
||||
import url from 'url';
|
||||
import path from 'path';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.use(useCollection('directus_files'));
|
||||
|
||||
const multipartHandler = asyncHandler(async (req, res, next) => {
|
||||
if (req.is('multipart/form-data') === false) return next();
|
||||
|
||||
|
||||
@@ -3,9 +3,12 @@ import asyncHandler from 'express-async-handler';
|
||||
import FoldersService from '../services/folders';
|
||||
import MetaService from '../services/meta';
|
||||
import { ForbiddenException } from '../exceptions';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.use(useCollection('directus_folders'));
|
||||
|
||||
router.post(
|
||||
'/',
|
||||
asyncHandler(async (req, res, next) => {
|
||||
|
||||
@@ -4,9 +4,12 @@ import PermissionsService from '../services/permissions';
|
||||
import MetaService from '../services/meta';
|
||||
import { clone } from 'lodash';
|
||||
import { InvalidCredentialsException, ForbiddenException } from '../exceptions';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.use(useCollection('directus_permissions'));
|
||||
|
||||
router.post(
|
||||
'/',
|
||||
asyncHandler(async (req, res, next) => {
|
||||
|
||||
@@ -3,9 +3,12 @@ import asyncHandler from 'express-async-handler';
|
||||
import PresetsService from '../services/presets';
|
||||
import MetaService from '../services/meta';
|
||||
import { ForbiddenException } from '../exceptions';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.use(useCollection('directus_presets'));
|
||||
|
||||
router.post(
|
||||
'/',
|
||||
asyncHandler(async (req, res, next) => {
|
||||
|
||||
@@ -3,9 +3,12 @@ import asyncHandler from 'express-async-handler';
|
||||
import RelationsService from '../services/relations';
|
||||
import MetaService from '../services/meta';
|
||||
import { ForbiddenException } from '../exceptions';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.use(useCollection('directus_relations'));
|
||||
|
||||
router.post(
|
||||
'/',
|
||||
asyncHandler(async (req, res, next) => {
|
||||
|
||||
@@ -2,9 +2,12 @@ import express from 'express';
|
||||
import asyncHandler from 'express-async-handler';
|
||||
import RevisionsService from '../services/revisions';
|
||||
import MetaService from '../services/meta';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.use(useCollection('directus_revisions'));
|
||||
|
||||
router.get(
|
||||
'/',
|
||||
asyncHandler(async (req, res, next) => {
|
||||
|
||||
@@ -3,9 +3,12 @@ import asyncHandler from 'express-async-handler';
|
||||
import RolesService from '../services/roles';
|
||||
import MetaService from '../services/meta';
|
||||
import { ForbiddenException } from '../exceptions';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.use(useCollection('directus_roles'));
|
||||
|
||||
router.post(
|
||||
'/',
|
||||
asyncHandler(async (req, res, next) => {
|
||||
|
||||
@@ -2,9 +2,12 @@ import express from 'express';
|
||||
import asyncHandler from 'express-async-handler';
|
||||
import SettingsService from '../services/settings';
|
||||
import { ForbiddenException } from '../exceptions';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.use(useCollection('directus_settings'));
|
||||
|
||||
router.get(
|
||||
'/',
|
||||
asyncHandler(async (req, res, next) => {
|
||||
|
||||
@@ -5,9 +5,12 @@ import { InvalidPayloadException, InvalidCredentialsException, ForbiddenExceptio
|
||||
import UsersService from '../services/users';
|
||||
import MetaService from '../services/meta';
|
||||
import AuthService from '../services/authentication';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.use(useCollection('directus_users'));
|
||||
|
||||
router.post(
|
||||
'/',
|
||||
asyncHandler(async (req, res, next) => {
|
||||
|
||||
@@ -3,9 +3,12 @@ import asyncHandler from 'express-async-handler';
|
||||
import WebhooksService from '../services/webhooks';
|
||||
import MetaService from '../services/meta';
|
||||
import { ForbiddenException } from '../exceptions';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.use(useCollection('directus_webhooks'));
|
||||
|
||||
router.post(
|
||||
'/',
|
||||
asyncHandler(async (req, res, next) => {
|
||||
|
||||
@@ -4,7 +4,7 @@ import env from "../env";
|
||||
import { getCacheKey } from "../utils/get-cache-key";
|
||||
import cache from '../cache';
|
||||
import { Transform, transforms } from 'json2csv';
|
||||
import { PassThrough } from "stream";
|
||||
import { PassThrough } from 'stream';
|
||||
|
||||
export const respond: RequestHandler = asyncHandler(async (req, res) => {
|
||||
if (req.method.toLowerCase() === 'get' && env.CACHE_ENABLED === true && cache && !req.sanitizedQuery.export) {
|
||||
@@ -12,20 +12,44 @@ export const respond: RequestHandler = asyncHandler(async (req, res) => {
|
||||
await cache.set(key, res.locals.payload);
|
||||
}
|
||||
|
||||
if (req.sanitizedQuery.export === 'json') {
|
||||
res.attachment('export.json');
|
||||
res.set('Content-Type', 'application/json');
|
||||
return res.status(200).send(JSON.stringify(res.locals.payload, null, '\t'));
|
||||
}
|
||||
if (req.sanitizedQuery.export) {
|
||||
let filename = '';
|
||||
|
||||
if (req.sanitizedQuery.export === 'csv') {
|
||||
res.attachment('export.csv');
|
||||
res.set('Content-Type', 'text/csv');
|
||||
const stream = new PassThrough();
|
||||
stream.end(Buffer.from(JSON.stringify(res.locals.payload.data), 'utf-8'));
|
||||
const json2csv = new Transform({ transforms: [transforms.flatten({ separator: '.' })] });
|
||||
return stream.pipe(json2csv).pipe(res);
|
||||
if (req.collection) {
|
||||
filename += req.collection;
|
||||
} else {
|
||||
filename += 'Export';
|
||||
}
|
||||
|
||||
filename += ' ' + getDateFormatted();
|
||||
|
||||
if (req.sanitizedQuery.export === 'json') {
|
||||
res.attachment(`${filename}.json`);
|
||||
res.set('Content-Type', 'application/json');
|
||||
return res.status(200).send(JSON.stringify(res.locals.payload, null, '\t'));
|
||||
}
|
||||
|
||||
if (req.sanitizedQuery.export === 'csv') {
|
||||
res.attachment(`${filename}.csv`);
|
||||
res.set('Content-Type', 'text/csv');
|
||||
const stream = new PassThrough();
|
||||
stream.end(Buffer.from(JSON.stringify(res.locals.payload.data), 'utf-8'));
|
||||
const json2csv = new Transform({ transforms: [transforms.flatten({ separator: '.' })] });
|
||||
return stream.pipe(json2csv).pipe(res);
|
||||
}
|
||||
}
|
||||
|
||||
return res.json(res.locals.payload);
|
||||
});
|
||||
|
||||
function getDateFormatted() {
|
||||
const date = new Date();
|
||||
|
||||
let month = String(date.getMonth() + 1);
|
||||
if (month.length === 1) month = '0' + month;
|
||||
|
||||
let day = String(date.getDate());
|
||||
if (day.length === 1) day = '0' + day;
|
||||
|
||||
return `${date.getFullYear()}-${month}-${day} at ${date.getHours()}.${date.getMinutes()}.${date.getSeconds()}`;
|
||||
}
|
||||
|
||||
@@ -31,13 +31,18 @@ export const useNotificationsStore = createStore({
|
||||
|
||||
return id;
|
||||
},
|
||||
hide(id: string) {
|
||||
const toBeHidden = this.state.queue.find((n) => n.id === id);
|
||||
if (!toBeHidden) return;
|
||||
|
||||
this.state.queue = this.state.queue.filter((n) => n.id !== id);
|
||||
this.state.previous = [...this.state.previous, toBeHidden];
|
||||
},
|
||||
remove(id: string) {
|
||||
const toBeRemoved = this.state.queue.find((n) => n.id === id);
|
||||
|
||||
if (!toBeRemoved) return;
|
||||
|
||||
this.state.queue = this.state.queue.filter((n) => n.id !== id);
|
||||
this.state.previous = [...this.state.previous, toBeRemoved];
|
||||
},
|
||||
update(id: string, updates: Partial<Notification>) {
|
||||
this.state.queue = this.state.queue.map(updateIfNeeded);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<transition-expand tag="div">
|
||||
<div v-if="active" class="inline">
|
||||
<div class="padding-box">
|
||||
<router-link class="link" :to="activityLink" :class="{ 'has-items': lastFour.length > 0 }">
|
||||
<router-link class="link" to="/activity" :class="{ 'has-items': lastFour.length > 0 }">
|
||||
{{ $t('show_all_activity') }}
|
||||
</router-link>
|
||||
<transition-group tag="div" name="notification" class="transition">
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
<drawer-button
|
||||
:active="active"
|
||||
@click="active = !active"
|
||||
@click="$emit('input', !active)"
|
||||
v-tooltip.left="$t('notifications')"
|
||||
class="toggle"
|
||||
icon="notifications"
|
||||
@@ -37,28 +37,22 @@ import { useNotificationsStore } from '@/stores/';
|
||||
|
||||
export default defineComponent({
|
||||
components: { DrawerButton, NotificationItem },
|
||||
model: {
|
||||
prop: 'active',
|
||||
},
|
||||
props: {
|
||||
drawerOpen: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
active: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const notificationsStore = useNotificationsStore();
|
||||
|
||||
const activityLink = computed(() => `/activity`);
|
||||
const active = ref(false);
|
||||
|
||||
watch(
|
||||
() => props.drawerOpen,
|
||||
(open: boolean) => {
|
||||
if (open === false) {
|
||||
active.value = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return { lastFour: notificationsStore.lastFour, activityLink, active };
|
||||
return { lastFour: notificationsStore.lastFour };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -35,14 +35,14 @@
|
||||
|
||||
<div class="spacer" />
|
||||
|
||||
<notifications-preview :drawer-open="drawerOpen" />
|
||||
<notifications-preview v-model="notificationsPreviewActive" :drawer-open="drawerOpen" />
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<v-overlay class="nav-overlay" :active="navOpen" @click="navOpen = false" />
|
||||
<v-overlay class="drawer-overlay" :active="drawerOpen" @click="drawerOpen = false" />
|
||||
|
||||
<notifications-group :dense="drawerOpen === false" />
|
||||
<notifications-group v-if="notificationsPreviewActive === false" :dense="drawerOpen === false" />
|
||||
|
||||
<template v-if="showDropEffect">
|
||||
<div class="drop-border top" />
|
||||
@@ -93,6 +93,8 @@ export default defineComponent({
|
||||
const notificationsStore = useNotificationsStore();
|
||||
const appStore = useAppStore();
|
||||
|
||||
const notificationsPreviewActive = ref(false);
|
||||
|
||||
const { drawerOpen } = toRefs(appStore.state);
|
||||
|
||||
const theme = computed(() => {
|
||||
@@ -119,6 +121,7 @@ export default defineComponent({
|
||||
dragging,
|
||||
drawerOpen,
|
||||
openDrawer,
|
||||
notificationsPreviewActive,
|
||||
};
|
||||
|
||||
function useFileUpload() {
|
||||
@@ -237,10 +240,7 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
notificationsStore.remove(fileUploadNotificationID);
|
||||
|
||||
emitter.emit(Events.upload);
|
||||
|
||||
notificationsStore.remove(fileUploadNotificationID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user