Skip to content

Commit

Permalink
Add support for adding a collection accent color (#5818)
Browse files Browse the repository at this point in the history
* Added icon_color to directus_collections
Added migrations
Added color property to select-icon
Fixed select-icon placeholder

* Use icon color in collection header bar.

* Set `collection` and `note` fields to hald witdh

* Rename icon_color->color

Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
  • Loading branch information
Oreilles and rijkvanzanten committed Jun 3, 2021
1 parent 09a9f56 commit 22f2e46
Show file tree
Hide file tree
Showing 14 changed files with 102 additions and 51 deletions.
@@ -0,0 +1,13 @@
import { Knex } from 'knex';

export async function up(knex: Knex): Promise<void> {
await knex.schema.alterTable('directus_collections', (table) => {
table.string('color').nullable();
});
}

export async function down(knex: Knex): Promise<void> {
await knex.schema.alterTable('directus_collections', (table) => {
table.dropColumn('color');
});
}
14 changes: 10 additions & 4 deletions api/src/database/system-data/fields/collections.yaml
Expand Up @@ -18,16 +18,22 @@ fields:
readonly: true
width: half

- field: note
interface: input
options:
placeholder: A description of this collection...
width: half

- field: icon
interface: select-icon
options:
width: half

- field: note
interface: input
- field: color
interface: select-color
options:
placeholder: A description of this collection...
width: full
placeholder: Choose a color...
width: half

- field: display_template
interface: system-display-template
Expand Down
4 changes: 4 additions & 0 deletions app/src/components/v-icon/v-icon.vue
Expand Up @@ -5,6 +5,7 @@
:role="hasClick ? 'button' : null"
@click="emitClick"
:tabindex="hasClick ? 0 : null"
:style="{ '--v-icon-color': color }"
>
<component v-if="customIconName" :is="customIconName" />
<i v-else :class="{ filled }">{{ name }}</i>
Expand Down Expand Up @@ -98,6 +99,9 @@ export default defineComponent({
type: Boolean,
default: false,
},
color: {
type: String,
},
...sizeProps,
},
Expand Down
2 changes: 1 addition & 1 deletion app/src/interfaces/select-color/select-color.vue
Expand Up @@ -3,7 +3,7 @@
<template #activator>
<v-input
:disabled="disabled"
:placeholder="$t('interfaces.color.placeholder')"
:placeholder="$t('interfaces.select-color.placeholder')"
v-model="hex"
:pattern="/#([a-f\d]{2}){3}/i"
class="color-input"
Expand Down
8 changes: 4 additions & 4 deletions app/src/modules/collections/components/navigation.vue
Expand Up @@ -11,7 +11,7 @@
v-if="(group.name === undefined || group.name === null) && group.accordion === 'always_open' && index === 0"
>
<v-list-item :exact="exact" v-for="navItem in group.items" :key="navItem.to" :to="navItem.to">
<v-list-item-icon><v-icon :name="navItem.icon" /></v-list-item-icon>
<v-list-item-icon><v-icon :name="navItem.icon" :color="navItem.color" /></v-list-item-icon>
<v-list-item-content>
<v-text-overflow :text="navItem.name" />
</v-list-item-content>
Expand All @@ -27,7 +27,7 @@
@toggle="toggleActive(group.name)"
>
<v-list-item :exact="exact" v-for="navItem in group.items" :key="navItem.to" :to="navItem.to">
<v-list-item-icon><v-icon :name="navItem.icon" /></v-list-item-icon>
<v-list-item-icon><v-icon :name="navItem.icon" :color="navItem.color" /></v-list-item-icon>
<v-list-item-content>
<v-text-overflow :text="navItem.name" />
</v-list-item-content>
Expand All @@ -38,7 +38,7 @@
</template>

<v-list-item v-else :exact="exact" v-for="navItem in navItems" :key="navItem.to" :to="navItem.to">
<v-list-item-icon><v-icon :name="navItem.icon" /></v-list-item-icon>
<v-list-item-icon><v-icon :name="navItem.icon" :color="navItem.color" /></v-list-item-icon>
<v-list-item-content>
<v-text-overflow :text="navItem.name" />
</v-list-item-content>
Expand Down Expand Up @@ -72,7 +72,7 @@
:key="navItem.to"
:to="navItem.to"
>
<v-list-item-icon><v-icon :name="navItem.icon" /></v-list-item-icon>
<v-list-item-icon><v-icon :name="navItem.icon" :color="navItem.color" /></v-list-item-icon>
<v-list-item-content>
<v-text-overflow :text="navItem.name" />
</v-list-item-content>
Expand Down
2 changes: 2 additions & 0 deletions app/src/modules/collections/composables/use-navigation.ts
Expand Up @@ -8,6 +8,7 @@ export type NavItem = {
name: string | VueI18n.TranslateResult;
to: string;
icon: string;
color: string | null | undefined;
note: string | null;
};

Expand All @@ -25,6 +26,7 @@ function collectionToNavItem(collection: Collection): NavItem {
collection: collection.collection,
name: collection.name,
icon: collection.meta?.icon || 'label',
color: collection.meta?.color,
note: collection.meta?.note || null,
to: `/collections/${collection.collection}`,
};
Expand Down
2 changes: 1 addition & 1 deletion app/src/modules/collections/routes/collection.vue
Expand Up @@ -3,7 +3,7 @@
<private-view v-else :title="bookmark ? bookmarkTitle : currentCollection.name">
<template #title-outer:prepend>
<v-button class="header-icon" rounded icon secondary disabled>
<v-icon :name="currentCollection.icon" />
<v-icon :name="currentCollection.icon" :color="currentCollection.meta.color" />
</v-button>
</template>

Expand Down
2 changes: 1 addition & 1 deletion app/src/modules/collections/routes/overview.vue
Expand Up @@ -20,7 +20,7 @@
@click:row="navigateToCollection"
>
<template #item.icon="{ item }">
<v-icon class="icon" :name="item.icon" />
<v-icon class="icon" :name="item.icon" :color="item.color" />
</template>
</v-table>

Expand Down
Expand Up @@ -45,6 +45,7 @@
unmanaged: item.meta === null && item.collection.startsWith('directus_') === false,
}"
:name="item.icon"
:color="item.meta.color"
/>
</template>

Expand Down
1 change: 1 addition & 0 deletions app/src/types/collections.ts
Expand Up @@ -14,6 +14,7 @@ export interface CollectionRaw {
hidden: boolean;
singleton: boolean;
icon: string | null;
color: string | null;
translations: Translations[] | null;
display_template: string | null;
sort_field: string | null;
Expand Down
31 changes: 21 additions & 10 deletions docs/guides/installation/iis.md
@@ -1,22 +1,30 @@
# IIS (Internet Information Services)
Deploying directus to IIS will require [iisnode](https://github.com/Azure/iisnode), an entrypoint file, and some specific web.config configurations.

Deploying directus to IIS will require [iisnode](https://github.com/Azure/iisnode), an entrypoint file, and some
specific web.config configurations.

# iisnode

iisnode can be downloaded from the [azure/iisnode releases](https://github.com/Azure/iisnode/releases) page.

## Entrypoint
iisnode acts as a reverse proxy, and simply forwards requests to files based on any rewrite rules and the files available. Since iisnode simply pipes requests to files, running the directus CLI directly won't work. To get around this, use an entrypoint script like the `index.js` below.

``` js
var { default: start } = require("directus/dist/start");
iisnode acts as a reverse proxy, and simply forwards requests to files based on any rewrite rules and the files
available. Since iisnode simply pipes requests to files, running the directus CLI directly won't work. To get around
this, use an entrypoint script like the `index.js` below.

```js
var { default: start } = require('directus/dist/start');

start();
```

## web.config
With an entrypoint created, add a web.config to the root of the project. The following web.config is a simple example of running directus with iisnode

``` xml
With an entrypoint created, add a web.config to the root of the project. The following web.config is a simple example of
running directus with iisnode

```xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
Expand All @@ -39,10 +47,13 @@ With an entrypoint created, add a web.config to the root of the project. The fol
```

A few important points regarding this file:

1. The iisnode handler `path` parameter is set to the entrypoint filepath
2. The iisnode handler `verb` parameter is set to handle all verbs (*)
2. The iisnode handler `verb` parameter is set to handle all verbs (\*)
3. The iisnode `node_env` parameter is bound to the environment variable `node_env`
4. The iisnode `enableXFF` parameter is set to `true`. Since iisnode acts as a reverse proxy, this is required to pass client ip and other details on to the directus server, which directus modules expect and depend on.
5. the rewrite rule is in place to send all requests made to this site to the entrypoint, ensuring that directus handles the routing and not IIS
4. The iisnode `enableXFF` parameter is set to `true`. Since iisnode acts as a reverse proxy, this is required to pass
client ip and other details on to the directus server, which directus modules expect and depend on.
5. the rewrite rule is in place to send all requests made to this site to the entrypoint, ensuring that directus handles
the routing and not IIS

While there are dozens even hundreds of options within IIS, this should help in getting started with Directus on IIS.
While there are dozens even hundreds of options within IIS, this should help in getting started with Directus on IIS.
18 changes: 9 additions & 9 deletions docs/reference/environment-variables.md
Expand Up @@ -48,15 +48,15 @@ All the `DB_POOL_` prefixed options are passed [to `tarn.js`](https://github.com

## Security

| Variable | Description | Default Value |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `KEY` | Unique identifier for the project. | -- |
| `SECRET` | Secret string for the project. | -- |
| `ACCESS_TOKEN_TTL` | The duration that the access token is valid. | 15m |
| `REFRESH_TOKEN_TTL` | The duration that the refresh token is valid, and also how long users stay logged-in to the App. | 7d |
| `REFRESH_TOKEN_COOKIE_DOMAIN` | Which domain to use for the refresh cookie. Useful for development mode. | -- |
| `REFRESH_TOKEN_COOKIE_SECURE` | Whether or not to use a secure cookie for the refresh token in cookie mode. | `false` |
| `REFRESH_TOKEN_COOKIE_SAME_SITE` | Value for `sameSite` in the refresh token cookie when in cookie mode. | `lax` |
| Variable | Description | Default Value |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `KEY` | Unique identifier for the project. | -- |
| `SECRET` | Secret string for the project. | -- |
| `ACCESS_TOKEN_TTL` | The duration that the access token is valid. | 15m |
| `REFRESH_TOKEN_TTL` | The duration that the refresh token is valid, and also how long users stay logged-in to the App. | 7d |
| `REFRESH_TOKEN_COOKIE_DOMAIN` | Which domain to use for the refresh cookie. Useful for development mode. | -- |
| `REFRESH_TOKEN_COOKIE_SECURE` | Whether or not to use a secure cookie for the refresh token in cookie mode. | `false` |
| `REFRESH_TOKEN_COOKIE_SAME_SITE` | Value for `sameSite` in the refresh token cookie when in cookie mode. | `lax` |
| `PASSWORD_RESET_URL_ALLOW_LIST` | List of URLs that can be used [as `reset_url` in /password/request](/reference/api/system/authentication/#request-password-reset) | -- |
| `USER_INVITE_URL_ALLOW_LIST` | List of URLs that can be used [as `invite_url` in /users/invite](/reference/api/system/users/#invite-a-new-user) | -- |

Expand Down
5 changes: 5 additions & 0 deletions packages/specs/src/components/collection.yaml
Expand Up @@ -20,6 +20,11 @@ properties:
type: string
example: people
nullable: true
color:
description: Choose an accent color for this collection.
type: string
example: '#00C897'
nullable: true
note:
description: A note describing the collection.
type: string
Expand Down
50 changes: 29 additions & 21 deletions packages/specs/src/paths/collections/collection.yaml
Expand Up @@ -3,29 +3,29 @@ get:
description: Retrieves the details of a single collection.
operationId: getCollection
parameters:
- $ref: "../../openapi.yaml#/components/parameters/Meta"
- $ref: '../../openapi.yaml#/components/parameters/Meta'
responses:
"200":
'200':
content:
application/json:
schema:
type: object
properties:
data:
$ref: "../../openapi.yaml#/components/schemas/Collections"
$ref: '../../openapi.yaml#/components/schemas/Collections'
description: Successful request
"401":
$ref: "../../openapi.yaml#/components/responses/UnauthorizedError"
"404":
$ref: "../../openapi.yaml#/components/responses/NotFoundError"
'401':
$ref: '../../openapi.yaml#/components/responses/UnauthorizedError'
'404':
$ref: '../../openapi.yaml#/components/responses/NotFoundError'
tags:
- Collections
patch:
summary: Update a Collection
description: Update an existing collection.
operationId: updateCollection
parameters:
- $ref: "../../openapi.yaml#/components/parameters/Meta"
- $ref: '../../openapi.yaml#/components/parameters/Meta'
requestBody:
content:
application/json:
Expand All @@ -41,6 +41,11 @@ patch:
type: string
example: people
nullable: true
color:
description: Choose the color for the icon assigned to this collection.
type: string
example: '#00C897'
nullable: true
note:
description: A note describing the collection.
type: string
Expand All @@ -60,7 +65,8 @@ patch:
type: boolean
example: false
translation:
description: Key value pairs of how to show this collection's name in different languages in the admin app.
description:
Key value pairs of how to show this collection's name in different languages in the admin app.
type: string
example: null
nullable: true
Expand Down Expand Up @@ -90,33 +96,35 @@ patch:
example: null
nullable: true
responses:
"200":
'200':
content:
application/json:
schema:
type: object
properties:
data:
$ref: "../../openapi.yaml#/components/schemas/Collections"
$ref: '../../openapi.yaml#/components/schemas/Collections'
description: Successful request
"401":
$ref: "../../openapi.yaml#/components/responses/UnauthorizedError"
"404":
$ref: "../../openapi.yaml#/components/responses/NotFoundError"
'401':
$ref: '../../openapi.yaml#/components/responses/UnauthorizedError'
'404':
$ref: '../../openapi.yaml#/components/responses/NotFoundError'
tags:
- Collections

delete:
summary: Delete a Collection
description: "Delete an existing collection. Warning: This will delete the whole collection, including the items within. Proceed with caution."
description:
'Delete an existing collection. Warning: This will delete the whole collection, including the items within. Proceed
with caution.'
operationId: deleteCollection
responses:
"200":
'200':
description: Successful request
"401":
$ref: "../../openapi.yaml#/components/responses/UnauthorizedError"
"404":
$ref: "../../openapi.yaml#/components/responses/NotFoundError"
'401':
$ref: '../../openapi.yaml#/components/responses/UnauthorizedError'
'404':
$ref: '../../openapi.yaml#/components/responses/NotFoundError'
tags:
- Collections

Expand Down

0 comments on commit 22f2e46

Please sign in to comment.