Push changes
parent
41161d13e9
commit
86a68e2d96
@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx lint-staged
|
||||
@ -1,31 +1,31 @@
|
||||
apiVersion: v2
|
||||
name: planka
|
||||
description: A Helm chart to deploy Planka and it's dependencies.
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.1.23
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "1.16.2"
|
||||
|
||||
dependencies:
|
||||
- alias: postgresql
|
||||
condition: postgresql.enabled
|
||||
name: postgresql
|
||||
repository: &bitnami-repo https://charts.bitnami.com/bitnami
|
||||
version: 12.5.1
|
||||
apiVersion: v2
|
||||
name: planka
|
||||
description: A Helm chart to deploy Planka and it's dependencies.
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.1.23
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "1.16.2"
|
||||
|
||||
dependencies:
|
||||
- alias: postgresql
|
||||
condition: postgresql.enabled
|
||||
name: postgresql
|
||||
repository: &bitnami-repo https://charts.bitnami.com/bitnami
|
||||
version: 12.5.1
|
||||
|
||||
@ -1,141 +1,141 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "planka.fullname" . }}
|
||||
labels:
|
||||
{{- include "planka.labels" . | nindent 4 }}
|
||||
spec:
|
||||
{{- if not .Values.autoscaling.enabled }}
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
{{- end }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "planka.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
{{- with .Values.podAnnotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "planka.selectorLabels" . | nindent 8 }}
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "planka.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.service.containerPort | default 1337 }}
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
volumeMounts:
|
||||
- mountPath: /app/public/user-avatars
|
||||
subPath: user-avatars
|
||||
name: planka
|
||||
- mountPath: /app/public/project-background-images
|
||||
subPath: project-background-images
|
||||
name: planka
|
||||
- mountPath: /app/private/attachments
|
||||
subPath: attachments
|
||||
name: planka
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
env:
|
||||
{{- if not .Values.postgresql.enabled }}
|
||||
- name: DATABASE_URL
|
||||
value: {{ required "If the included postgresql deployment is disabled you need to define a Database URL in 'dburl'" .Values.dburl }}
|
||||
{{- else }}
|
||||
- name: DATABASE_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: planka-postgresql-svcbind-custom-user
|
||||
key: uri
|
||||
{{- end }}
|
||||
- name: BASE_URL
|
||||
{{- if .Values.baseUrl }}
|
||||
value: {{ .Values.baseUrl }}
|
||||
{{- else if .Values.ingress.enabled }}
|
||||
value: {{ printf "https://%s" (first .Values.ingress.hosts).host }}
|
||||
{{- else }}
|
||||
value: http://localhost:3000
|
||||
{{- end }}
|
||||
- name: SECRET_KEY
|
||||
value: {{ required "A secret key needs to be generated using 'openssl rand -hex 64' and assigned to secretkey." .Values.secretkey }}
|
||||
- name: TRUST_PROXY
|
||||
value: "0"
|
||||
- name: DEFAULT_ADMIN_EMAIL
|
||||
value: {{ .Values.admin_email }}
|
||||
- name: DEFAULT_ADMIN_PASSWORD
|
||||
value: {{ .Values.admin_password }}
|
||||
- name: DEFAULT_ADMIN_NAME
|
||||
value: {{ .Values.admin_name }}
|
||||
- name: DEFAULT_ADMIN_USERNAME
|
||||
value: {{ .Values.admin_username }}
|
||||
{{ range $k, $v := .Values.env }}
|
||||
- name: {{ $k | quote }}
|
||||
value: {{ $v | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.oidc.enabled }}
|
||||
{{- $secretName := default (printf "%s-oidc" (include "planka.fullname" .)) .Values.oidc.existingSecret }}
|
||||
- name: OIDC_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
key: clientId
|
||||
name: {{ $secretName }}
|
||||
- name: OIDC_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
key: clientSecret
|
||||
name: {{ $secretName }}
|
||||
- name: OIDC_ISSUER
|
||||
value: {{ required "issuerUrl is required when configuring OIDC" .Values.oidc.issuerUrl | quote }}
|
||||
- name: OIDC_SCOPES
|
||||
value: {{ join " " .Values.oidc.scopes | default "openid profile email" | quote }}
|
||||
{{- if .Values.oidc.admin.roles }}
|
||||
- name: OIDC_ADMIN_ROLES
|
||||
value: {{ join "," .Values.oidc.admin.roles | quote }}
|
||||
{{- end }}
|
||||
- name: OIDC_ROLES_ATTRIBUTE
|
||||
value: {{ .Values.oidc.admin.rolesAttribute | default "groups" | quote }}
|
||||
{{- if .Values.oidc.admin.ignoreRoles }}
|
||||
- name: OIDC_IGNORE_ROLES
|
||||
value: {{ .Values.oidc.admin.ignoreRoles | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: planka
|
||||
{{- if .Values.persistence.enabled }}
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .Values.persistence.existingClaim | default (include "planka.fullname" .) }}
|
||||
{{- else }}
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "planka.fullname" . }}
|
||||
labels:
|
||||
{{- include "planka.labels" . | nindent 4 }}
|
||||
spec:
|
||||
{{- if not .Values.autoscaling.enabled }}
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
{{- end }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "planka.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
{{- with .Values.podAnnotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "planka.selectorLabels" . | nindent 8 }}
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "planka.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.service.containerPort | default 1337 }}
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
volumeMounts:
|
||||
- mountPath: /app/public/user-avatars
|
||||
subPath: user-avatars
|
||||
name: planka
|
||||
- mountPath: /app/public/project-background-images
|
||||
subPath: project-background-images
|
||||
name: planka
|
||||
- mountPath: /app/private/attachments
|
||||
subPath: attachments
|
||||
name: planka
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
env:
|
||||
{{- if not .Values.postgresql.enabled }}
|
||||
- name: DATABASE_URL
|
||||
value: {{ required "If the included postgresql deployment is disabled you need to define a Database URL in 'dburl'" .Values.dburl }}
|
||||
{{- else }}
|
||||
- name: DATABASE_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: planka-postgresql-svcbind-custom-user
|
||||
key: uri
|
||||
{{- end }}
|
||||
- name: BASE_URL
|
||||
{{- if .Values.baseUrl }}
|
||||
value: {{ .Values.baseUrl }}
|
||||
{{- else if .Values.ingress.enabled }}
|
||||
value: {{ printf "https://%s" (first .Values.ingress.hosts).host }}
|
||||
{{- else }}
|
||||
value: http://localhost:3000
|
||||
{{- end }}
|
||||
- name: SECRET_KEY
|
||||
value: {{ required "A secret key needs to be generated using 'openssl rand -hex 64' and assigned to secretkey." .Values.secretkey }}
|
||||
- name: TRUST_PROXY
|
||||
value: "0"
|
||||
- name: DEFAULT_ADMIN_EMAIL
|
||||
value: {{ .Values.admin_email }}
|
||||
- name: DEFAULT_ADMIN_PASSWORD
|
||||
value: {{ .Values.admin_password }}
|
||||
- name: DEFAULT_ADMIN_NAME
|
||||
value: {{ .Values.admin_name }}
|
||||
- name: DEFAULT_ADMIN_USERNAME
|
||||
value: {{ .Values.admin_username }}
|
||||
{{ range $k, $v := .Values.env }}
|
||||
- name: {{ $k | quote }}
|
||||
value: {{ $v | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.oidc.enabled }}
|
||||
{{- $secretName := default (printf "%s-oidc" (include "planka.fullname" .)) .Values.oidc.existingSecret }}
|
||||
- name: OIDC_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
key: clientId
|
||||
name: {{ $secretName }}
|
||||
- name: OIDC_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
key: clientSecret
|
||||
name: {{ $secretName }}
|
||||
- name: OIDC_ISSUER
|
||||
value: {{ required "issuerUrl is required when configuring OIDC" .Values.oidc.issuerUrl | quote }}
|
||||
- name: OIDC_SCOPES
|
||||
value: {{ join " " .Values.oidc.scopes | default "openid profile email" | quote }}
|
||||
{{- if .Values.oidc.admin.roles }}
|
||||
- name: OIDC_ADMIN_ROLES
|
||||
value: {{ join "," .Values.oidc.admin.roles | quote }}
|
||||
{{- end }}
|
||||
- name: OIDC_ROLES_ATTRIBUTE
|
||||
value: {{ .Values.oidc.admin.rolesAttribute | default "groups" | quote }}
|
||||
{{- if .Values.oidc.admin.ignoreRoles }}
|
||||
- name: OIDC_IGNORE_ROLES
|
||||
value: {{ .Values.oidc.admin.ignoreRoles | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: planka
|
||||
{{- if .Values.persistence.enabled }}
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .Values.persistence.existingClaim | default (include "planka.fullname" .) }}
|
||||
{{- else }}
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
|
||||
@ -1,182 +1,182 @@
|
||||
# Default values for planka.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: ghcr.io/plankanban/planka
|
||||
pullPolicy: IfNotPresent
|
||||
# Overrides the image tag whose default is the chart appVersion.
|
||||
tag: ""
|
||||
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
# Generate a secret using openssl rand -base64 45
|
||||
secretkey: ""
|
||||
|
||||
# Base url for Planka. Will override `ingress.hosts[0].host`
|
||||
# Defaults to `http://localhost:3000` if ingress is disabled.
|
||||
baseUrl: ""
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
create: true
|
||||
# Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
name: ""
|
||||
|
||||
podAnnotations: {}
|
||||
|
||||
podSecurityContext: {}
|
||||
# fsGroup: 2000
|
||||
|
||||
securityContext: {}
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
# readOnlyRootFilesystem: true
|
||||
# runAsNonRoot: true
|
||||
# runAsUser: 1000
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 1337
|
||||
## @param service.containerPort Planka HTTP container port
|
||||
## If empty will default to 1337
|
||||
##
|
||||
containerPort: 1337
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
className: ""
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
# Used to set planka BASE_URL if no `baseurl` is provided.
|
||||
- host: planka.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
tls: []
|
||||
# - secretName: planka-tls
|
||||
# hosts:
|
||||
# - planka.local
|
||||
|
||||
resources: {}
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 1
|
||||
maxReplicas: 100
|
||||
targetCPUUtilizationPercentage: 80
|
||||
# targetMemoryUtilizationPercentage: 80
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
|
||||
postgresql:
|
||||
enabled: true
|
||||
auth:
|
||||
database: planka
|
||||
username: planka
|
||||
password: ""
|
||||
postgresPassword: ""
|
||||
replicationPassword: ""
|
||||
# existingSecret: planka-postgresql
|
||||
serviceBindings:
|
||||
enabled: true
|
||||
|
||||
## Set this if you disable the built-in postgresql deployment
|
||||
dburl:
|
||||
|
||||
## PVC-based data storage configuration
|
||||
persistence:
|
||||
enabled: false
|
||||
# existingClaim: netbox-data
|
||||
# storageClass: "-"
|
||||
accessMode: ReadWriteOnce
|
||||
size: 10Gi
|
||||
|
||||
## OpenID Identity Management configuration
|
||||
##
|
||||
## Example:
|
||||
## ---------------
|
||||
## oidc:
|
||||
## enabled: true
|
||||
## clientId: sxxaAIAxVXlCxTmc1YLHBbQr8NL8MqLI2DUbt42d
|
||||
## clientSecret: om4RTMRVHRszU7bqxB7RZNkHIzA8e4sGYWxeCwIMYQXPwEBWe4SY5a0wwCe9ltB3zrq5f0dnFnp34cEHD7QSMHsKvV9AiV5Z7eqDraMnv0I8IFivmuV5wovAECAYreSI
|
||||
## issuerUrl: https://auth.local/application/o/planka/
|
||||
## admin:
|
||||
## roles:
|
||||
## - planka-admin
|
||||
##
|
||||
## ---------------
|
||||
## NOTE: A minimal configuration requires setting `clientId`, `clientSecret` and `issuerUrl`. (plus `admin.roles` for administrators)
|
||||
## ref: https://docs.planka.cloud/docs/Configuration/OIDC
|
||||
##
|
||||
oidc:
|
||||
## @param oidc.enabled Enable single sign-on (SSO) with OpenID Connect (OIDC)
|
||||
##
|
||||
enabled: false
|
||||
|
||||
## OIDC credentials
|
||||
## @param oidc.clientId A string unique to the provider that identifies your app.
|
||||
## @param oidc.clientSecret A secret string that the provider uses to confirm ownership of a client ID.
|
||||
##
|
||||
## NOTE: Either specify inline `clientId` and `clientSecret` or refer to them via `existingSecret`
|
||||
##
|
||||
clientId: ""
|
||||
clientSecret: ""
|
||||
|
||||
## @param oidc.existingSecret Name of an existing secret containing OIDC credentials
|
||||
## NOTE: Must contain key `clientId` and `clientSecret`
|
||||
## NOTE: When it's set, the `clientId` and `clientSecret` parameters are ignored
|
||||
##
|
||||
existingSecret: ""
|
||||
|
||||
## @param oidc.issuerUrl The OpenID connect metadata document endpoint
|
||||
##
|
||||
issuerUrl: ""
|
||||
|
||||
## @param oidc.scopes A list of scopes required for OIDC client.
|
||||
## If empty will default to `openid`, `profile` and `email`
|
||||
## NOTE: Planka needs the email and name claims
|
||||
##
|
||||
scopes: []
|
||||
|
||||
## Admin permissions configuration
|
||||
admin:
|
||||
## @param oidc.admin.ignoreRoles If set to true, the admin roles will be ignored.
|
||||
## It is useful if you want to use OIDC for authentication but not for authorization.
|
||||
## If empty will default to `false`
|
||||
##
|
||||
ignoreRoles: false
|
||||
|
||||
## @param oidc.admin.rolesAttribute The name of a custom group claim that you have configured in your OIDC provider
|
||||
## If empty will default to `groups`
|
||||
##
|
||||
rolesAttribute: groups
|
||||
|
||||
## @param oidc.admin.roles The names of the admin groups
|
||||
##
|
||||
roles: []
|
||||
# - planka-admin
|
||||
# Default values for planka.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: ghcr.io/plankanban/planka
|
||||
pullPolicy: IfNotPresent
|
||||
# Overrides the image tag whose default is the chart appVersion.
|
||||
tag: ""
|
||||
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
# Generate a secret using openssl rand -base64 45
|
||||
secretkey: ""
|
||||
|
||||
# Base url for Planka. Will override `ingress.hosts[0].host`
|
||||
# Defaults to `http://localhost:3000` if ingress is disabled.
|
||||
baseUrl: ""
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
create: true
|
||||
# Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
name: ""
|
||||
|
||||
podAnnotations: {}
|
||||
|
||||
podSecurityContext: {}
|
||||
# fsGroup: 2000
|
||||
|
||||
securityContext: {}
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
# readOnlyRootFilesystem: true
|
||||
# runAsNonRoot: true
|
||||
# runAsUser: 1000
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 1337
|
||||
## @param service.containerPort Planka HTTP container port
|
||||
## If empty will default to 1337
|
||||
##
|
||||
containerPort: 1337
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
className: ""
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
# Used to set planka BASE_URL if no `baseurl` is provided.
|
||||
- host: planka.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
tls: []
|
||||
# - secretName: planka-tls
|
||||
# hosts:
|
||||
# - planka.local
|
||||
|
||||
resources: {}
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 1
|
||||
maxReplicas: 100
|
||||
targetCPUUtilizationPercentage: 80
|
||||
# targetMemoryUtilizationPercentage: 80
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
|
||||
postgresql:
|
||||
enabled: true
|
||||
auth:
|
||||
database: planka
|
||||
username: planka
|
||||
password: ""
|
||||
postgresPassword: ""
|
||||
replicationPassword: ""
|
||||
# existingSecret: planka-postgresql
|
||||
serviceBindings:
|
||||
enabled: true
|
||||
|
||||
## Set this if you disable the built-in postgresql deployment
|
||||
dburl:
|
||||
|
||||
## PVC-based data storage configuration
|
||||
persistence:
|
||||
enabled: false
|
||||
# existingClaim: netbox-data
|
||||
# storageClass: "-"
|
||||
accessMode: ReadWriteOnce
|
||||
size: 10Gi
|
||||
|
||||
## OpenID Identity Management configuration
|
||||
##
|
||||
## Example:
|
||||
## ---------------
|
||||
## oidc:
|
||||
## enabled: true
|
||||
## clientId: sxxaAIAxVXlCxTmc1YLHBbQr8NL8MqLI2DUbt42d
|
||||
## clientSecret: om4RTMRVHRszU7bqxB7RZNkHIzA8e4sGYWxeCwIMYQXPwEBWe4SY5a0wwCe9ltB3zrq5f0dnFnp34cEHD7QSMHsKvV9AiV5Z7eqDraMnv0I8IFivmuV5wovAECAYreSI
|
||||
## issuerUrl: https://auth.local/application/o/planka/
|
||||
## admin:
|
||||
## roles:
|
||||
## - planka-admin
|
||||
##
|
||||
## ---------------
|
||||
## NOTE: A minimal configuration requires setting `clientId`, `clientSecret` and `issuerUrl`. (plus `admin.roles` for administrators)
|
||||
## ref: https://docs.planka.cloud/docs/Configuration/OIDC
|
||||
##
|
||||
oidc:
|
||||
## @param oidc.enabled Enable single sign-on (SSO) with OpenID Connect (OIDC)
|
||||
##
|
||||
enabled: false
|
||||
|
||||
## OIDC credentials
|
||||
## @param oidc.clientId A string unique to the provider that identifies your app.
|
||||
## @param oidc.clientSecret A secret string that the provider uses to confirm ownership of a client ID.
|
||||
##
|
||||
## NOTE: Either specify inline `clientId` and `clientSecret` or refer to them via `existingSecret`
|
||||
##
|
||||
clientId: ""
|
||||
clientSecret: ""
|
||||
|
||||
## @param oidc.existingSecret Name of an existing secret containing OIDC credentials
|
||||
## NOTE: Must contain key `clientId` and `clientSecret`
|
||||
## NOTE: When it's set, the `clientId` and `clientSecret` parameters are ignored
|
||||
##
|
||||
existingSecret: ""
|
||||
|
||||
## @param oidc.issuerUrl The OpenID connect metadata document endpoint
|
||||
##
|
||||
issuerUrl: ""
|
||||
|
||||
## @param oidc.scopes A list of scopes required for OIDC client.
|
||||
## If empty will default to `openid`, `profile` and `email`
|
||||
## NOTE: Planka needs the email and name claims
|
||||
##
|
||||
scopes: []
|
||||
|
||||
## Admin permissions configuration
|
||||
admin:
|
||||
## @param oidc.admin.ignoreRoles If set to true, the admin roles will be ignored.
|
||||
## It is useful if you want to use OIDC for authentication but not for authorization.
|
||||
## If empty will default to `false`
|
||||
##
|
||||
ignoreRoles: false
|
||||
|
||||
## @param oidc.admin.rolesAttribute The name of a custom group claim that you have configured in your OIDC provider
|
||||
## If empty will default to `groups`
|
||||
##
|
||||
rolesAttribute: groups
|
||||
|
||||
## @param oidc.admin.roles The names of the admin groups
|
||||
##
|
||||
roles: []
|
||||
# - planka-admin
|
||||
|
||||
@ -1 +1 @@
|
||||
REACT_APP_VERSION=1.16.2
|
||||
REACT_APP_VERSION=1.16.2
|
||||
|
||||
@ -1,132 +1,132 @@
|
||||
import ActionTypes from '../constants/ActionTypes';
|
||||
|
||||
const createCard = (card) => ({
|
||||
type: ActionTypes.CARD_CREATE,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
createCard.success = (localId, card) => ({
|
||||
type: ActionTypes.CARD_CREATE__SUCCESS,
|
||||
payload: {
|
||||
localId,
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
createCard.failure = (localId, error) => ({
|
||||
type: ActionTypes.CARD_CREATE__FAILURE,
|
||||
payload: {
|
||||
localId,
|
||||
error,
|
||||
},
|
||||
});
|
||||
|
||||
const handleCardCreate = (card, cardMemberships, cardLabels, tasks, attachments) => ({
|
||||
type: ActionTypes.CARD_CREATE_HANDLE,
|
||||
payload: {
|
||||
card,
|
||||
cardMemberships,
|
||||
cardLabels,
|
||||
tasks,
|
||||
attachments,
|
||||
},
|
||||
});
|
||||
|
||||
const updateCard = (id, data) => ({
|
||||
type: ActionTypes.CARD_UPDATE,
|
||||
payload: {
|
||||
id,
|
||||
data,
|
||||
},
|
||||
});
|
||||
|
||||
updateCard.success = (card) => ({
|
||||
type: ActionTypes.CARD_UPDATE__SUCCESS,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
updateCard.failure = (id, error) => ({
|
||||
type: ActionTypes.CARD_UPDATE__FAILURE,
|
||||
payload: {
|
||||
id,
|
||||
error,
|
||||
},
|
||||
});
|
||||
|
||||
const handleCardUpdate = (card) => ({
|
||||
type: ActionTypes.CARD_UPDATE_HANDLE,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
const duplicateCard = (id, card, taskIds) => ({
|
||||
type: ActionTypes.CARD_DUPLICATE,
|
||||
payload: {
|
||||
id,
|
||||
card,
|
||||
taskIds,
|
||||
},
|
||||
});
|
||||
|
||||
duplicateCard.success = (localId, card, cardMemberships, cardLabels, tasks) => ({
|
||||
type: ActionTypes.CARD_DUPLICATE__SUCCESS,
|
||||
payload: {
|
||||
localId,
|
||||
card,
|
||||
cardMemberships,
|
||||
cardLabels,
|
||||
tasks,
|
||||
},
|
||||
});
|
||||
|
||||
duplicateCard.failure = (id, error) => ({
|
||||
type: ActionTypes.CARD_DUPLICATE__FAILURE,
|
||||
payload: {
|
||||
id,
|
||||
error,
|
||||
},
|
||||
});
|
||||
|
||||
const deleteCard = (id) => ({
|
||||
type: ActionTypes.CARD_DELETE,
|
||||
payload: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
|
||||
deleteCard.success = (card) => ({
|
||||
type: ActionTypes.CARD_DELETE__SUCCESS,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
deleteCard.failure = (id, error) => ({
|
||||
type: ActionTypes.CARD_DELETE__FAILURE,
|
||||
payload: {
|
||||
id,
|
||||
error,
|
||||
},
|
||||
});
|
||||
|
||||
const handleCardDelete = (card) => ({
|
||||
type: ActionTypes.CARD_DELETE_HANDLE,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
export default {
|
||||
createCard,
|
||||
handleCardCreate,
|
||||
updateCard,
|
||||
handleCardUpdate,
|
||||
duplicateCard,
|
||||
deleteCard,
|
||||
handleCardDelete,
|
||||
};
|
||||
import ActionTypes from '../constants/ActionTypes';
|
||||
|
||||
const createCard = (card) => ({
|
||||
type: ActionTypes.CARD_CREATE,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
createCard.success = (localId, card) => ({
|
||||
type: ActionTypes.CARD_CREATE__SUCCESS,
|
||||
payload: {
|
||||
localId,
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
createCard.failure = (localId, error) => ({
|
||||
type: ActionTypes.CARD_CREATE__FAILURE,
|
||||
payload: {
|
||||
localId,
|
||||
error,
|
||||
},
|
||||
});
|
||||
|
||||
const handleCardCreate = (card, cardMemberships, cardLabels, tasks, attachments) => ({
|
||||
type: ActionTypes.CARD_CREATE_HANDLE,
|
||||
payload: {
|
||||
card,
|
||||
cardMemberships,
|
||||
cardLabels,
|
||||
tasks,
|
||||
attachments,
|
||||
},
|
||||
});
|
||||
|
||||
const updateCard = (id, data) => ({
|
||||
type: ActionTypes.CARD_UPDATE,
|
||||
payload: {
|
||||
id,
|
||||
data,
|
||||
},
|
||||
});
|
||||
|
||||
updateCard.success = (card) => ({
|
||||
type: ActionTypes.CARD_UPDATE__SUCCESS,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
updateCard.failure = (id, error) => ({
|
||||
type: ActionTypes.CARD_UPDATE__FAILURE,
|
||||
payload: {
|
||||
id,
|
||||
error,
|
||||
},
|
||||
});
|
||||
|
||||
const handleCardUpdate = (card) => ({
|
||||
type: ActionTypes.CARD_UPDATE_HANDLE,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
const duplicateCard = (id, card, taskIds) => ({
|
||||
type: ActionTypes.CARD_DUPLICATE,
|
||||
payload: {
|
||||
id,
|
||||
card,
|
||||
taskIds,
|
||||
},
|
||||
});
|
||||
|
||||
duplicateCard.success = (localId, card, cardMemberships, cardLabels, tasks) => ({
|
||||
type: ActionTypes.CARD_DUPLICATE__SUCCESS,
|
||||
payload: {
|
||||
localId,
|
||||
card,
|
||||
cardMemberships,
|
||||
cardLabels,
|
||||
tasks,
|
||||
},
|
||||
});
|
||||
|
||||
duplicateCard.failure = (id, error) => ({
|
||||
type: ActionTypes.CARD_DUPLICATE__FAILURE,
|
||||
payload: {
|
||||
id,
|
||||
error,
|
||||
},
|
||||
});
|
||||
|
||||
const deleteCard = (id) => ({
|
||||
type: ActionTypes.CARD_DELETE,
|
||||
payload: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
|
||||
deleteCard.success = (card) => ({
|
||||
type: ActionTypes.CARD_DELETE__SUCCESS,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
deleteCard.failure = (id, error) => ({
|
||||
type: ActionTypes.CARD_DELETE__FAILURE,
|
||||
payload: {
|
||||
id,
|
||||
error,
|
||||
},
|
||||
});
|
||||
|
||||
const handleCardDelete = (card) => ({
|
||||
type: ActionTypes.CARD_DELETE_HANDLE,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
export default {
|
||||
createCard,
|
||||
handleCardCreate,
|
||||
updateCard,
|
||||
handleCardUpdate,
|
||||
duplicateCard,
|
||||
deleteCard,
|
||||
handleCardDelete,
|
||||
};
|
||||
|
||||
@ -1,94 +1,94 @@
|
||||
import socket from './socket';
|
||||
import { transformAttachment } from './attachments';
|
||||
|
||||
/* Transformers */
|
||||
|
||||
export const transformCard = (card) => ({
|
||||
...card,
|
||||
...(card.dueDate && {
|
||||
dueDate: new Date(card.dueDate),
|
||||
}),
|
||||
...(card.stopwatch && {
|
||||
stopwatch: {
|
||||
...card.stopwatch,
|
||||
...(card.stopwatch.startedAt && {
|
||||
startedAt: new Date(card.stopwatch.startedAt),
|
||||
}),
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
export const transformCardData = (data) => ({
|
||||
...data,
|
||||
...(data.dueDate && {
|
||||
dueDate: data.dueDate.toISOString(),
|
||||
}),
|
||||
...(data.stopwatch && {
|
||||
stopwatch: {
|
||||
...data.stopwatch,
|
||||
...(data.stopwatch.startedAt && {
|
||||
startedAt: data.stopwatch.startedAt.toISOString(),
|
||||
}),
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
/* Actions */
|
||||
|
||||
const createCard = (listId, data, headers) =>
|
||||
socket.post(`/lists/${listId}/cards`, transformCardData(data), headers).then((body) => ({
|
||||
...body,
|
||||
item: transformCard(body.item),
|
||||
}));
|
||||
|
||||
const getCard = (id, headers) =>
|
||||
socket.get(`/cards/${id}`, undefined, headers).then((body) => ({
|
||||
...body,
|
||||
item: transformCard(body.item),
|
||||
included: {
|
||||
...body.included,
|
||||
attachments: body.included.attachments.map(transformAttachment),
|
||||
},
|
||||
}));
|
||||
|
||||
const updateCard = (id, data, headers) =>
|
||||
socket.patch(`/cards/${id}`, transformCardData(data), headers).then((body) => ({
|
||||
...body,
|
||||
item: transformCard(body.item),
|
||||
}));
|
||||
|
||||
const duplicateCard = (id, data, headers) =>
|
||||
socket.post(`/cards/${id}/duplicate`, data, headers).then((body) => ({
|
||||
...body,
|
||||
item: transformCard(body.item),
|
||||
}));
|
||||
|
||||
const deleteCard = (id, headers) =>
|
||||
socket.delete(`/cards/${id}`, undefined, headers).then((body) => ({
|
||||
...body,
|
||||
item: transformCard(body.item),
|
||||
}));
|
||||
|
||||
/* Event handlers */
|
||||
|
||||
const makeHandleCardCreate = (next) => (body) => {
|
||||
next({
|
||||
...body,
|
||||
item: transformCard(body.item),
|
||||
});
|
||||
};
|
||||
|
||||
const makeHandleCardUpdate = makeHandleCardCreate;
|
||||
|
||||
const makeHandleCardDelete = makeHandleCardCreate;
|
||||
|
||||
export default {
|
||||
createCard,
|
||||
getCard,
|
||||
updateCard,
|
||||
deleteCard,
|
||||
duplicateCard,
|
||||
makeHandleCardCreate,
|
||||
makeHandleCardUpdate,
|
||||
makeHandleCardDelete,
|
||||
};
|
||||
import socket from './socket';
|
||||
import { transformAttachment } from './attachments';
|
||||
|
||||
/* Transformers */
|
||||
|
||||
export const transformCard = (card) => ({
|
||||
...card,
|
||||
...(card.dueDate && {
|
||||
dueDate: new Date(card.dueDate),
|
||||
}),
|
||||
...(card.stopwatch && {
|
||||
stopwatch: {
|
||||
...card.stopwatch,
|
||||
...(card.stopwatch.startedAt && {
|
||||
startedAt: new Date(card.stopwatch.startedAt),
|
||||
}),
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
export const transformCardData = (data) => ({
|
||||
...data,
|
||||
...(data.dueDate && {
|
||||
dueDate: data.dueDate.toISOString(),
|
||||
}),
|
||||
...(data.stopwatch && {
|
||||
stopwatch: {
|
||||
...data.stopwatch,
|
||||
...(data.stopwatch.startedAt && {
|
||||
startedAt: data.stopwatch.startedAt.toISOString(),
|
||||
}),
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
/* Actions */
|
||||
|
||||
const createCard = (listId, data, headers) =>
|
||||
socket.post(`/lists/${listId}/cards`, transformCardData(data), headers).then((body) => ({
|
||||
...body,
|
||||
item: transformCard(body.item),
|
||||
}));
|
||||
|
||||
const getCard = (id, headers) =>
|
||||
socket.get(`/cards/${id}`, undefined, headers).then((body) => ({
|
||||
...body,
|
||||
item: transformCard(body.item),
|
||||
included: {
|
||||
...body.included,
|
||||
attachments: body.included.attachments.map(transformAttachment),
|
||||
},
|
||||
}));
|
||||
|
||||
const updateCard = (id, data, headers) =>
|
||||
socket.patch(`/cards/${id}`, transformCardData(data), headers).then((body) => ({
|
||||
...body,
|
||||
item: transformCard(body.item),
|
||||
}));
|
||||
|
||||
const duplicateCard = (id, data, headers) =>
|
||||
socket.post(`/cards/${id}/duplicate`, data, headers).then((body) => ({
|
||||
...body,
|
||||
item: transformCard(body.item),
|
||||
}));
|
||||
|
||||
const deleteCard = (id, headers) =>
|
||||
socket.delete(`/cards/${id}`, undefined, headers).then((body) => ({
|
||||
...body,
|
||||
item: transformCard(body.item),
|
||||
}));
|
||||
|
||||
/* Event handlers */
|
||||
|
||||
const makeHandleCardCreate = (next) => (body) => {
|
||||
next({
|
||||
...body,
|
||||
item: transformCard(body.item),
|
||||
});
|
||||
};
|
||||
|
||||
const makeHandleCardUpdate = makeHandleCardCreate;
|
||||
|
||||
const makeHandleCardDelete = makeHandleCardCreate;
|
||||
|
||||
export default {
|
||||
createCard,
|
||||
getCard,
|
||||
updateCard,
|
||||
deleteCard,
|
||||
duplicateCard,
|
||||
makeHandleCardCreate,
|
||||
makeHandleCardUpdate,
|
||||
makeHandleCardDelete,
|
||||
};
|
||||
|
||||
@ -1,260 +1,260 @@
|
||||
import pick from 'lodash/pick';
|
||||
import React, { useCallback } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Menu } from 'semantic-ui-react';
|
||||
import { Popup } from '../../lib/custom-ui';
|
||||
|
||||
import { useSteps } from '../../hooks';
|
||||
import BoardMembershipsStep from '../BoardMembershipsStep';
|
||||
import LabelsStep from '../LabelsStep';
|
||||
import DueDateEditStep from '../DueDateEditStep';
|
||||
import StopwatchEditStep from '../StopwatchEditStep';
|
||||
import CardMoveStep from '../CardMoveStep';
|
||||
import DeleteStep from '../DeleteStep';
|
||||
|
||||
import styles from './ActionsStep.module.scss';
|
||||
|
||||
const StepTypes = {
|
||||
USERS: 'USERS',
|
||||
LABELS: 'LABELS',
|
||||
EDIT_DUE_DATE: 'EDIT_DUE_DATE',
|
||||
EDIT_STOPWATCH: 'EDIT_STOPWATCH',
|
||||
MOVE: 'MOVE',
|
||||
DELETE: 'DELETE',
|
||||
};
|
||||
|
||||
const ActionsStep = React.memo(
|
||||
({
|
||||
card,
|
||||
projectsToLists,
|
||||
boardMemberships,
|
||||
currentUserIds,
|
||||
labels,
|
||||
currentLabelIds,
|
||||
onNameEdit,
|
||||
onUpdate,
|
||||
onMove,
|
||||
onTransfer,
|
||||
onDuplicate,
|
||||
onDelete,
|
||||
onUserAdd,
|
||||
onUserRemove,
|
||||
onBoardFetch,
|
||||
onLabelAdd,
|
||||
onLabelRemove,
|
||||
onLabelCreate,
|
||||
onLabelUpdate,
|
||||
onLabelMove,
|
||||
onLabelDelete,
|
||||
onClose,
|
||||
}) => {
|
||||
const [t] = useTranslation();
|
||||
const [step, openStep, handleBack] = useSteps();
|
||||
|
||||
const handleEditNameClick = useCallback(() => {
|
||||
onNameEdit();
|
||||
onClose();
|
||||
}, [onNameEdit, onClose]);
|
||||
|
||||
const handleUsersClick = useCallback(() => {
|
||||
openStep(StepTypes.USERS);
|
||||
}, [openStep]);
|
||||
|
||||
const handleLabelsClick = useCallback(() => {
|
||||
openStep(StepTypes.LABELS);
|
||||
}, [openStep]);
|
||||
|
||||
const handleEditDueDateClick = useCallback(() => {
|
||||
openStep(StepTypes.EDIT_DUE_DATE);
|
||||
}, [openStep]);
|
||||
|
||||
const handleEditStopwatchClick = useCallback(() => {
|
||||
openStep(StepTypes.EDIT_STOPWATCH);
|
||||
}, [openStep]);
|
||||
|
||||
const handleMoveClick = useCallback(() => {
|
||||
openStep(StepTypes.MOVE);
|
||||
}, [openStep]);
|
||||
|
||||
const handleDuplicateClick = useCallback(() => {
|
||||
onDuplicate();
|
||||
onClose();
|
||||
}, [onDuplicate, onClose]);
|
||||
|
||||
const handleDeleteClick = useCallback(() => {
|
||||
openStep(StepTypes.DELETE);
|
||||
}, [openStep]);
|
||||
|
||||
const handleDueDateUpdate = useCallback(
|
||||
(dueDate) => {
|
||||
onUpdate({
|
||||
dueDate,
|
||||
});
|
||||
},
|
||||
[onUpdate],
|
||||
);
|
||||
|
||||
const handleStopwatchUpdate = useCallback(
|
||||
(stopwatch) => {
|
||||
onUpdate({
|
||||
stopwatch,
|
||||
});
|
||||
},
|
||||
[onUpdate],
|
||||
);
|
||||
|
||||
if (step) {
|
||||
switch (step.type) {
|
||||
case StepTypes.USERS:
|
||||
return (
|
||||
<BoardMembershipsStep
|
||||
items={boardMemberships}
|
||||
currentUserIds={currentUserIds}
|
||||
onUserSelect={onUserAdd}
|
||||
onUserDeselect={onUserRemove}
|
||||
onBack={handleBack}
|
||||
/>
|
||||
);
|
||||
case StepTypes.LABELS:
|
||||
return (
|
||||
<LabelsStep
|
||||
items={labels}
|
||||
currentIds={currentLabelIds}
|
||||
onSelect={onLabelAdd}
|
||||
onDeselect={onLabelRemove}
|
||||
onCreate={onLabelCreate}
|
||||
onUpdate={onLabelUpdate}
|
||||
onMove={onLabelMove}
|
||||
onDelete={onLabelDelete}
|
||||
onBack={handleBack}
|
||||
/>
|
||||
);
|
||||
case StepTypes.EDIT_DUE_DATE:
|
||||
return (
|
||||
<DueDateEditStep
|
||||
defaultValue={card.dueDate}
|
||||
onUpdate={handleDueDateUpdate}
|
||||
onBack={handleBack}
|
||||
onClose={onClose}
|
||||
/>
|
||||
);
|
||||
case StepTypes.EDIT_STOPWATCH:
|
||||
return (
|
||||
<StopwatchEditStep
|
||||
defaultValue={card.stopwatch}
|
||||
onUpdate={handleStopwatchUpdate}
|
||||
onBack={handleBack}
|
||||
onClose={onClose}
|
||||
/>
|
||||
);
|
||||
case StepTypes.MOVE:
|
||||
return (
|
||||
<CardMoveStep
|
||||
projectsToLists={projectsToLists}
|
||||
defaultPath={pick(card, ['projectId', 'boardId', 'listId'])}
|
||||
onMove={onMove}
|
||||
onTransfer={onTransfer}
|
||||
onBoardFetch={onBoardFetch}
|
||||
onBack={handleBack}
|
||||
onClose={onClose}
|
||||
/>
|
||||
);
|
||||
case StepTypes.DELETE:
|
||||
return (
|
||||
<DeleteStep
|
||||
title="common.deleteCard"
|
||||
content="common.areYouSureYouWantToDeleteThisCard"
|
||||
buttonContent="action.deleteCard"
|
||||
onConfirm={onDelete}
|
||||
onBack={handleBack}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Popup.Header>
|
||||
{t('common.cardActions', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Popup.Header>
|
||||
<Popup.Content>
|
||||
<Menu secondary vertical className={styles.menu}>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleEditNameClick}>
|
||||
{t('action.editTitle', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleUsersClick}>
|
||||
{t('common.members', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleLabelsClick}>
|
||||
{t('common.labels', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleEditDueDateClick}>
|
||||
{t('action.editDueDate', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleEditStopwatchClick}>
|
||||
{t('action.editStopwatch', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleMoveClick}>
|
||||
{t('action.moveCard', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleDuplicateClick}>
|
||||
{t('action.duplicateCard', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleDeleteClick}>
|
||||
{t('action.deleteCard', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</Popup.Content>
|
||||
</>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
ActionsStep.propTypes = {
|
||||
/* eslint-disable react/forbid-prop-types */
|
||||
card: PropTypes.object.isRequired,
|
||||
projectsToLists: PropTypes.array.isRequired,
|
||||
boardMemberships: PropTypes.array.isRequired,
|
||||
currentUserIds: PropTypes.array.isRequired,
|
||||
labels: PropTypes.array.isRequired,
|
||||
currentLabelIds: PropTypes.array.isRequired,
|
||||
/* eslint-enable react/forbid-prop-types */
|
||||
onNameEdit: PropTypes.func.isRequired,
|
||||
onUpdate: PropTypes.func.isRequired,
|
||||
onMove: PropTypes.func.isRequired,
|
||||
onTransfer: PropTypes.func.isRequired,
|
||||
onDuplicate: PropTypes.func.isRequired,
|
||||
onDelete: PropTypes.func.isRequired,
|
||||
onUserAdd: PropTypes.func.isRequired,
|
||||
onUserRemove: PropTypes.func.isRequired,
|
||||
onBoardFetch: PropTypes.func.isRequired,
|
||||
onLabelAdd: PropTypes.func.isRequired,
|
||||
onLabelRemove: PropTypes.func.isRequired,
|
||||
onLabelCreate: PropTypes.func.isRequired,
|
||||
onLabelUpdate: PropTypes.func.isRequired,
|
||||
onLabelMove: PropTypes.func.isRequired,
|
||||
onLabelDelete: PropTypes.func.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default ActionsStep;
|
||||
import pick from 'lodash/pick';
|
||||
import React, { useCallback } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Menu } from 'semantic-ui-react';
|
||||
import { Popup } from '../../lib/custom-ui';
|
||||
|
||||
import { useSteps } from '../../hooks';
|
||||
import BoardMembershipsStep from '../BoardMembershipsStep';
|
||||
import LabelsStep from '../LabelsStep';
|
||||
import DueDateEditStep from '../DueDateEditStep';
|
||||
import StopwatchEditStep from '../StopwatchEditStep';
|
||||
import CardMoveStep from '../CardMoveStep';
|
||||
import DeleteStep from '../DeleteStep';
|
||||
|
||||
import styles from './ActionsStep.module.scss';
|
||||
|
||||
const StepTypes = {
|
||||
USERS: 'USERS',
|
||||
LABELS: 'LABELS',
|
||||
EDIT_DUE_DATE: 'EDIT_DUE_DATE',
|
||||
EDIT_STOPWATCH: 'EDIT_STOPWATCH',
|
||||
MOVE: 'MOVE',
|
||||
DELETE: 'DELETE',
|
||||
};
|
||||
|
||||
const ActionsStep = React.memo(
|
||||
({
|
||||
card,
|
||||
projectsToLists,
|
||||
boardMemberships,
|
||||
currentUserIds,
|
||||
labels,
|
||||
currentLabelIds,
|
||||
onNameEdit,
|
||||
onUpdate,
|
||||
onMove,
|
||||
onTransfer,
|
||||
onDuplicate,
|
||||
onDelete,
|
||||
onUserAdd,
|
||||
onUserRemove,
|
||||
onBoardFetch,
|
||||
onLabelAdd,
|
||||
onLabelRemove,
|
||||
onLabelCreate,
|
||||
onLabelUpdate,
|
||||
onLabelMove,
|
||||
onLabelDelete,
|
||||
onClose,
|
||||
}) => {
|
||||
const [t] = useTranslation();
|
||||
const [step, openStep, handleBack] = useSteps();
|
||||
|
||||
const handleEditNameClick = useCallback(() => {
|
||||
onNameEdit();
|
||||
onClose();
|
||||
}, [onNameEdit, onClose]);
|
||||
|
||||
const handleUsersClick = useCallback(() => {
|
||||
openStep(StepTypes.USERS);
|
||||
}, [openStep]);
|
||||
|
||||
const handleLabelsClick = useCallback(() => {
|
||||
openStep(StepTypes.LABELS);
|
||||
}, [openStep]);
|
||||
|
||||
const handleEditDueDateClick = useCallback(() => {
|
||||
openStep(StepTypes.EDIT_DUE_DATE);
|
||||
}, [openStep]);
|
||||
|
||||
const handleEditStopwatchClick = useCallback(() => {
|
||||
openStep(StepTypes.EDIT_STOPWATCH);
|
||||
}, [openStep]);
|
||||
|
||||
const handleMoveClick = useCallback(() => {
|
||||
openStep(StepTypes.MOVE);
|
||||
}, [openStep]);
|
||||
|
||||
const handleDuplicateClick = useCallback(() => {
|
||||
onDuplicate();
|
||||
onClose();
|
||||
}, [onDuplicate, onClose]);
|
||||
|
||||
const handleDeleteClick = useCallback(() => {
|
||||
openStep(StepTypes.DELETE);
|
||||
}, [openStep]);
|
||||
|
||||
const handleDueDateUpdate = useCallback(
|
||||
(dueDate) => {
|
||||
onUpdate({
|
||||
dueDate,
|
||||
});
|
||||
},
|
||||
[onUpdate],
|
||||
);
|
||||
|
||||
const handleStopwatchUpdate = useCallback(
|
||||
(stopwatch) => {
|
||||
onUpdate({
|
||||
stopwatch,
|
||||
});
|
||||
},
|
||||
[onUpdate],
|
||||
);
|
||||
|
||||
if (step) {
|
||||
switch (step.type) {
|
||||
case StepTypes.USERS:
|
||||
return (
|
||||
<BoardMembershipsStep
|
||||
items={boardMemberships}
|
||||
currentUserIds={currentUserIds}
|
||||
onUserSelect={onUserAdd}
|
||||
onUserDeselect={onUserRemove}
|
||||
onBack={handleBack}
|
||||
/>
|
||||
);
|
||||
case StepTypes.LABELS:
|
||||
return (
|
||||
<LabelsStep
|
||||
items={labels}
|
||||
currentIds={currentLabelIds}
|
||||
onSelect={onLabelAdd}
|
||||
onDeselect={onLabelRemove}
|
||||
onCreate={onLabelCreate}
|
||||
onUpdate={onLabelUpdate}
|
||||
onMove={onLabelMove}
|
||||
onDelete={onLabelDelete}
|
||||
onBack={handleBack}
|
||||
/>
|
||||
);
|
||||
case StepTypes.EDIT_DUE_DATE:
|
||||
return (
|
||||
<DueDateEditStep
|
||||
defaultValue={card.dueDate}
|
||||
onUpdate={handleDueDateUpdate}
|
||||
onBack={handleBack}
|
||||
onClose={onClose}
|
||||
/>
|
||||
);
|
||||
case StepTypes.EDIT_STOPWATCH:
|
||||
return (
|
||||
<StopwatchEditStep
|
||||
defaultValue={card.stopwatch}
|
||||
onUpdate={handleStopwatchUpdate}
|
||||
onBack={handleBack}
|
||||
onClose={onClose}
|
||||
/>
|
||||
);
|
||||
case StepTypes.MOVE:
|
||||
return (
|
||||
<CardMoveStep
|
||||
projectsToLists={projectsToLists}
|
||||
defaultPath={pick(card, ['projectId', 'boardId', 'listId'])}
|
||||
onMove={onMove}
|
||||
onTransfer={onTransfer}
|
||||
onBoardFetch={onBoardFetch}
|
||||
onBack={handleBack}
|
||||
onClose={onClose}
|
||||
/>
|
||||
);
|
||||
case StepTypes.DELETE:
|
||||
return (
|
||||
<DeleteStep
|
||||
title="common.deleteCard"
|
||||
content="common.areYouSureYouWantToDeleteThisCard"
|
||||
buttonContent="action.deleteCard"
|
||||
onConfirm={onDelete}
|
||||
onBack={handleBack}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Popup.Header>
|
||||
{t('common.cardActions', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Popup.Header>
|
||||
<Popup.Content>
|
||||
<Menu secondary vertical className={styles.menu}>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleEditNameClick}>
|
||||
{t('action.editTitle', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleUsersClick}>
|
||||
{t('common.members', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleLabelsClick}>
|
||||
{t('common.labels', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleEditDueDateClick}>
|
||||
{t('action.editDueDate', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleEditStopwatchClick}>
|
||||
{t('action.editStopwatch', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleMoveClick}>
|
||||
{t('action.moveCard', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleDuplicateClick}>
|
||||
{t('action.duplicateCard', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleDeleteClick}>
|
||||
{t('action.deleteCard', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</Popup.Content>
|
||||
</>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
ActionsStep.propTypes = {
|
||||
/* eslint-disable react/forbid-prop-types */
|
||||
card: PropTypes.object.isRequired,
|
||||
projectsToLists: PropTypes.array.isRequired,
|
||||
boardMemberships: PropTypes.array.isRequired,
|
||||
currentUserIds: PropTypes.array.isRequired,
|
||||
labels: PropTypes.array.isRequired,
|
||||
currentLabelIds: PropTypes.array.isRequired,
|
||||
/* eslint-enable react/forbid-prop-types */
|
||||
onNameEdit: PropTypes.func.isRequired,
|
||||
onUpdate: PropTypes.func.isRequired,
|
||||
onMove: PropTypes.func.isRequired,
|
||||
onTransfer: PropTypes.func.isRequired,
|
||||
onDuplicate: PropTypes.func.isRequired,
|
||||
onDelete: PropTypes.func.isRequired,
|
||||
onUserAdd: PropTypes.func.isRequired,
|
||||
onUserRemove: PropTypes.func.isRequired,
|
||||
onBoardFetch: PropTypes.func.isRequired,
|
||||
onLabelAdd: PropTypes.func.isRequired,
|
||||
onLabelRemove: PropTypes.func.isRequired,
|
||||
onLabelCreate: PropTypes.func.isRequired,
|
||||
onLabelUpdate: PropTypes.func.isRequired,
|
||||
onLabelMove: PropTypes.func.isRequired,
|
||||
onLabelDelete: PropTypes.func.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default ActionsStep;
|
||||
|
||||
@ -1,262 +1,262 @@
|
||||
import React, { useCallback, useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { Button, Icon } from 'semantic-ui-react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Draggable } from 'react-beautiful-dnd';
|
||||
import { usePopup } from '../../lib/popup';
|
||||
|
||||
import { startStopwatch, stopStopwatch } from '../../utils/stopwatch';
|
||||
import Paths from '../../constants/Paths';
|
||||
import Tasks from './Tasks';
|
||||
import NameEdit from './NameEdit';
|
||||
import ActionsStep from './ActionsStep';
|
||||
import User from '../User';
|
||||
import Label from '../Label';
|
||||
import DueDate from '../DueDate';
|
||||
import Stopwatch from '../Stopwatch';
|
||||
|
||||
import styles from './Card.module.scss';
|
||||
|
||||
const Card = React.memo(
|
||||
({
|
||||
id,
|
||||
index,
|
||||
name,
|
||||
dueDate,
|
||||
stopwatch,
|
||||
coverUrl,
|
||||
boardId,
|
||||
listId,
|
||||
projectId,
|
||||
isPersisted,
|
||||
notificationsTotal,
|
||||
users,
|
||||
labels,
|
||||
tasks,
|
||||
allProjectsToLists,
|
||||
allBoardMemberships,
|
||||
allLabels,
|
||||
canEdit,
|
||||
onUpdate,
|
||||
onMove,
|
||||
onTransfer,
|
||||
onDuplicate,
|
||||
onDelete,
|
||||
onUserAdd,
|
||||
onUserRemove,
|
||||
onBoardFetch,
|
||||
onLabelAdd,
|
||||
onLabelRemove,
|
||||
onLabelCreate,
|
||||
onLabelUpdate,
|
||||
onLabelMove,
|
||||
onLabelDelete,
|
||||
}) => {
|
||||
const nameEdit = useRef(null);
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
if (document.activeElement) {
|
||||
document.activeElement.blur();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleToggleStopwatchClick = useCallback(
|
||||
(event) => {
|
||||
event.preventDefault();
|
||||
|
||||
onUpdate({
|
||||
stopwatch: stopwatch.startedAt ? stopStopwatch(stopwatch) : startStopwatch(stopwatch),
|
||||
});
|
||||
},
|
||||
[stopwatch, onUpdate],
|
||||
);
|
||||
|
||||
const handleNameUpdate = useCallback(
|
||||
(newName) => {
|
||||
onUpdate({
|
||||
name: newName,
|
||||
});
|
||||
},
|
||||
[onUpdate],
|
||||
);
|
||||
|
||||
const handleNameEdit = useCallback(() => {
|
||||
nameEdit.current.open();
|
||||
}, []);
|
||||
|
||||
const ActionsPopup = usePopup(ActionsStep);
|
||||
|
||||
const contentNode = (
|
||||
<>
|
||||
{coverUrl && <img src={coverUrl} alt="" className={styles.cover} />}
|
||||
<div className={styles.details}>
|
||||
{labels.length > 0 && (
|
||||
<span className={styles.labels}>
|
||||
{labels.map((label) => (
|
||||
<span
|
||||
key={label.id}
|
||||
className={classNames(styles.attachment, styles.attachmentLeft)}
|
||||
>
|
||||
<Label name={label.name} color={label.color} size="tiny" />
|
||||
</span>
|
||||
))}
|
||||
</span>
|
||||
)}
|
||||
<div className={styles.name}>{name}</div>
|
||||
{tasks.length > 0 && <Tasks items={tasks} />}
|
||||
{(dueDate || stopwatch || notificationsTotal > 0) && (
|
||||
<span className={styles.attachments}>
|
||||
{notificationsTotal > 0 && (
|
||||
<span
|
||||
className={classNames(
|
||||
styles.attachment,
|
||||
styles.attachmentLeft,
|
||||
styles.notification,
|
||||
)}
|
||||
>
|
||||
{notificationsTotal}
|
||||
</span>
|
||||
)}
|
||||
{dueDate && (
|
||||
<span className={classNames(styles.attachment, styles.attachmentLeft)}>
|
||||
<DueDate value={dueDate} size="tiny" />
|
||||
</span>
|
||||
)}
|
||||
{stopwatch && (
|
||||
<span className={classNames(styles.attachment, styles.attachmentLeft)}>
|
||||
<Stopwatch
|
||||
as="span"
|
||||
startedAt={stopwatch.startedAt}
|
||||
total={stopwatch.total}
|
||||
size="tiny"
|
||||
onClick={canEdit ? handleToggleStopwatchClick : undefined}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
{users.length > 0 && (
|
||||
<span className={classNames(styles.attachments, styles.attachmentsRight)}>
|
||||
{users.map((user) => (
|
||||
<span
|
||||
key={user.id}
|
||||
className={classNames(styles.attachment, styles.attachmentRight)}
|
||||
>
|
||||
<User name={user.name} avatarUrl={user.avatarUrl} size="small" />
|
||||
</span>
|
||||
))}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<Draggable draggableId={`card:${id}`} index={index} isDragDisabled={!isPersisted || !canEdit}>
|
||||
{({ innerRef, draggableProps, dragHandleProps }) => (
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
<div {...draggableProps} {...dragHandleProps} ref={innerRef} className={styles.wrapper}>
|
||||
<NameEdit ref={nameEdit} defaultValue={name} onUpdate={handleNameUpdate}>
|
||||
<div className={styles.card}>
|
||||
{isPersisted ? (
|
||||
<>
|
||||
<Link
|
||||
to={Paths.CARDS.replace(':id', id)}
|
||||
className={styles.content}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{contentNode}
|
||||
</Link>
|
||||
{canEdit && (
|
||||
<ActionsPopup
|
||||
card={{
|
||||
dueDate,
|
||||
stopwatch,
|
||||
boardId,
|
||||
listId,
|
||||
projectId,
|
||||
}}
|
||||
projectsToLists={allProjectsToLists}
|
||||
boardMemberships={allBoardMemberships}
|
||||
currentUserIds={users.map((user) => user.id)}
|
||||
labels={allLabels}
|
||||
currentLabelIds={labels.map((label) => label.id)}
|
||||
onNameEdit={handleNameEdit}
|
||||
onUpdate={onUpdate}
|
||||
onMove={onMove}
|
||||
onTransfer={onTransfer}
|
||||
onDuplicate={onDuplicate}
|
||||
onDelete={onDelete}
|
||||
onUserAdd={onUserAdd}
|
||||
onUserRemove={onUserRemove}
|
||||
onBoardFetch={onBoardFetch}
|
||||
onLabelAdd={onLabelAdd}
|
||||
onLabelRemove={onLabelRemove}
|
||||
onLabelCreate={onLabelCreate}
|
||||
onLabelUpdate={onLabelUpdate}
|
||||
onLabelMove={onLabelMove}
|
||||
onLabelDelete={onLabelDelete}
|
||||
>
|
||||
<Button className={classNames(styles.actionsButton, styles.target)}>
|
||||
<Icon fitted name="pencil" size="small" />
|
||||
</Button>
|
||||
</ActionsPopup>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<span className={styles.content}>{contentNode}</span>
|
||||
)}
|
||||
</div>
|
||||
</NameEdit>
|
||||
</div>
|
||||
)}
|
||||
</Draggable>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Card.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
dueDate: PropTypes.instanceOf(Date),
|
||||
stopwatch: PropTypes.object, // eslint-disable-line react/forbid-prop-types
|
||||
coverUrl: PropTypes.string,
|
||||
boardId: PropTypes.string.isRequired,
|
||||
listId: PropTypes.string.isRequired,
|
||||
projectId: PropTypes.string.isRequired,
|
||||
isPersisted: PropTypes.bool.isRequired,
|
||||
notificationsTotal: PropTypes.number.isRequired,
|
||||
/* eslint-disable react/forbid-prop-types */
|
||||
users: PropTypes.array.isRequired,
|
||||
labels: PropTypes.array.isRequired,
|
||||
tasks: PropTypes.array.isRequired,
|
||||
allProjectsToLists: PropTypes.array.isRequired,
|
||||
allBoardMemberships: PropTypes.array.isRequired,
|
||||
allLabels: PropTypes.array.isRequired,
|
||||
/* eslint-enable react/forbid-prop-types */
|
||||
canEdit: PropTypes.bool.isRequired,
|
||||
onUpdate: PropTypes.func.isRequired,
|
||||
onMove: PropTypes.func.isRequired,
|
||||
onTransfer: PropTypes.func.isRequired,
|
||||
onDuplicate: PropTypes.func.isRequired,
|
||||
onDelete: PropTypes.func.isRequired,
|
||||
onUserAdd: PropTypes.func.isRequired,
|
||||
onUserRemove: PropTypes.func.isRequired,
|
||||
onBoardFetch: PropTypes.func.isRequired,
|
||||
onLabelAdd: PropTypes.func.isRequired,
|
||||
onLabelRemove: PropTypes.func.isRequired,
|
||||
onLabelCreate: PropTypes.func.isRequired,
|
||||
onLabelUpdate: PropTypes.func.isRequired,
|
||||
onLabelMove: PropTypes.func.isRequired,
|
||||
onLabelDelete: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
Card.defaultProps = {
|
||||
dueDate: undefined,
|
||||
stopwatch: undefined,
|
||||
coverUrl: undefined,
|
||||
};
|
||||
|
||||
export default Card;
|
||||
import React, { useCallback, useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { Button, Icon } from 'semantic-ui-react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Draggable } from 'react-beautiful-dnd';
|
||||
import { usePopup } from '../../lib/popup';
|
||||
|
||||
import { startStopwatch, stopStopwatch } from '../../utils/stopwatch';
|
||||
import Paths from '../../constants/Paths';
|
||||
import Tasks from './Tasks';
|
||||
import NameEdit from './NameEdit';
|
||||
import ActionsStep from './ActionsStep';
|
||||
import User from '../User';
|
||||
import Label from '../Label';
|
||||
import DueDate from '../DueDate';
|
||||
import Stopwatch from '../Stopwatch';
|
||||
|
||||
import styles from './Card.module.scss';
|
||||
|
||||
const Card = React.memo(
|
||||
({
|
||||
id,
|
||||
index,
|
||||
name,
|
||||
dueDate,
|
||||
stopwatch,
|
||||
coverUrl,
|
||||
boardId,
|
||||
listId,
|
||||
projectId,
|
||||
isPersisted,
|
||||
notificationsTotal,
|
||||
users,
|
||||
labels,
|
||||
tasks,
|
||||
allProjectsToLists,
|
||||
allBoardMemberships,
|
||||
allLabels,
|
||||
canEdit,
|
||||
onUpdate,
|
||||
onMove,
|
||||
onTransfer,
|
||||
onDuplicate,
|
||||
onDelete,
|
||||
onUserAdd,
|
||||
onUserRemove,
|
||||
onBoardFetch,
|
||||
onLabelAdd,
|
||||
onLabelRemove,
|
||||
onLabelCreate,
|
||||
onLabelUpdate,
|
||||
onLabelMove,
|
||||
onLabelDelete,
|
||||
}) => {
|
||||
const nameEdit = useRef(null);
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
if (document.activeElement) {
|
||||
document.activeElement.blur();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleToggleStopwatchClick = useCallback(
|
||||
(event) => {
|
||||
event.preventDefault();
|
||||
|
||||
onUpdate({
|
||||
stopwatch: stopwatch.startedAt ? stopStopwatch(stopwatch) : startStopwatch(stopwatch),
|
||||
});
|
||||
},
|
||||
[stopwatch, onUpdate],
|
||||
);
|
||||
|
||||
const handleNameUpdate = useCallback(
|
||||
(newName) => {
|
||||
onUpdate({
|
||||
name: newName,
|
||||
});
|
||||
},
|
||||
[onUpdate],
|
||||
);
|
||||
|
||||
const handleNameEdit = useCallback(() => {
|
||||
nameEdit.current.open();
|
||||
}, []);
|
||||
|
||||
const ActionsPopup = usePopup(ActionsStep);
|
||||
|
||||
const contentNode = (
|
||||
<>
|
||||
{coverUrl && <img src={coverUrl} alt="" className={styles.cover} />}
|
||||
<div className={styles.details}>
|
||||
{labels.length > 0 && (
|
||||
<span className={styles.labels}>
|
||||
{labels.map((label) => (
|
||||
<span
|
||||
key={label.id}
|
||||
className={classNames(styles.attachment, styles.attachmentLeft)}
|
||||
>
|
||||
<Label name={label.name} color={label.color} size="tiny" />
|
||||
</span>
|
||||
))}
|
||||
</span>
|
||||
)}
|
||||
<div className={styles.name}>{name}</div>
|
||||
{tasks.length > 0 && <Tasks items={tasks} />}
|
||||
{(dueDate || stopwatch || notificationsTotal > 0) && (
|
||||
<span className={styles.attachments}>
|
||||
{notificationsTotal > 0 && (
|
||||
<span
|
||||
className={classNames(
|
||||
styles.attachment,
|
||||
styles.attachmentLeft,
|
||||
styles.notification,
|
||||
)}
|
||||
>
|
||||
{notificationsTotal}
|
||||
</span>
|
||||
)}
|
||||
{dueDate && (
|
||||
<span className={classNames(styles.attachment, styles.attachmentLeft)}>
|
||||
<DueDate value={dueDate} size="tiny" />
|
||||
</span>
|
||||
)}
|
||||
{stopwatch && (
|
||||
<span className={classNames(styles.attachment, styles.attachmentLeft)}>
|
||||
<Stopwatch
|
||||
as="span"
|
||||
startedAt={stopwatch.startedAt}
|
||||
total={stopwatch.total}
|
||||
size="tiny"
|
||||
onClick={canEdit ? handleToggleStopwatchClick : undefined}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
{users.length > 0 && (
|
||||
<span className={classNames(styles.attachments, styles.attachmentsRight)}>
|
||||
{users.map((user) => (
|
||||
<span
|
||||
key={user.id}
|
||||
className={classNames(styles.attachment, styles.attachmentRight)}
|
||||
>
|
||||
<User name={user.name} avatarUrl={user.avatarUrl} size="small" />
|
||||
</span>
|
||||
))}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<Draggable draggableId={`card:${id}`} index={index} isDragDisabled={!isPersisted || !canEdit}>
|
||||
{({ innerRef, draggableProps, dragHandleProps }) => (
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
<div {...draggableProps} {...dragHandleProps} ref={innerRef} className={styles.wrapper}>
|
||||
<NameEdit ref={nameEdit} defaultValue={name} onUpdate={handleNameUpdate}>
|
||||
<div className={styles.card}>
|
||||
{isPersisted ? (
|
||||
<>
|
||||
<Link
|
||||
to={Paths.CARDS.replace(':id', id)}
|
||||
className={styles.content}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{contentNode}
|
||||
</Link>
|
||||
{canEdit && (
|
||||
<ActionsPopup
|
||||
card={{
|
||||
dueDate,
|
||||
stopwatch,
|
||||
boardId,
|
||||
listId,
|
||||
projectId,
|
||||
}}
|
||||
projectsToLists={allProjectsToLists}
|
||||
boardMemberships={allBoardMemberships}
|
||||
currentUserIds={users.map((user) => user.id)}
|
||||
labels={allLabels}
|
||||
currentLabelIds={labels.map((label) => label.id)}
|
||||
onNameEdit={handleNameEdit}
|
||||
onUpdate={onUpdate}
|
||||
onMove={onMove}
|
||||
onTransfer={onTransfer}
|
||||
onDuplicate={onDuplicate}
|
||||
onDelete={onDelete}
|
||||
onUserAdd={onUserAdd}
|
||||
onUserRemove={onUserRemove}
|
||||
onBoardFetch={onBoardFetch}
|
||||
onLabelAdd={onLabelAdd}
|
||||
onLabelRemove={onLabelRemove}
|
||||
onLabelCreate={onLabelCreate}
|
||||
onLabelUpdate={onLabelUpdate}
|
||||
onLabelMove={onLabelMove}
|
||||
onLabelDelete={onLabelDelete}
|
||||
>
|
||||
<Button className={classNames(styles.actionsButton, styles.target)}>
|
||||
<Icon fitted name="pencil" size="small" />
|
||||
</Button>
|
||||
</ActionsPopup>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<span className={styles.content}>{contentNode}</span>
|
||||
)}
|
||||
</div>
|
||||
</NameEdit>
|
||||
</div>
|
||||
)}
|
||||
</Draggable>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Card.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
dueDate: PropTypes.instanceOf(Date),
|
||||
stopwatch: PropTypes.object, // eslint-disable-line react/forbid-prop-types
|
||||
coverUrl: PropTypes.string,
|
||||
boardId: PropTypes.string.isRequired,
|
||||
listId: PropTypes.string.isRequired,
|
||||
projectId: PropTypes.string.isRequired,
|
||||
isPersisted: PropTypes.bool.isRequired,
|
||||
notificationsTotal: PropTypes.number.isRequired,
|
||||
/* eslint-disable react/forbid-prop-types */
|
||||
users: PropTypes.array.isRequired,
|
||||
labels: PropTypes.array.isRequired,
|
||||
tasks: PropTypes.array.isRequired,
|
||||
allProjectsToLists: PropTypes.array.isRequired,
|
||||
allBoardMemberships: PropTypes.array.isRequired,
|
||||
allLabels: PropTypes.array.isRequired,
|
||||
/* eslint-enable react/forbid-prop-types */
|
||||
canEdit: PropTypes.bool.isRequired,
|
||||
onUpdate: PropTypes.func.isRequired,
|
||||
onMove: PropTypes.func.isRequired,
|
||||
onTransfer: PropTypes.func.isRequired,
|
||||
onDuplicate: PropTypes.func.isRequired,
|
||||
onDelete: PropTypes.func.isRequired,
|
||||
onUserAdd: PropTypes.func.isRequired,
|
||||
onUserRemove: PropTypes.func.isRequired,
|
||||
onBoardFetch: PropTypes.func.isRequired,
|
||||
onLabelAdd: PropTypes.func.isRequired,
|
||||
onLabelRemove: PropTypes.func.isRequired,
|
||||
onLabelCreate: PropTypes.func.isRequired,
|
||||
onLabelUpdate: PropTypes.func.isRequired,
|
||||
onLabelMove: PropTypes.func.isRequired,
|
||||
onLabelDelete: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
Card.defaultProps = {
|
||||
dueDate: undefined,
|
||||
stopwatch: undefined,
|
||||
coverUrl: undefined,
|
||||
};
|
||||
|
||||
export default Card;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,266 +1,266 @@
|
||||
export default {
|
||||
/* Router */
|
||||
|
||||
LOCATION_CHANGE_HANDLE: 'LOCATION_CHANGE_HANDLE',
|
||||
LOCATION_CHANGE_HANDLE__BOARD_FETCH: 'LOCATION_CHANGE_HANDLE__BOARD_FETCH',
|
||||
|
||||
/* Socket */
|
||||
|
||||
SOCKET_DISCONNECT_HANDLE: 'SOCKET_DISCONNECT_HANDLE',
|
||||
SOCKET_RECONNECT_HANDLE: 'SOCKET_RECONNECT_HANDLE',
|
||||
SOCKET_RECONNECT_HANDLE__CORE_FETCH: 'SOCKET_RECONNECT_HANDLE__CORE_FETCH',
|
||||
|
||||
/* Login */
|
||||
|
||||
LOGIN_INITIALIZE: 'LOGIN_INITIALIZE',
|
||||
AUTHENTICATE: 'AUTHENTICATE',
|
||||
AUTHENTICATE__SUCCESS: 'AUTHENTICATE__SUCCESS',
|
||||
AUTHENTICATE__FAILURE: 'AUTHENTICATE__FAILURE',
|
||||
USING_OIDC_AUTHENTICATE: 'USING_OIDC_AUTHENTICATE',
|
||||
USING_OIDC_AUTHENTICATE__SUCCESS: 'USING_OIDC_AUTHENTICATE__SUCCESS',
|
||||
USING_OIDC_AUTHENTICATE__FAILURE: 'USING_OIDC_AUTHENTICATE__FAILURE',
|
||||
AUTHENTICATE_ERROR_CLEAR: 'AUTHENTICATE_ERROR_CLEAR',
|
||||
|
||||
/* Core */
|
||||
|
||||
CORE_INITIALIZE: 'CORE_INITIALIZE',
|
||||
CORE_INITIALIZE__CONFIG_FETCH: 'CORE_INITIALIZE__CONFIG_FETCH',
|
||||
LOGOUT: 'LOGOUT',
|
||||
LOGOUT__ACCESS_TOKEN_INVALIDATE: 'LOGOUT__ACCESS_TOKEN_INVALIDATE',
|
||||
|
||||
/* Modals */
|
||||
|
||||
MODAL_OPEN: 'MODAL_OPEN',
|
||||
MODAL_CLOSE: 'MODAL_CLOSE',
|
||||
|
||||
/* Users */
|
||||
|
||||
USER_CREATE: 'USER_CREATE',
|
||||
USER_CREATE__SUCCESS: 'USER_CREATE__SUCCESS',
|
||||
USER_CREATE__FAILURE: 'USER_CREATE__FAILURE',
|
||||
USER_CREATE_HANDLE: 'USER_CREATE_HANDLE',
|
||||
USER_CREATE_ERROR_CLEAR: 'USER_CREATE_ERROR_CLEAR',
|
||||
USER_UPDATE: 'USER_UPDATE',
|
||||
USER_UPDATE__SUCCESS: 'USER_UPDATE__SUCCESS',
|
||||
USER_UPDATE__FAILURE: 'USER_UPDATE__FAILURE',
|
||||
USER_UPDATE_HANDLE: 'USER_UPDATE_HANDLE',
|
||||
USER_EMAIL_UPDATE: 'USER_EMAIL_UPDATE',
|
||||
USER_EMAIL_UPDATE__SUCCESS: 'USER_EMAIL_UPDATE__SUCCESS',
|
||||
USER_EMAIL_UPDATE__FAILURE: 'USER_EMAIL_UPDATE__FAILURE',
|
||||
USER_EMAIL_UPDATE_ERROR_CLEAR: 'USER_EMAIL_UPDATE_ERROR_CLEAR',
|
||||
USER_PASSWORD_UPDATE: 'USER_PASSWORD_UPDATE',
|
||||
USER_PASSWORD_UPDATE__SUCCESS: 'USER_PASSWORD_UPDATE__SUCCESS',
|
||||
USER_PASSWORD_UPDATE__FAILURE: 'USER_PASSWORD_UPDATE__FAILURE',
|
||||
USER_PASSWORD_UPDATE_ERROR_CLEAR: 'USER_PASSWORD_UPDATE_ERROR_CLEAR',
|
||||
USER_USERNAME_UPDATE: 'USER_USERNAME_UPDATE',
|
||||
USER_USERNAME_UPDATE__SUCCESS: 'USER_USERNAME_UPDATE__SUCCESS',
|
||||
USER_USERNAME_UPDATE__FAILURE: 'USER_USERNAME_UPDATE__FAILURE',
|
||||
USER_USERNAME_UPDATE_ERROR_CLEAR: 'USER_USERNAME_UPDATE_ERROR_CLEAR',
|
||||
USER_AVATAR_UPDATE: 'USER_AVATAR_UPDATE',
|
||||
USER_AVATAR_UPDATE__SUCCESS: 'USER_AVATAR_UPDATE__SUCCESS',
|
||||
USER_AVATAR_UPDATE__FAILURE: 'USER_AVATAR_UPDATE__FAILURE',
|
||||
USER_DELETE: 'USER_DELETE',
|
||||
USER_DELETE__SUCCESS: 'USER_DELETE__SUCCESS',
|
||||
USER_DELETE__FAILURE: 'USER_DELETE__FAILURE',
|
||||
USER_DELETE_HANDLE: 'USER_DELETE_HANDLE',
|
||||
USER_TO_CARD_ADD: 'USER_TO_CARD_ADD',
|
||||
USER_TO_CARD_ADD__SUCCESS: 'USER_TO_CARD_ADD__SUCCESS',
|
||||
USER_TO_CARD_ADD__FAILURE: 'USER_TO_CARD_ADD__FAILURE',
|
||||
USER_TO_CARD_ADD_HANDLE: 'USER_TO_CARD_ADD_HANDLE',
|
||||
USER_FROM_CARD_REMOVE: 'USER_FROM_CARD_REMOVE',
|
||||
USER_FROM_CARD_REMOVE__SUCCESS: 'USER_FROM_CARD_REMOVE__SUCCESS',
|
||||
USER_FROM_CARD_REMOVE__FAILURE: 'USER_FROM_CARD_REMOVE__FAILURE',
|
||||
USER_FROM_CARD_REMOVE_HANDLE: 'USER_FROM_CARD_REMOVE_HANDLE',
|
||||
USER_TO_BOARD_FILTER_ADD: 'USER_TO_BOARD_FILTER_ADD',
|
||||
USER_FROM_BOARD_FILTER_REMOVE: 'USER_FROM_BOARD_FILTER_REMOVE',
|
||||
|
||||
/* Projects */
|
||||
|
||||
PROJECT_CREATE: 'PROJECT_CREATE',
|
||||
PROJECT_CREATE__SUCCESS: 'PROJECT_CREATE__SUCCESS',
|
||||
PROJECT_CREATE__FAILURE: 'PROJECT_CREATE__FAILURE',
|
||||
PROJECT_CREATE_HANDLE: 'PROJECT_CREATE_HANDLE',
|
||||
PROJECT_UPDATE: 'PROJECT_UPDATE',
|
||||
PROJECT_UPDATE__SUCCESS: 'PROJECT_UPDATE__SUCCESS',
|
||||
PROJECT_UPDATE__FAILURE: 'PROJECT_UPDATE__FAILURE',
|
||||
PROJECT_UPDATE_HANDLE: 'PROJECT_UPDATE_HANDLE',
|
||||
PROJECT_BACKGROUND_IMAGE_UPDATE: 'PROJECT_BACKGROUND_IMAGE_UPDATE',
|
||||
PROJECT_BACKGROUND_IMAGE_UPDATE__SUCCESS: 'PROJECT_BACKGROUND_IMAGE_UPDATE__SUCCESS',
|
||||
PROJECT_BACKGROUND_IMAGE_UPDATE__FAILURE: 'PROJECT_BACKGROUND_IMAGE_UPDATE__FAILURE',
|
||||
PROJECT_DELETE: 'PROJECT_DELETE',
|
||||
PROJECT_DELETE__SUCCESS: 'PROJECT_DELETE__SUCCESS',
|
||||
PROJECT_DELETE__FAILURE: 'PROJECT_DELETE__FAILURE',
|
||||
PROJECT_DELETE_HANDLE: 'PROJECT_DELETE_HANDLE',
|
||||
|
||||
/* Project managers */
|
||||
|
||||
PROJECT_MANAGER_CREATE: 'PROJECT_MANAGER_CREATE',
|
||||
PROJECT_MANAGER_CREATE__SUCCESS: 'PROJECT_MANAGER_CREATE__SUCCESS',
|
||||
PROJECT_MANAGER_CREATE__FAILURE: 'PROJECT_MANAGER_CREATE__FAILURE',
|
||||
PROJECT_MANAGER_CREATE_HANDLE: 'PROJECT_MANAGER_CREATE_HANDLE',
|
||||
PROJECT_MANAGER_CREATE_HANDLE__PROJECT_FETCH: 'PROJECT_MANAGER_CREATE_HANDLE__PROJECT_FETCH',
|
||||
PROJECT_MANAGER_DELETE: 'PROJECT_MANAGER_DELETE',
|
||||
PROJECT_MANAGER_DELETE__SUCCESS: 'PROJECT_MANAGER_DELETE__SUCCESS',
|
||||
PROJECT_MANAGER_DELETE__FAILURE: 'PROJECT_MANAGER_DELETE__FAILURE',
|
||||
PROJECT_MANAGER_DELETE_HANDLE: 'PROJECT_MANAGER_DELETE_HANDLE',
|
||||
|
||||
/* Boards */
|
||||
|
||||
BOARD_CREATE: 'BOARD_CREATE',
|
||||
BOARD_CREATE__SUCCESS: 'BOARD_CREATE__SUCCESS',
|
||||
BOARD_CREATE__FAILURE: 'BOARD_CREATE__FAILURE',
|
||||
BOARD_CREATE_HANDLE: 'BOARD_CREATE_HANDLE',
|
||||
BOARD_FETCH: 'BOARD_FETCH',
|
||||
BOARD_FETCH__SUCCESS: 'BOARD_FETCH__SUCCESS',
|
||||
BOARD_FETCH__FAILURE: 'BOARD_FETCH__FAILURE',
|
||||
BOARD_UPDATE: 'BOARD_UPDATE',
|
||||
BOARD_UPDATE__SUCCESS: 'BOARD_UPDATE__SUCCESS',
|
||||
BOARD_UPDATE__FAILURE: 'BOARD_UPDATE__FAILURE',
|
||||
BOARD_UPDATE_HANDLE: 'BOARD_UPDATE_HANDLE',
|
||||
BOARD_DELETE: 'BOARD_DELETE',
|
||||
BOARD_DELETE__SUCCESS: 'BOARD_DELETE__SUCCESS',
|
||||
BOARD_DELETE__FAILURE: 'BOARD_DELETE__FAILURE',
|
||||
BOARD_DELETE_HANDLE: 'BOARD_DELETE_HANDLE',
|
||||
|
||||
/* Board memberships */
|
||||
|
||||
BOARD_MEMBERSHIP_CREATE: 'BOARD_MEMBERSHIP_CREATE',
|
||||
BOARD_MEMBERSHIP_CREATE__SUCCESS: 'BOARD_MEMBERSHIP_CREATE__SUCCESS',
|
||||
BOARD_MEMBERSHIP_CREATE__FAILURE: 'BOARD_MEMBERSHIP_CREATE__FAILURE',
|
||||
BOARD_MEMBERSHIP_CREATE_HANDLE: 'BOARD_MEMBERSHIP_CREATE_HANDLE',
|
||||
BOARD_MEMBERSHIP_CREATE_HANDLE__PROJECT_FETCH: 'BOARD_MEMBERSHIP_CREATE_HANDLE__PROJECT_FETCH',
|
||||
BOARD_MEMBERSHIP_UPDATE: 'BOARD_MEMBERSHIP_UPDATE',
|
||||
BOARD_MEMBERSHIP_UPDATE__SUCCESS: 'BOARD_MEMBERSHIP_UPDATE__SUCCESS',
|
||||
BOARD_MEMBERSHIP_UPDATE__FAILURE: 'BOARD_MEMBERSHIP_UPDATE__FAILURE',
|
||||
BOARD_MEMBERSHIP_UPDATE_HANDLE: 'BOARD_MEMBERSHIP_UPDATE_HANDLE',
|
||||
BOARD_MEMBERSHIP_DELETE: 'BOARD_MEMBERSHIP_DELETE',
|
||||
BOARD_MEMBERSHIP_DELETE__SUCCESS: 'BOARD_MEMBERSHIP_DELETE__SUCCESS',
|
||||
BOARD_MEMBERSHIP_DELETE__FAILURE: 'BOARD_MEMBERSHIP_DELETE__FAILURE',
|
||||
BOARD_MEMBERSHIP_DELETE_HANDLE: 'BOARD_MEMBERSHIP_DELETE_HANDLE',
|
||||
|
||||
/* Labels */
|
||||
|
||||
LABEL_CREATE: 'LABEL_CREATE',
|
||||
LABEL_CREATE__SUCCESS: 'LABEL_CREATE__SUCCESS',
|
||||
LABEL_CREATE__FAILURE: 'LABEL_CREATE__FAILURE',
|
||||
LABEL_CREATE_HANDLE: 'LABEL_CREATE_HANDLE',
|
||||
LABEL_UPDATE: 'LABEL_UPDATE',
|
||||
LABEL_UPDATE__SUCCESS: 'LABEL_UPDATE__SUCCESS',
|
||||
LABEL_UPDATE__FAILURE: 'LABEL_UPDATE__FAILURE',
|
||||
LABEL_UPDATE_HANDLE: 'LABEL_UPDATE_HANDLE',
|
||||
LABEL_DELETE: 'LABEL_DELETE',
|
||||
LABEL_DELETE__SUCCESS: 'LABEL_DELETE__SUCCESS',
|
||||
LABEL_DELETE__FAILURE: 'LABEL_DELETE__FAILURE',
|
||||
LABEL_DELETE_HANDLE: 'LABEL_DELETE_HANDLE',
|
||||
LABEL_TO_CARD_ADD: 'LABEL_TO_CARD_ADD',
|
||||
LABEL_TO_CARD_ADD__SUCCESS: 'LABEL_TO_CARD_ADD__SUCCESS',
|
||||
LABEL_TO_CARD_ADD__FAILURE: 'LABEL_TO_CARD_ADD__FAILURE',
|
||||
LABEL_TO_CARD_ADD_HANDLE: 'LABEL_TO_CARD_ADD_HANDLE',
|
||||
LABEL_FROM_CARD_REMOVE: 'LABEL_FROM_CARD_REMOVE',
|
||||
LABEL_FROM_CARD_REMOVE__SUCCESS: 'LABEL_FROM_CARD_REMOVE__SUCCESS',
|
||||
LABEL_FROM_CARD_REMOVE__FAILURE: 'LABEL_FROM_CARD_REMOVE__FAILURE',
|
||||
LABEL_FROM_CARD_REMOVE_HANDLE: 'LABEL_FROM_CARD_REMOVE_HANDLE',
|
||||
LABEL_TO_BOARD_FILTER_ADD: 'LABEL_TO_BOARD_FILTER_ADD',
|
||||
LABEL_FROM_BOARD_FILTER_REMOVE: 'LABEL_FROM_BOARD_FILTER_REMOVE',
|
||||
|
||||
/* Lists */
|
||||
|
||||
LIST_CREATE: 'LIST_CREATE',
|
||||
LIST_CREATE__SUCCESS: 'LIST_CREATE__SUCCESS',
|
||||
LIST_CREATE__FAILURE: 'LIST_CREATE__FAILURE',
|
||||
LIST_CREATE_HANDLE: 'LIST_CREATE_HANDLE',
|
||||
LIST_UPDATE: 'LIST_UPDATE',
|
||||
LIST_UPDATE__SUCCESS: 'LIST_UPDATE__SUCCESS',
|
||||
LIST_UPDATE__FAILURE: 'LIST_UPDATE__FAILURE',
|
||||
LIST_UPDATE_HANDLE: 'LIST_UPDATE_HANDLE',
|
||||
LIST_DELETE: 'LIST_DELETE',
|
||||
LIST_DELETE__SUCCESS: 'LIST_DELETE__SUCCESS',
|
||||
LIST_DELETE__FAILURE: 'LIST_DELETE__FAILURE',
|
||||
LIST_DELETE_HANDLE: 'LIST_DELETE_HANDLE',
|
||||
|
||||
/* Cards */
|
||||
|
||||
CARD_CREATE: 'CARD_CREATE',
|
||||
CARD_CREATE__SUCCESS: 'CARD_CREATE__SUCCESS',
|
||||
CARD_CREATE__FAILURE: 'CARD_CREATE__FAILURE',
|
||||
CARD_CREATE_HANDLE: 'CARD_CREATE_HANDLE',
|
||||
CARD_FETCH: 'CARD_FETCH',
|
||||
CARD_FETCH__SUCCESS: 'CARD_FETCH__SUCCESS',
|
||||
CARD_FETCH__FAILURE: 'CARD_FETCH__FAILURE',
|
||||
CARD_UPDATE: 'CARD_UPDATE',
|
||||
CARD_UPDATE__SUCCESS: 'CARD_UPDATE__SUCCESS',
|
||||
CARD_UPDATE__FAILURE: 'CARD_UPDATE__FAILURE',
|
||||
CARD_UPDATE_HANDLE: 'CARD_UPDATE_HANDLE',
|
||||
CARD_TRANSFER: 'CARD_TRANSFER',
|
||||
CARD_TRANSFER__SUCCESS: 'CARD_TRANSFER__SUCCESS',
|
||||
CARD_TRANSFER__FAILURE: 'CARD_TRANSFER__FAILURE',
|
||||
CARD_DUPLICATE: 'CARD_DUPLICATE',
|
||||
CARD_DUPLICATE__SUCCESS: 'CARD_DUPLICATE__SUCCESS',
|
||||
CARD_DUPLICATE__FAILURE: 'CARD_DUPLICATE__FAILURE',
|
||||
CARD_DELETE: 'CARD_DELETE',
|
||||
CARD_DELETE__SUCCESS: 'CARD_DELETE__SUCCESS',
|
||||
CARD_DELETE__FAILURE: 'CARD_DELETE__FAILURE',
|
||||
CARD_DELETE_HANDLE: 'CARD_DELETE_HANDLE',
|
||||
|
||||
/* Tasks */
|
||||
|
||||
TASK_CREATE: 'TASK_CREATE',
|
||||
TASK_CREATE__SUCCESS: 'TASK_CREATE__SUCCESS',
|
||||
TASK_CREATE__FAILURE: 'TASK_CREATE__FAILURE',
|
||||
TASK_CREATE_HANDLE: 'TASK_CREATE_HANDLE',
|
||||
TASK_UPDATE: 'TASK_UPDATE',
|
||||
TASK_UPDATE__SUCCESS: 'TASK_UPDATE__SUCCESS',
|
||||
TASK_UPDATE__FAILURE: 'TASK_UPDATE__FAILURE',
|
||||
TASK_UPDATE_HANDLE: 'TASK_UPDATE_HANDLE',
|
||||
TASK_DELETE: 'TASK_DELETE',
|
||||
TASK_DELETE__SUCCESS: 'TASK_DELETE__SUCCESS',
|
||||
TASK_DELETE__FAILURE: 'TASK_DELETE__FAILURE',
|
||||
TASK_DELETE_HANDLE: 'TASK_DELETE_HANDLE',
|
||||
|
||||
/* Attachments */
|
||||
|
||||
ATTACHMENT_CREATE: 'ATTACHMENT_CREATE',
|
||||
ATTACHMENT_CREATE__SUCCESS: 'ATTACHMENT_CREATE__SUCCESS',
|
||||
ATTACHMENT_CREATE__FAILURE: 'ATTACHMENT_CREATE__FAILURE',
|
||||
ATTACHMENT_CREATE_HANDLE: 'ATTACHMENT_CREATE_HANDLE',
|
||||
ATTACHMENT_UPDATE: 'ATTACHMENT_UPDATE',
|
||||
ATTACHMENT_UPDATE__SUCCESS: 'ATTACHMENT_UPDATE__SUCCESS',
|
||||
ATTACHMENT_UPDATE__FAILURE: 'ATTACHMENT_UPDATE__FAILURE',
|
||||
ATTACHMENT_UPDATE_HANDLE: 'ATTACHMENT_UPDATE_HANDLE',
|
||||
ATTACHMENT_DELETE: 'ATTACHMENT_DELETE',
|
||||
ATTACHMENT_DELETE__SUCCESS: 'ATTACHMENT_DELETE__SUCCESS',
|
||||
ATTACHMENT_DELETE__FAILURE: 'ATTACHMENT_DELETE__FAILURE',
|
||||
ATTACHMENT_DELETE_HANDLE: 'ATTACHMENT_DELETE_HANDLE',
|
||||
|
||||
/* Activities */
|
||||
|
||||
ACTIVITIES_FETCH: 'ACTIVITIES_FETCH',
|
||||
ACTIVITIES_FETCH__SUCCESS: 'ACTIVITIES_FETCH__SUCCESS',
|
||||
ACTIVITIES_FETCH__FAILURE: 'ACTIVITIES_FETCH__FAILURE',
|
||||
ACTIVITIES_DETAILS_TOGGLE: 'ACTIVITIES_DETAILS_TOGGLE',
|
||||
ACTIVITIES_DETAILS_TOGGLE__SUCCESS: 'ACTIVITIES_DETAILS_TOGGLE__SUCCESS',
|
||||
ACTIVITIES_DETAILS_TOGGLE__FAILURE: 'ACTIVITIES_DETAILS_TOGGLE__FAILURE',
|
||||
ACTIVITY_CREATE_HANDLE: 'ACTIVITY_CREATE_HANDLE',
|
||||
ACTIVITY_UPDATE_HANDLE: 'ACTIVITY_UPDATE_HANDLE',
|
||||
ACTIVITY_DELETE_HANDLE: 'ACTIVITY_DELETE_HANDLE',
|
||||
|
||||
/* Comment activities */
|
||||
|
||||
COMMENT_ACTIVITY_CREATE: 'COMMENT_ACTIVITY_CREATE',
|
||||
COMMENT_ACTIVITY_CREATE__SUCCESS: 'COMMENT_ACTIVITY_CREATE__SUCCESS',
|
||||
COMMENT_ACTIVITY_CREATE__FAILURE: 'COMMENT_ACTIVITY_CREATE__FAILURE',
|
||||
COMMENT_ACTIVITY_UPDATE: 'COMMENT_ACTIVITY_UPDATE',
|
||||
COMMENT_ACTIVITY_UPDATE__SUCCESS: 'COMMENT_ACTIVITY_UPDATE__SUCCESS',
|
||||
COMMENT_ACTIVITY_UPDATE__FAILURE: 'COMMENT_ACTIVITY_UPDATE__FAILURE',
|
||||
COMMENT_ACTIVITY_DELETE: 'COMMENT_ACTIVITY_DELETE',
|
||||
COMMENT_ACTIVITY_DELETE__SUCCESS: 'COMMENT_ACTIVITY_DELETE__SUCCESS',
|
||||
COMMENT_ACTIVITY_DELETE__FAILURE: 'COMMENT_ACTIVITY_DELETE__FAILURE',
|
||||
|
||||
/* Notifications */
|
||||
|
||||
NOTIFICATION_CREATE_HANDLE: 'NOTIFICATION_CREATE_HANDLE',
|
||||
NOTIFICATION_DELETE: 'NOTIFICATION_DELETE',
|
||||
NOTIFICATION_DELETE__SUCCESS: 'NOTIFICATION_DELETE__SUCCESS',
|
||||
NOTIFICATION_DELETE__FAILURE: 'NOTIFICATION_DELETE__FAILURE',
|
||||
NOTIFICATION_DELETE_HANDLE: 'NOTIFICATION_DELETE_HANDLE',
|
||||
};
|
||||
export default {
|
||||
/* Router */
|
||||
|
||||
LOCATION_CHANGE_HANDLE: 'LOCATION_CHANGE_HANDLE',
|
||||
LOCATION_CHANGE_HANDLE__BOARD_FETCH: 'LOCATION_CHANGE_HANDLE__BOARD_FETCH',
|
||||
|
||||
/* Socket */
|
||||
|
||||
SOCKET_DISCONNECT_HANDLE: 'SOCKET_DISCONNECT_HANDLE',
|
||||
SOCKET_RECONNECT_HANDLE: 'SOCKET_RECONNECT_HANDLE',
|
||||
SOCKET_RECONNECT_HANDLE__CORE_FETCH: 'SOCKET_RECONNECT_HANDLE__CORE_FETCH',
|
||||
|
||||
/* Login */
|
||||
|
||||
LOGIN_INITIALIZE: 'LOGIN_INITIALIZE',
|
||||
AUTHENTICATE: 'AUTHENTICATE',
|
||||
AUTHENTICATE__SUCCESS: 'AUTHENTICATE__SUCCESS',
|
||||
AUTHENTICATE__FAILURE: 'AUTHENTICATE__FAILURE',
|
||||
USING_OIDC_AUTHENTICATE: 'USING_OIDC_AUTHENTICATE',
|
||||
USING_OIDC_AUTHENTICATE__SUCCESS: 'USING_OIDC_AUTHENTICATE__SUCCESS',
|
||||
USING_OIDC_AUTHENTICATE__FAILURE: 'USING_OIDC_AUTHENTICATE__FAILURE',
|
||||
AUTHENTICATE_ERROR_CLEAR: 'AUTHENTICATE_ERROR_CLEAR',
|
||||
|
||||
/* Core */
|
||||
|
||||
CORE_INITIALIZE: 'CORE_INITIALIZE',
|
||||
CORE_INITIALIZE__CONFIG_FETCH: 'CORE_INITIALIZE__CONFIG_FETCH',
|
||||
LOGOUT: 'LOGOUT',
|
||||
LOGOUT__ACCESS_TOKEN_INVALIDATE: 'LOGOUT__ACCESS_TOKEN_INVALIDATE',
|
||||
|
||||
/* Modals */
|
||||
|
||||
MODAL_OPEN: 'MODAL_OPEN',
|
||||
MODAL_CLOSE: 'MODAL_CLOSE',
|
||||
|
||||
/* Users */
|
||||
|
||||
USER_CREATE: 'USER_CREATE',
|
||||
USER_CREATE__SUCCESS: 'USER_CREATE__SUCCESS',
|
||||
USER_CREATE__FAILURE: 'USER_CREATE__FAILURE',
|
||||
USER_CREATE_HANDLE: 'USER_CREATE_HANDLE',
|
||||
USER_CREATE_ERROR_CLEAR: 'USER_CREATE_ERROR_CLEAR',
|
||||
USER_UPDATE: 'USER_UPDATE',
|
||||
USER_UPDATE__SUCCESS: 'USER_UPDATE__SUCCESS',
|
||||
USER_UPDATE__FAILURE: 'USER_UPDATE__FAILURE',
|
||||
USER_UPDATE_HANDLE: 'USER_UPDATE_HANDLE',
|
||||
USER_EMAIL_UPDATE: 'USER_EMAIL_UPDATE',
|
||||
USER_EMAIL_UPDATE__SUCCESS: 'USER_EMAIL_UPDATE__SUCCESS',
|
||||
USER_EMAIL_UPDATE__FAILURE: 'USER_EMAIL_UPDATE__FAILURE',
|
||||
USER_EMAIL_UPDATE_ERROR_CLEAR: 'USER_EMAIL_UPDATE_ERROR_CLEAR',
|
||||
USER_PASSWORD_UPDATE: 'USER_PASSWORD_UPDATE',
|
||||
USER_PASSWORD_UPDATE__SUCCESS: 'USER_PASSWORD_UPDATE__SUCCESS',
|
||||
USER_PASSWORD_UPDATE__FAILURE: 'USER_PASSWORD_UPDATE__FAILURE',
|
||||
USER_PASSWORD_UPDATE_ERROR_CLEAR: 'USER_PASSWORD_UPDATE_ERROR_CLEAR',
|
||||
USER_USERNAME_UPDATE: 'USER_USERNAME_UPDATE',
|
||||
USER_USERNAME_UPDATE__SUCCESS: 'USER_USERNAME_UPDATE__SUCCESS',
|
||||
USER_USERNAME_UPDATE__FAILURE: 'USER_USERNAME_UPDATE__FAILURE',
|
||||
USER_USERNAME_UPDATE_ERROR_CLEAR: 'USER_USERNAME_UPDATE_ERROR_CLEAR',
|
||||
USER_AVATAR_UPDATE: 'USER_AVATAR_UPDATE',
|
||||
USER_AVATAR_UPDATE__SUCCESS: 'USER_AVATAR_UPDATE__SUCCESS',
|
||||
USER_AVATAR_UPDATE__FAILURE: 'USER_AVATAR_UPDATE__FAILURE',
|
||||
USER_DELETE: 'USER_DELETE',
|
||||
USER_DELETE__SUCCESS: 'USER_DELETE__SUCCESS',
|
||||
USER_DELETE__FAILURE: 'USER_DELETE__FAILURE',
|
||||
USER_DELETE_HANDLE: 'USER_DELETE_HANDLE',
|
||||
USER_TO_CARD_ADD: 'USER_TO_CARD_ADD',
|
||||
USER_TO_CARD_ADD__SUCCESS: 'USER_TO_CARD_ADD__SUCCESS',
|
||||
USER_TO_CARD_ADD__FAILURE: 'USER_TO_CARD_ADD__FAILURE',
|
||||
USER_TO_CARD_ADD_HANDLE: 'USER_TO_CARD_ADD_HANDLE',
|
||||
USER_FROM_CARD_REMOVE: 'USER_FROM_CARD_REMOVE',
|
||||
USER_FROM_CARD_REMOVE__SUCCESS: 'USER_FROM_CARD_REMOVE__SUCCESS',
|
||||
USER_FROM_CARD_REMOVE__FAILURE: 'USER_FROM_CARD_REMOVE__FAILURE',
|
||||
USER_FROM_CARD_REMOVE_HANDLE: 'USER_FROM_CARD_REMOVE_HANDLE',
|
||||
USER_TO_BOARD_FILTER_ADD: 'USER_TO_BOARD_FILTER_ADD',
|
||||
USER_FROM_BOARD_FILTER_REMOVE: 'USER_FROM_BOARD_FILTER_REMOVE',
|
||||
|
||||
/* Projects */
|
||||
|
||||
PROJECT_CREATE: 'PROJECT_CREATE',
|
||||
PROJECT_CREATE__SUCCESS: 'PROJECT_CREATE__SUCCESS',
|
||||
PROJECT_CREATE__FAILURE: 'PROJECT_CREATE__FAILURE',
|
||||
PROJECT_CREATE_HANDLE: 'PROJECT_CREATE_HANDLE',
|
||||
PROJECT_UPDATE: 'PROJECT_UPDATE',
|
||||
PROJECT_UPDATE__SUCCESS: 'PROJECT_UPDATE__SUCCESS',
|
||||
PROJECT_UPDATE__FAILURE: 'PROJECT_UPDATE__FAILURE',
|
||||
PROJECT_UPDATE_HANDLE: 'PROJECT_UPDATE_HANDLE',
|
||||
PROJECT_BACKGROUND_IMAGE_UPDATE: 'PROJECT_BACKGROUND_IMAGE_UPDATE',
|
||||
PROJECT_BACKGROUND_IMAGE_UPDATE__SUCCESS: 'PROJECT_BACKGROUND_IMAGE_UPDATE__SUCCESS',
|
||||
PROJECT_BACKGROUND_IMAGE_UPDATE__FAILURE: 'PROJECT_BACKGROUND_IMAGE_UPDATE__FAILURE',
|
||||
PROJECT_DELETE: 'PROJECT_DELETE',
|
||||
PROJECT_DELETE__SUCCESS: 'PROJECT_DELETE__SUCCESS',
|
||||
PROJECT_DELETE__FAILURE: 'PROJECT_DELETE__FAILURE',
|
||||
PROJECT_DELETE_HANDLE: 'PROJECT_DELETE_HANDLE',
|
||||
|
||||
/* Project managers */
|
||||
|
||||
PROJECT_MANAGER_CREATE: 'PROJECT_MANAGER_CREATE',
|
||||
PROJECT_MANAGER_CREATE__SUCCESS: 'PROJECT_MANAGER_CREATE__SUCCESS',
|
||||
PROJECT_MANAGER_CREATE__FAILURE: 'PROJECT_MANAGER_CREATE__FAILURE',
|
||||
PROJECT_MANAGER_CREATE_HANDLE: 'PROJECT_MANAGER_CREATE_HANDLE',
|
||||
PROJECT_MANAGER_CREATE_HANDLE__PROJECT_FETCH: 'PROJECT_MANAGER_CREATE_HANDLE__PROJECT_FETCH',
|
||||
PROJECT_MANAGER_DELETE: 'PROJECT_MANAGER_DELETE',
|
||||
PROJECT_MANAGER_DELETE__SUCCESS: 'PROJECT_MANAGER_DELETE__SUCCESS',
|
||||
PROJECT_MANAGER_DELETE__FAILURE: 'PROJECT_MANAGER_DELETE__FAILURE',
|
||||
PROJECT_MANAGER_DELETE_HANDLE: 'PROJECT_MANAGER_DELETE_HANDLE',
|
||||
|
||||
/* Boards */
|
||||
|
||||
BOARD_CREATE: 'BOARD_CREATE',
|
||||
BOARD_CREATE__SUCCESS: 'BOARD_CREATE__SUCCESS',
|
||||
BOARD_CREATE__FAILURE: 'BOARD_CREATE__FAILURE',
|
||||
BOARD_CREATE_HANDLE: 'BOARD_CREATE_HANDLE',
|
||||
BOARD_FETCH: 'BOARD_FETCH',
|
||||
BOARD_FETCH__SUCCESS: 'BOARD_FETCH__SUCCESS',
|
||||
BOARD_FETCH__FAILURE: 'BOARD_FETCH__FAILURE',
|
||||
BOARD_UPDATE: 'BOARD_UPDATE',
|
||||
BOARD_UPDATE__SUCCESS: 'BOARD_UPDATE__SUCCESS',
|
||||
BOARD_UPDATE__FAILURE: 'BOARD_UPDATE__FAILURE',
|
||||
BOARD_UPDATE_HANDLE: 'BOARD_UPDATE_HANDLE',
|
||||
BOARD_DELETE: 'BOARD_DELETE',
|
||||
BOARD_DELETE__SUCCESS: 'BOARD_DELETE__SUCCESS',
|
||||
BOARD_DELETE__FAILURE: 'BOARD_DELETE__FAILURE',
|
||||
BOARD_DELETE_HANDLE: 'BOARD_DELETE_HANDLE',
|
||||
|
||||
/* Board memberships */
|
||||
|
||||
BOARD_MEMBERSHIP_CREATE: 'BOARD_MEMBERSHIP_CREATE',
|
||||
BOARD_MEMBERSHIP_CREATE__SUCCESS: 'BOARD_MEMBERSHIP_CREATE__SUCCESS',
|
||||
BOARD_MEMBERSHIP_CREATE__FAILURE: 'BOARD_MEMBERSHIP_CREATE__FAILURE',
|
||||
BOARD_MEMBERSHIP_CREATE_HANDLE: 'BOARD_MEMBERSHIP_CREATE_HANDLE',
|
||||
BOARD_MEMBERSHIP_CREATE_HANDLE__PROJECT_FETCH: 'BOARD_MEMBERSHIP_CREATE_HANDLE__PROJECT_FETCH',
|
||||
BOARD_MEMBERSHIP_UPDATE: 'BOARD_MEMBERSHIP_UPDATE',
|
||||
BOARD_MEMBERSHIP_UPDATE__SUCCESS: 'BOARD_MEMBERSHIP_UPDATE__SUCCESS',
|
||||
BOARD_MEMBERSHIP_UPDATE__FAILURE: 'BOARD_MEMBERSHIP_UPDATE__FAILURE',
|
||||
BOARD_MEMBERSHIP_UPDATE_HANDLE: 'BOARD_MEMBERSHIP_UPDATE_HANDLE',
|
||||
BOARD_MEMBERSHIP_DELETE: 'BOARD_MEMBERSHIP_DELETE',
|
||||
BOARD_MEMBERSHIP_DELETE__SUCCESS: 'BOARD_MEMBERSHIP_DELETE__SUCCESS',
|
||||
BOARD_MEMBERSHIP_DELETE__FAILURE: 'BOARD_MEMBERSHIP_DELETE__FAILURE',
|
||||
BOARD_MEMBERSHIP_DELETE_HANDLE: 'BOARD_MEMBERSHIP_DELETE_HANDLE',
|
||||
|
||||
/* Labels */
|
||||
|
||||
LABEL_CREATE: 'LABEL_CREATE',
|
||||
LABEL_CREATE__SUCCESS: 'LABEL_CREATE__SUCCESS',
|
||||
LABEL_CREATE__FAILURE: 'LABEL_CREATE__FAILURE',
|
||||
LABEL_CREATE_HANDLE: 'LABEL_CREATE_HANDLE',
|
||||
LABEL_UPDATE: 'LABEL_UPDATE',
|
||||
LABEL_UPDATE__SUCCESS: 'LABEL_UPDATE__SUCCESS',
|
||||
LABEL_UPDATE__FAILURE: 'LABEL_UPDATE__FAILURE',
|
||||
LABEL_UPDATE_HANDLE: 'LABEL_UPDATE_HANDLE',
|
||||
LABEL_DELETE: 'LABEL_DELETE',
|
||||
LABEL_DELETE__SUCCESS: 'LABEL_DELETE__SUCCESS',
|
||||
LABEL_DELETE__FAILURE: 'LABEL_DELETE__FAILURE',
|
||||
LABEL_DELETE_HANDLE: 'LABEL_DELETE_HANDLE',
|
||||
LABEL_TO_CARD_ADD: 'LABEL_TO_CARD_ADD',
|
||||
LABEL_TO_CARD_ADD__SUCCESS: 'LABEL_TO_CARD_ADD__SUCCESS',
|
||||
LABEL_TO_CARD_ADD__FAILURE: 'LABEL_TO_CARD_ADD__FAILURE',
|
||||
LABEL_TO_CARD_ADD_HANDLE: 'LABEL_TO_CARD_ADD_HANDLE',
|
||||
LABEL_FROM_CARD_REMOVE: 'LABEL_FROM_CARD_REMOVE',
|
||||
LABEL_FROM_CARD_REMOVE__SUCCESS: 'LABEL_FROM_CARD_REMOVE__SUCCESS',
|
||||
LABEL_FROM_CARD_REMOVE__FAILURE: 'LABEL_FROM_CARD_REMOVE__FAILURE',
|
||||
LABEL_FROM_CARD_REMOVE_HANDLE: 'LABEL_FROM_CARD_REMOVE_HANDLE',
|
||||
LABEL_TO_BOARD_FILTER_ADD: 'LABEL_TO_BOARD_FILTER_ADD',
|
||||
LABEL_FROM_BOARD_FILTER_REMOVE: 'LABEL_FROM_BOARD_FILTER_REMOVE',
|
||||
|
||||
/* Lists */
|
||||
|
||||
LIST_CREATE: 'LIST_CREATE',
|
||||
LIST_CREATE__SUCCESS: 'LIST_CREATE__SUCCESS',
|
||||
LIST_CREATE__FAILURE: 'LIST_CREATE__FAILURE',
|
||||
LIST_CREATE_HANDLE: 'LIST_CREATE_HANDLE',
|
||||
LIST_UPDATE: 'LIST_UPDATE',
|
||||
LIST_UPDATE__SUCCESS: 'LIST_UPDATE__SUCCESS',
|
||||
LIST_UPDATE__FAILURE: 'LIST_UPDATE__FAILURE',
|
||||
LIST_UPDATE_HANDLE: 'LIST_UPDATE_HANDLE',
|
||||
LIST_DELETE: 'LIST_DELETE',
|
||||
LIST_DELETE__SUCCESS: 'LIST_DELETE__SUCCESS',
|
||||
LIST_DELETE__FAILURE: 'LIST_DELETE__FAILURE',
|
||||
LIST_DELETE_HANDLE: 'LIST_DELETE_HANDLE',
|
||||
|
||||
/* Cards */
|
||||
|
||||
CARD_CREATE: 'CARD_CREATE',
|
||||
CARD_CREATE__SUCCESS: 'CARD_CREATE__SUCCESS',
|
||||
CARD_CREATE__FAILURE: 'CARD_CREATE__FAILURE',
|
||||
CARD_CREATE_HANDLE: 'CARD_CREATE_HANDLE',
|
||||
CARD_FETCH: 'CARD_FETCH',
|
||||
CARD_FETCH__SUCCESS: 'CARD_FETCH__SUCCESS',
|
||||
CARD_FETCH__FAILURE: 'CARD_FETCH__FAILURE',
|
||||
CARD_UPDATE: 'CARD_UPDATE',
|
||||
CARD_UPDATE__SUCCESS: 'CARD_UPDATE__SUCCESS',
|
||||
CARD_UPDATE__FAILURE: 'CARD_UPDATE__FAILURE',
|
||||
CARD_UPDATE_HANDLE: 'CARD_UPDATE_HANDLE',
|
||||
CARD_TRANSFER: 'CARD_TRANSFER',
|
||||
CARD_TRANSFER__SUCCESS: 'CARD_TRANSFER__SUCCESS',
|
||||
CARD_TRANSFER__FAILURE: 'CARD_TRANSFER__FAILURE',
|
||||
CARD_DUPLICATE: 'CARD_DUPLICATE',
|
||||
CARD_DUPLICATE__SUCCESS: 'CARD_DUPLICATE__SUCCESS',
|
||||
CARD_DUPLICATE__FAILURE: 'CARD_DUPLICATE__FAILURE',
|
||||
CARD_DELETE: 'CARD_DELETE',
|
||||
CARD_DELETE__SUCCESS: 'CARD_DELETE__SUCCESS',
|
||||
CARD_DELETE__FAILURE: 'CARD_DELETE__FAILURE',
|
||||
CARD_DELETE_HANDLE: 'CARD_DELETE_HANDLE',
|
||||
|
||||
/* Tasks */
|
||||
|
||||
TASK_CREATE: 'TASK_CREATE',
|
||||
TASK_CREATE__SUCCESS: 'TASK_CREATE__SUCCESS',
|
||||
TASK_CREATE__FAILURE: 'TASK_CREATE__FAILURE',
|
||||
TASK_CREATE_HANDLE: 'TASK_CREATE_HANDLE',
|
||||
TASK_UPDATE: 'TASK_UPDATE',
|
||||
TASK_UPDATE__SUCCESS: 'TASK_UPDATE__SUCCESS',
|
||||
TASK_UPDATE__FAILURE: 'TASK_UPDATE__FAILURE',
|
||||
TASK_UPDATE_HANDLE: 'TASK_UPDATE_HANDLE',
|
||||
TASK_DELETE: 'TASK_DELETE',
|
||||
TASK_DELETE__SUCCESS: 'TASK_DELETE__SUCCESS',
|
||||
TASK_DELETE__FAILURE: 'TASK_DELETE__FAILURE',
|
||||
TASK_DELETE_HANDLE: 'TASK_DELETE_HANDLE',
|
||||
|
||||
/* Attachments */
|
||||
|
||||
ATTACHMENT_CREATE: 'ATTACHMENT_CREATE',
|
||||
ATTACHMENT_CREATE__SUCCESS: 'ATTACHMENT_CREATE__SUCCESS',
|
||||
ATTACHMENT_CREATE__FAILURE: 'ATTACHMENT_CREATE__FAILURE',
|
||||
ATTACHMENT_CREATE_HANDLE: 'ATTACHMENT_CREATE_HANDLE',
|
||||
ATTACHMENT_UPDATE: 'ATTACHMENT_UPDATE',
|
||||
ATTACHMENT_UPDATE__SUCCESS: 'ATTACHMENT_UPDATE__SUCCESS',
|
||||
ATTACHMENT_UPDATE__FAILURE: 'ATTACHMENT_UPDATE__FAILURE',
|
||||
ATTACHMENT_UPDATE_HANDLE: 'ATTACHMENT_UPDATE_HANDLE',
|
||||
ATTACHMENT_DELETE: 'ATTACHMENT_DELETE',
|
||||
ATTACHMENT_DELETE__SUCCESS: 'ATTACHMENT_DELETE__SUCCESS',
|
||||
ATTACHMENT_DELETE__FAILURE: 'ATTACHMENT_DELETE__FAILURE',
|
||||
ATTACHMENT_DELETE_HANDLE: 'ATTACHMENT_DELETE_HANDLE',
|
||||
|
||||
/* Activities */
|
||||
|
||||
ACTIVITIES_FETCH: 'ACTIVITIES_FETCH',
|
||||
ACTIVITIES_FETCH__SUCCESS: 'ACTIVITIES_FETCH__SUCCESS',
|
||||
ACTIVITIES_FETCH__FAILURE: 'ACTIVITIES_FETCH__FAILURE',
|
||||
ACTIVITIES_DETAILS_TOGGLE: 'ACTIVITIES_DETAILS_TOGGLE',
|
||||
ACTIVITIES_DETAILS_TOGGLE__SUCCESS: 'ACTIVITIES_DETAILS_TOGGLE__SUCCESS',
|
||||
ACTIVITIES_DETAILS_TOGGLE__FAILURE: 'ACTIVITIES_DETAILS_TOGGLE__FAILURE',
|
||||
ACTIVITY_CREATE_HANDLE: 'ACTIVITY_CREATE_HANDLE',
|
||||
ACTIVITY_UPDATE_HANDLE: 'ACTIVITY_UPDATE_HANDLE',
|
||||
ACTIVITY_DELETE_HANDLE: 'ACTIVITY_DELETE_HANDLE',
|
||||
|
||||
/* Comment activities */
|
||||
|
||||
COMMENT_ACTIVITY_CREATE: 'COMMENT_ACTIVITY_CREATE',
|
||||
COMMENT_ACTIVITY_CREATE__SUCCESS: 'COMMENT_ACTIVITY_CREATE__SUCCESS',
|
||||
COMMENT_ACTIVITY_CREATE__FAILURE: 'COMMENT_ACTIVITY_CREATE__FAILURE',
|
||||
COMMENT_ACTIVITY_UPDATE: 'COMMENT_ACTIVITY_UPDATE',
|
||||
COMMENT_ACTIVITY_UPDATE__SUCCESS: 'COMMENT_ACTIVITY_UPDATE__SUCCESS',
|
||||
COMMENT_ACTIVITY_UPDATE__FAILURE: 'COMMENT_ACTIVITY_UPDATE__FAILURE',
|
||||
COMMENT_ACTIVITY_DELETE: 'COMMENT_ACTIVITY_DELETE',
|
||||
COMMENT_ACTIVITY_DELETE__SUCCESS: 'COMMENT_ACTIVITY_DELETE__SUCCESS',
|
||||
COMMENT_ACTIVITY_DELETE__FAILURE: 'COMMENT_ACTIVITY_DELETE__FAILURE',
|
||||
|
||||
/* Notifications */
|
||||
|
||||
NOTIFICATION_CREATE_HANDLE: 'NOTIFICATION_CREATE_HANDLE',
|
||||
NOTIFICATION_DELETE: 'NOTIFICATION_DELETE',
|
||||
NOTIFICATION_DELETE__SUCCESS: 'NOTIFICATION_DELETE__SUCCESS',
|
||||
NOTIFICATION_DELETE__FAILURE: 'NOTIFICATION_DELETE__FAILURE',
|
||||
NOTIFICATION_DELETE_HANDLE: 'NOTIFICATION_DELETE_HANDLE',
|
||||
};
|
||||
|
||||
@ -1,179 +1,179 @@
|
||||
const PREFIX = '@entry';
|
||||
|
||||
export default {
|
||||
PREFIX,
|
||||
|
||||
/* Socket */
|
||||
|
||||
SOCKET_DISCONNECT_HANDLE: `${PREFIX}/SOCKET_DISCONNECT_HANDLE`,
|
||||
SOCKET_RECONNECT_HANDLE: `${PREFIX}/SOCKET_RECONNECT_HANDLE`,
|
||||
|
||||
/* Login */
|
||||
|
||||
AUTHENTICATE: `${PREFIX}/AUTHENTICATE`,
|
||||
USING_OIDC_AUTHENTICATE: `${PREFIX}/USING_OIDC_AUTHENTICATE`,
|
||||
AUTHENTICATE_ERROR_CLEAR: `${PREFIX}/AUTHENTICATE_ERROR_CLEAR`,
|
||||
|
||||
/* Core */
|
||||
|
||||
LOGOUT: `${PREFIX}/LOGOUT`,
|
||||
|
||||
/* Modals */
|
||||
|
||||
MODAL_OPEN: `${PREFIX}/MODAL_OPEN`,
|
||||
MODAL_CLOSE: `${PREFIX}/MODAL_CLOSE`,
|
||||
|
||||
/* Users */
|
||||
|
||||
USER_CREATE: `${PREFIX}/USER_CREATE`,
|
||||
USER_CREATE_HANDLE: `${PREFIX}/USER_CREATE_HANDLE`,
|
||||
USER_CREATE_ERROR_CLEAR: `${PREFIX}/USER_CREATE_ERROR_CLEAR`,
|
||||
USER_UPDATE: `${PREFIX}/USER_UPDATE`,
|
||||
CURRENT_USER_UPDATE: `${PREFIX}/CURRENT_USER_UPDATE`,
|
||||
USER_UPDATE_HANDLE: `${PREFIX}/USER_UPDATE_HANDLE`,
|
||||
CURRENT_USER_LANGUAGE_UPDATE: `${PREFIX}/CURRENT_USER_LANGUAGE_UPDATE`,
|
||||
USER_EMAIL_UPDATE: `${PREFIX}/USER_EMAIL_UPDATE`,
|
||||
CURRENT_USER_EMAIL_UPDATE: `${PREFIX}/CURRENT_USER_EMAIL_UPDATE`,
|
||||
USER_EMAIL_UPDATE_ERROR_CLEAR: `${PREFIX}/USER_EMAIL_UPDATE_ERROR_CLEAR`,
|
||||
CURRENT_USER_EMAIL_UPDATE_ERROR_CLEAR: `${PREFIX}/CURRENT_USER_EMAIL_UPDATE_ERROR_CLEAR`,
|
||||
USER_PASSWORD_UPDATE: `${PREFIX}/USER_PASSWORD_UPDATE`,
|
||||
CURRENT_USER_PASSWORD_UPDATE: `${PREFIX}/CURRENT_USER_PASSWORD_UPDATE`,
|
||||
USER_PASSWORD_UPDATE_ERROR_CLEAR: `${PREFIX}/USER_PASSWORD_UPDATE_ERROR_CLEAR`,
|
||||
CURRENT_USER_PASSWORD_UPDATE_ERROR_CLEAR: `${PREFIX}/CURRENT_USER_PASSWORD_UPDATE_ERROR_CLEAR`,
|
||||
USER_USERNAME_UPDATE: `${PREFIX}/USER_USERNAME_UPDATE`,
|
||||
CURRENT_USER_USERNAME_UPDATE: `${PREFIX}/CURRENT_USER_USERNAME_UPDATE`,
|
||||
USER_USERNAME_UPDATE_ERROR_CLEAR: `${PREFIX}/USER_USERNAME_UPDATE_ERROR_CLEAR`,
|
||||
CURRENT_USER_USERNAME_UPDATE_ERROR_CLEAR: `${PREFIX}/CURRENT_USER_USERNAME_UPDATE_ERROR_CLEAR`,
|
||||
CURRENT_USER_AVATAR_UPDATE: `${PREFIX}/CURRENT_USER_AVATAR_UPDATE`,
|
||||
USER_DELETE: `${PREFIX}/USER_DELETE`,
|
||||
USER_DELETE_HANDLE: `${PREFIX}/USER_DELETE_HANDLE`,
|
||||
USER_TO_CARD_ADD: `${PREFIX}/USER_TO_CARD_ADD`,
|
||||
USER_TO_CURRENT_CARD_ADD: `${PREFIX}/USER_TO_CURRENT_CARD_ADD`,
|
||||
USER_TO_CARD_ADD_HANDLE: `${PREFIX}/USER_TO_CARD_ADD_HANDLE`,
|
||||
USER_FROM_CARD_REMOVE: `${PREFIX}/USER_FROM_CARD_REMOVE`,
|
||||
USER_FROM_CURRENT_CARD_REMOVE: `${PREFIX}/USER_FROM_CURRENT_CARD_REMOVE`,
|
||||
USER_FROM_CARD_REMOVE_HANDLE: `${PREFIX}/USER_FROM_CARD_REMOVE_HANDLE`,
|
||||
USER_TO_FILTER_IN_CURRENT_BOARD_ADD: `${PREFIX}/USER_TO_FILTER_IN_CURRENT_BOARD_ADD`,
|
||||
USER_FROM_FILTER_IN_CURRENT_BOARD_REMOVE: `${PREFIX}/USER_FROM_FILTER_IN_CURRENT_BOARD_REMOVE`,
|
||||
|
||||
/* Projects */
|
||||
|
||||
PROJECT_CREATE: `${PREFIX}/PROJECT_CREATE`,
|
||||
PROJECT_CREATE_HANDLE: `${PREFIX}/PROJECT_CREATE_HANDLE`,
|
||||
CURRENT_PROJECT_UPDATE: `${PREFIX}/CURRENT_PROJECT_UPDATE`,
|
||||
PROJECT_UPDATE_HANDLE: `${PREFIX}/PROJECT_UPDATE_HANDLE`,
|
||||
CURRENT_PROJECT_BACKGROUND_IMAGE_UPDATE: `${PREFIX}/CURRENT_PROJECT_BACKGROUND_IMAGE_UPDATE`,
|
||||
CURRENT_PROJECT_DELETE: `${PREFIX}/CURRENT_PROJECT_DELETE`,
|
||||
PROJECT_DELETE_HANDLE: `${PREFIX}/PROJECT_DELETE_HANDLE`,
|
||||
|
||||
/* Project managers */
|
||||
|
||||
MANAGER_IN_CURRENT_PROJECT_CREATE: `${PREFIX}/MANAGER_IN_CURRENT_PROJECT_CREATE`,
|
||||
PROJECT_MANAGER_CREATE_HANDLE: `${PREFIX}/PROJECT_MANAGER_CREATE_HANDLE`,
|
||||
PROJECT_MANAGER_DELETE: `${PREFIX}/PROJECT_MANAGER_DELETE`,
|
||||
PROJECT_MANAGER_DELETE_HANDLE: `${PREFIX}/PROJECT_MANAGER_DELETE_HANDLE`,
|
||||
|
||||
/* Boards */
|
||||
|
||||
BOARD_IN_CURRENT_PROJECT_CREATE: `${PREFIX}/BOARD_IN_CURRENT_PROJECT_CREATE`,
|
||||
BOARD_CREATE_HANDLE: `${PREFIX}/BOARD_CREATE_HANDLE`,
|
||||
BOARD_FETCH: `${PREFIX}/BOARD_FETCH`,
|
||||
BOARD_UPDATE: `${PREFIX}/BOARD_UPDATE`,
|
||||
BOARD_UPDATE_HANDLE: `${PREFIX}/BOARD_UPDATE_HANDLE`,
|
||||
BOARD_MOVE: `${PREFIX}/BOARD_MOVE`,
|
||||
BOARD_DELETE: `${PREFIX}/BOARD_DELETE`,
|
||||
BOARD_DELETE_HANDLE: `${PREFIX}/BOARD_DELETE_HANDLE`,
|
||||
|
||||
/* Board memberships */
|
||||
|
||||
MEMBERSHIP_IN_CURRENT_BOARD_CREATE: `${PREFIX}/MEMBERSHIP_IN_CURRENT_BOARD_CREATE`,
|
||||
BOARD_MEMBERSHIP_CREATE_HANDLE: `${PREFIX}/BOARD_MEMBERSHIP_CREATE_HANDLE`,
|
||||
BOARD_MEMBERSHIP_UPDATE: `${PREFIX}/BOARD_MEMBERSHIP_UPDATE`,
|
||||
BOARD_MEMBERSHIP_UPDATE_HANDLE: `${PREFIX}/BOARD_MEMBERSHIP_UPDATE_HANDLE`,
|
||||
BOARD_MEMBERSHIP_DELETE: `${PREFIX}/BOARD_MEMBERSHIP_DELETE`,
|
||||
BOARD_MEMBERSHIP_DELETE_HANDLE: `${PREFIX}/BOARD_MEMBERSHIP_DELETE_HANDLE`,
|
||||
|
||||
/* Labels */
|
||||
|
||||
LABEL_IN_CURRENT_BOARD_CREATE: `${PREFIX}/LABEL_IN_CURRENT_BOARD_CREATE`,
|
||||
LABEL_CREATE_HANDLE: `${PREFIX}/LABEL_CREATE_HANDLE`,
|
||||
LABEL_UPDATE: `${PREFIX}/LABEL_UPDATE`,
|
||||
LABEL_UPDATE_HANDLE: `${PREFIX}/LABEL_UPDATE_HANDLE`,
|
||||
LABEL_MOVE: `${PREFIX}/LABEL_MOVE`,
|
||||
LABEL_DELETE: `${PREFIX}/LABEL_DELETE`,
|
||||
LABEL_DELETE_HANDLE: `${PREFIX}/LABEL_DELETE_HANDLE`,
|
||||
LABEL_TO_CARD_ADD: `${PREFIX}/LABEL_TO_CARD_ADD`,
|
||||
LABEL_TO_CURRENT_CARD_ADD: `${PREFIX}/LABEL_TO_CURRENT_CARD_ADD`,
|
||||
LABEL_TO_CARD_ADD_HANDLE: `${PREFIX}/LABEL_TO_CARD_ADD_HANDLE`,
|
||||
LABEL_FROM_CARD_REMOVE: `${PREFIX}/LABEL_FROM_CARD_REMOVE`,
|
||||
LABEL_FROM_CURRENT_CARD_REMOVE: `${PREFIX}/LABEL_FROM_CURRENT_CARD_REMOVE`,
|
||||
LABEL_FROM_CARD_REMOVE_HANDLE: `${PREFIX}/LABEL_FROM_CARD_REMOVE_HANDLE`,
|
||||
LABEL_TO_FILTER_IN_CURRENT_BOARD_ADD: `${PREFIX}/LABEL_TO_FILTER_IN_CURRENT_BOARD_ADD`,
|
||||
LABEL_FROM_FILTER_IN_CURRENT_BOARD_REMOVE: `${PREFIX}/LABEL_FROM_FILTER_IN_CURRENT_BOARD_REMOVE`,
|
||||
|
||||
/* Lists */
|
||||
|
||||
LIST_IN_CURRENT_BOARD_CREATE: `${PREFIX}/LIST_IN_CURRENT_BOARD_CREATE`,
|
||||
LIST_CREATE_HANDLE: `${PREFIX}/LIST_CREATE_HANDLE`,
|
||||
LIST_UPDATE: `${PREFIX}/LIST_UPDATE`,
|
||||
LIST_UPDATE_HANDLE: `${PREFIX}/LIST_UPDATE_HANDLE`,
|
||||
LIST_MOVE: `${PREFIX}/LIST_MOVE`,
|
||||
LIST_DELETE: `${PREFIX}/LIST_DELETE`,
|
||||
LIST_DELETE_HANDLE: `${PREFIX}/LIST_DELETE_HANDLE`,
|
||||
|
||||
/* Cards */
|
||||
|
||||
CARD_CREATE: `${PREFIX}/CARD_CREATE`,
|
||||
CARD_CREATE_HANDLE: `${PREFIX}/CARD_CREATE_HANDLE`,
|
||||
CARD_UPDATE: `${PREFIX}/CARD_UPDATE`,
|
||||
CURRENT_CARD_UPDATE: `${PREFIX}/CURRENT_CARD_UPDATE`,
|
||||
CARD_UPDATE_HANDLE: `${PREFIX}/CARD_UPDATE_HANDLE`,
|
||||
CARD_MOVE: `${PREFIX}/CARD_MOVE`,
|
||||
CURRENT_CARD_MOVE: `${PREFIX}/CURRENT_CARD_MOVE`,
|
||||
CARD_TRANSFER: `${PREFIX}/CARD_TRANSFER`,
|
||||
CURRENT_CARD_TRANSFER: `${PREFIX}/CURRENT_CARD_TRANSFER`,
|
||||
CARD_DUPLICATE: `${PREFIX}/CARD_DUPLICATE`,
|
||||
CURRENT_CARD_DUPLICATE: `${PREFIX}/CURRENT_CARD_DUPLICATE`,
|
||||
CARD_DELETE: `${PREFIX}/CARD_DELETE`,
|
||||
CURRENT_CARD_DELETE: `${PREFIX}/CURRENT_CARD_DELETE`,
|
||||
CARD_DELETE_HANDLE: `${PREFIX}/CARD_DELETE_HANDLE`,
|
||||
|
||||
/* Tasks */
|
||||
|
||||
TASK_IN_CURRENT_CARD_CREATE: `${PREFIX}/TASK_IN_CURRENT_CARD_CREATE`,
|
||||
TASK_CREATE_HANDLE: `${PREFIX}/TASK_CREATE_HANDLE`,
|
||||
TASK_UPDATE: `${PREFIX}/TASK_UPDATE`,
|
||||
TASK_UPDATE_HANDLE: `${PREFIX}/TASK_UPDATE_HANDLE`,
|
||||
TASK_MOVE: `${PREFIX}/TASK_MOVE`,
|
||||
TASK_DELETE: `${PREFIX}/TASK_DELETE`,
|
||||
TASK_DELETE_HANDLE: `${PREFIX}/TASK_DELETE_HANDLE`,
|
||||
|
||||
/* Attachments */
|
||||
|
||||
ATTACHMENT_IN_CURRENT_CARD_CREATE: `${PREFIX}/ATTACHMENT_IN_CURRENT_CARD_CREATE`,
|
||||
ATTACHMENT_CREATE_HANDLE: `${PREFIX}/ATTACHMENT_CREATE_HANDLE`,
|
||||
ATTACHMENT_UPDATE: `${PREFIX}/ATTACHMENT_UPDATE`,
|
||||
ATTACHMENT_UPDATE_HANDLE: `${PREFIX}/ATTACHMENT_UPDATE_HANDLE`,
|
||||
ATTACHMENT_DELETE: `${PREFIX}/ATTACHMENT_DELETE`,
|
||||
ATTACHMENT_DELETE_HANDLE: `${PREFIX}/ATTACHMENT_DELETE_HANDLE`,
|
||||
|
||||
/* Activities */
|
||||
|
||||
ACTIVITIES_IN_CURRENT_CARD_FETCH: `${PREFIX}/ACTIVITIES_IN_CURRENT_CARD_FETCH`,
|
||||
ACTIVITIES_DETAILS_IN_CURRENT_CARD_TOGGLE: `${PREFIX}/ACTIVITIES_DETAILS_IN_CURRENT_CARD_TOGGLE`,
|
||||
ACTIVITY_CREATE_HANDLE: `${PREFIX}/ACTIVITY_CREATE_HANDLE`,
|
||||
ACTIVITY_UPDATE_HANDLE: `${PREFIX}/ACTIVITY_UPDATE_HANDLE`,
|
||||
ACTIVITY_DELETE_HANDLE: `${PREFIX}/ACTIVITY_DELETE_HANDLE`,
|
||||
|
||||
/* Comment activities */
|
||||
|
||||
COMMENT_ACTIVITY_IN_CURRENT_CARD_CREATE: `${PREFIX}/COMMENT_ACTIVITY_IN_CURRENT_CARD_CREATE`,
|
||||
COMMENT_ACTIVITY_UPDATE: `${PREFIX}/COMMENT_ACTIVITY_UPDATE`,
|
||||
COMMENT_ACTIVITY_DELETE: `${PREFIX}/COMMENT_ACTIVITY_DELETE`,
|
||||
|
||||
/* Notifications */
|
||||
|
||||
NOTIFICATION_CREATE_HANDLE: `${PREFIX}/NOTIFICATION_CREATE_HANDLE`,
|
||||
NOTIFICATION_DELETE: `${PREFIX}/NOTIFICATION_DELETE`,
|
||||
NOTIFICATION_DELETE_HANDLE: `${PREFIX}/NOTIFICATION_DELETE_HANDLE`,
|
||||
};
|
||||
const PREFIX = '@entry';
|
||||
|
||||
export default {
|
||||
PREFIX,
|
||||
|
||||
/* Socket */
|
||||
|
||||
SOCKET_DISCONNECT_HANDLE: `${PREFIX}/SOCKET_DISCONNECT_HANDLE`,
|
||||
SOCKET_RECONNECT_HANDLE: `${PREFIX}/SOCKET_RECONNECT_HANDLE`,
|
||||
|
||||
/* Login */
|
||||
|
||||
AUTHENTICATE: `${PREFIX}/AUTHENTICATE`,
|
||||
USING_OIDC_AUTHENTICATE: `${PREFIX}/USING_OIDC_AUTHENTICATE`,
|
||||
AUTHENTICATE_ERROR_CLEAR: `${PREFIX}/AUTHENTICATE_ERROR_CLEAR`,
|
||||
|
||||
/* Core */
|
||||
|
||||
LOGOUT: `${PREFIX}/LOGOUT`,
|
||||
|
||||
/* Modals */
|
||||
|
||||
MODAL_OPEN: `${PREFIX}/MODAL_OPEN`,
|
||||
MODAL_CLOSE: `${PREFIX}/MODAL_CLOSE`,
|
||||
|
||||
/* Users */
|
||||
|
||||
USER_CREATE: `${PREFIX}/USER_CREATE`,
|
||||
USER_CREATE_HANDLE: `${PREFIX}/USER_CREATE_HANDLE`,
|
||||
USER_CREATE_ERROR_CLEAR: `${PREFIX}/USER_CREATE_ERROR_CLEAR`,
|
||||
USER_UPDATE: `${PREFIX}/USER_UPDATE`,
|
||||
CURRENT_USER_UPDATE: `${PREFIX}/CURRENT_USER_UPDATE`,
|
||||
USER_UPDATE_HANDLE: `${PREFIX}/USER_UPDATE_HANDLE`,
|
||||
CURRENT_USER_LANGUAGE_UPDATE: `${PREFIX}/CURRENT_USER_LANGUAGE_UPDATE`,
|
||||
USER_EMAIL_UPDATE: `${PREFIX}/USER_EMAIL_UPDATE`,
|
||||
CURRENT_USER_EMAIL_UPDATE: `${PREFIX}/CURRENT_USER_EMAIL_UPDATE`,
|
||||
USER_EMAIL_UPDATE_ERROR_CLEAR: `${PREFIX}/USER_EMAIL_UPDATE_ERROR_CLEAR`,
|
||||
CURRENT_USER_EMAIL_UPDATE_ERROR_CLEAR: `${PREFIX}/CURRENT_USER_EMAIL_UPDATE_ERROR_CLEAR`,
|
||||
USER_PASSWORD_UPDATE: `${PREFIX}/USER_PASSWORD_UPDATE`,
|
||||
CURRENT_USER_PASSWORD_UPDATE: `${PREFIX}/CURRENT_USER_PASSWORD_UPDATE`,
|
||||
USER_PASSWORD_UPDATE_ERROR_CLEAR: `${PREFIX}/USER_PASSWORD_UPDATE_ERROR_CLEAR`,
|
||||
CURRENT_USER_PASSWORD_UPDATE_ERROR_CLEAR: `${PREFIX}/CURRENT_USER_PASSWORD_UPDATE_ERROR_CLEAR`,
|
||||
USER_USERNAME_UPDATE: `${PREFIX}/USER_USERNAME_UPDATE`,
|
||||
CURRENT_USER_USERNAME_UPDATE: `${PREFIX}/CURRENT_USER_USERNAME_UPDATE`,
|
||||
USER_USERNAME_UPDATE_ERROR_CLEAR: `${PREFIX}/USER_USERNAME_UPDATE_ERROR_CLEAR`,
|
||||
CURRENT_USER_USERNAME_UPDATE_ERROR_CLEAR: `${PREFIX}/CURRENT_USER_USERNAME_UPDATE_ERROR_CLEAR`,
|
||||
CURRENT_USER_AVATAR_UPDATE: `${PREFIX}/CURRENT_USER_AVATAR_UPDATE`,
|
||||
USER_DELETE: `${PREFIX}/USER_DELETE`,
|
||||
USER_DELETE_HANDLE: `${PREFIX}/USER_DELETE_HANDLE`,
|
||||
USER_TO_CARD_ADD: `${PREFIX}/USER_TO_CARD_ADD`,
|
||||
USER_TO_CURRENT_CARD_ADD: `${PREFIX}/USER_TO_CURRENT_CARD_ADD`,
|
||||
USER_TO_CARD_ADD_HANDLE: `${PREFIX}/USER_TO_CARD_ADD_HANDLE`,
|
||||
USER_FROM_CARD_REMOVE: `${PREFIX}/USER_FROM_CARD_REMOVE`,
|
||||
USER_FROM_CURRENT_CARD_REMOVE: `${PREFIX}/USER_FROM_CURRENT_CARD_REMOVE`,
|
||||
USER_FROM_CARD_REMOVE_HANDLE: `${PREFIX}/USER_FROM_CARD_REMOVE_HANDLE`,
|
||||
USER_TO_FILTER_IN_CURRENT_BOARD_ADD: `${PREFIX}/USER_TO_FILTER_IN_CURRENT_BOARD_ADD`,
|
||||
USER_FROM_FILTER_IN_CURRENT_BOARD_REMOVE: `${PREFIX}/USER_FROM_FILTER_IN_CURRENT_BOARD_REMOVE`,
|
||||
|
||||
/* Projects */
|
||||
|
||||
PROJECT_CREATE: `${PREFIX}/PROJECT_CREATE`,
|
||||
PROJECT_CREATE_HANDLE: `${PREFIX}/PROJECT_CREATE_HANDLE`,
|
||||
CURRENT_PROJECT_UPDATE: `${PREFIX}/CURRENT_PROJECT_UPDATE`,
|
||||
PROJECT_UPDATE_HANDLE: `${PREFIX}/PROJECT_UPDATE_HANDLE`,
|
||||
CURRENT_PROJECT_BACKGROUND_IMAGE_UPDATE: `${PREFIX}/CURRENT_PROJECT_BACKGROUND_IMAGE_UPDATE`,
|
||||
CURRENT_PROJECT_DELETE: `${PREFIX}/CURRENT_PROJECT_DELETE`,
|
||||
PROJECT_DELETE_HANDLE: `${PREFIX}/PROJECT_DELETE_HANDLE`,
|
||||
|
||||
/* Project managers */
|
||||
|
||||
MANAGER_IN_CURRENT_PROJECT_CREATE: `${PREFIX}/MANAGER_IN_CURRENT_PROJECT_CREATE`,
|
||||
PROJECT_MANAGER_CREATE_HANDLE: `${PREFIX}/PROJECT_MANAGER_CREATE_HANDLE`,
|
||||
PROJECT_MANAGER_DELETE: `${PREFIX}/PROJECT_MANAGER_DELETE`,
|
||||
PROJECT_MANAGER_DELETE_HANDLE: `${PREFIX}/PROJECT_MANAGER_DELETE_HANDLE`,
|
||||
|
||||
/* Boards */
|
||||
|
||||
BOARD_IN_CURRENT_PROJECT_CREATE: `${PREFIX}/BOARD_IN_CURRENT_PROJECT_CREATE`,
|
||||
BOARD_CREATE_HANDLE: `${PREFIX}/BOARD_CREATE_HANDLE`,
|
||||
BOARD_FETCH: `${PREFIX}/BOARD_FETCH`,
|
||||
BOARD_UPDATE: `${PREFIX}/BOARD_UPDATE`,
|
||||
BOARD_UPDATE_HANDLE: `${PREFIX}/BOARD_UPDATE_HANDLE`,
|
||||
BOARD_MOVE: `${PREFIX}/BOARD_MOVE`,
|
||||
BOARD_DELETE: `${PREFIX}/BOARD_DELETE`,
|
||||
BOARD_DELETE_HANDLE: `${PREFIX}/BOARD_DELETE_HANDLE`,
|
||||
|
||||
/* Board memberships */
|
||||
|
||||
MEMBERSHIP_IN_CURRENT_BOARD_CREATE: `${PREFIX}/MEMBERSHIP_IN_CURRENT_BOARD_CREATE`,
|
||||
BOARD_MEMBERSHIP_CREATE_HANDLE: `${PREFIX}/BOARD_MEMBERSHIP_CREATE_HANDLE`,
|
||||
BOARD_MEMBERSHIP_UPDATE: `${PREFIX}/BOARD_MEMBERSHIP_UPDATE`,
|
||||
BOARD_MEMBERSHIP_UPDATE_HANDLE: `${PREFIX}/BOARD_MEMBERSHIP_UPDATE_HANDLE`,
|
||||
BOARD_MEMBERSHIP_DELETE: `${PREFIX}/BOARD_MEMBERSHIP_DELETE`,
|
||||
BOARD_MEMBERSHIP_DELETE_HANDLE: `${PREFIX}/BOARD_MEMBERSHIP_DELETE_HANDLE`,
|
||||
|
||||
/* Labels */
|
||||
|
||||
LABEL_IN_CURRENT_BOARD_CREATE: `${PREFIX}/LABEL_IN_CURRENT_BOARD_CREATE`,
|
||||
LABEL_CREATE_HANDLE: `${PREFIX}/LABEL_CREATE_HANDLE`,
|
||||
LABEL_UPDATE: `${PREFIX}/LABEL_UPDATE`,
|
||||
LABEL_UPDATE_HANDLE: `${PREFIX}/LABEL_UPDATE_HANDLE`,
|
||||
LABEL_MOVE: `${PREFIX}/LABEL_MOVE`,
|
||||
LABEL_DELETE: `${PREFIX}/LABEL_DELETE`,
|
||||
LABEL_DELETE_HANDLE: `${PREFIX}/LABEL_DELETE_HANDLE`,
|
||||
LABEL_TO_CARD_ADD: `${PREFIX}/LABEL_TO_CARD_ADD`,
|
||||
LABEL_TO_CURRENT_CARD_ADD: `${PREFIX}/LABEL_TO_CURRENT_CARD_ADD`,
|
||||
LABEL_TO_CARD_ADD_HANDLE: `${PREFIX}/LABEL_TO_CARD_ADD_HANDLE`,
|
||||
LABEL_FROM_CARD_REMOVE: `${PREFIX}/LABEL_FROM_CARD_REMOVE`,
|
||||
LABEL_FROM_CURRENT_CARD_REMOVE: `${PREFIX}/LABEL_FROM_CURRENT_CARD_REMOVE`,
|
||||
LABEL_FROM_CARD_REMOVE_HANDLE: `${PREFIX}/LABEL_FROM_CARD_REMOVE_HANDLE`,
|
||||
LABEL_TO_FILTER_IN_CURRENT_BOARD_ADD: `${PREFIX}/LABEL_TO_FILTER_IN_CURRENT_BOARD_ADD`,
|
||||
LABEL_FROM_FILTER_IN_CURRENT_BOARD_REMOVE: `${PREFIX}/LABEL_FROM_FILTER_IN_CURRENT_BOARD_REMOVE`,
|
||||
|
||||
/* Lists */
|
||||
|
||||
LIST_IN_CURRENT_BOARD_CREATE: `${PREFIX}/LIST_IN_CURRENT_BOARD_CREATE`,
|
||||
LIST_CREATE_HANDLE: `${PREFIX}/LIST_CREATE_HANDLE`,
|
||||
LIST_UPDATE: `${PREFIX}/LIST_UPDATE`,
|
||||
LIST_UPDATE_HANDLE: `${PREFIX}/LIST_UPDATE_HANDLE`,
|
||||
LIST_MOVE: `${PREFIX}/LIST_MOVE`,
|
||||
LIST_DELETE: `${PREFIX}/LIST_DELETE`,
|
||||
LIST_DELETE_HANDLE: `${PREFIX}/LIST_DELETE_HANDLE`,
|
||||
|
||||
/* Cards */
|
||||
|
||||
CARD_CREATE: `${PREFIX}/CARD_CREATE`,
|
||||
CARD_CREATE_HANDLE: `${PREFIX}/CARD_CREATE_HANDLE`,
|
||||
CARD_UPDATE: `${PREFIX}/CARD_UPDATE`,
|
||||
CURRENT_CARD_UPDATE: `${PREFIX}/CURRENT_CARD_UPDATE`,
|
||||
CARD_UPDATE_HANDLE: `${PREFIX}/CARD_UPDATE_HANDLE`,
|
||||
CARD_MOVE: `${PREFIX}/CARD_MOVE`,
|
||||
CURRENT_CARD_MOVE: `${PREFIX}/CURRENT_CARD_MOVE`,
|
||||
CARD_TRANSFER: `${PREFIX}/CARD_TRANSFER`,
|
||||
CURRENT_CARD_TRANSFER: `${PREFIX}/CURRENT_CARD_TRANSFER`,
|
||||
CARD_DUPLICATE: `${PREFIX}/CARD_DUPLICATE`,
|
||||
CURRENT_CARD_DUPLICATE: `${PREFIX}/CURRENT_CARD_DUPLICATE`,
|
||||
CARD_DELETE: `${PREFIX}/CARD_DELETE`,
|
||||
CURRENT_CARD_DELETE: `${PREFIX}/CURRENT_CARD_DELETE`,
|
||||
CARD_DELETE_HANDLE: `${PREFIX}/CARD_DELETE_HANDLE`,
|
||||
|
||||
/* Tasks */
|
||||
|
||||
TASK_IN_CURRENT_CARD_CREATE: `${PREFIX}/TASK_IN_CURRENT_CARD_CREATE`,
|
||||
TASK_CREATE_HANDLE: `${PREFIX}/TASK_CREATE_HANDLE`,
|
||||
TASK_UPDATE: `${PREFIX}/TASK_UPDATE`,
|
||||
TASK_UPDATE_HANDLE: `${PREFIX}/TASK_UPDATE_HANDLE`,
|
||||
TASK_MOVE: `${PREFIX}/TASK_MOVE`,
|
||||
TASK_DELETE: `${PREFIX}/TASK_DELETE`,
|
||||
TASK_DELETE_HANDLE: `${PREFIX}/TASK_DELETE_HANDLE`,
|
||||
|
||||
/* Attachments */
|
||||
|
||||
ATTACHMENT_IN_CURRENT_CARD_CREATE: `${PREFIX}/ATTACHMENT_IN_CURRENT_CARD_CREATE`,
|
||||
ATTACHMENT_CREATE_HANDLE: `${PREFIX}/ATTACHMENT_CREATE_HANDLE`,
|
||||
ATTACHMENT_UPDATE: `${PREFIX}/ATTACHMENT_UPDATE`,
|
||||
ATTACHMENT_UPDATE_HANDLE: `${PREFIX}/ATTACHMENT_UPDATE_HANDLE`,
|
||||
ATTACHMENT_DELETE: `${PREFIX}/ATTACHMENT_DELETE`,
|
||||
ATTACHMENT_DELETE_HANDLE: `${PREFIX}/ATTACHMENT_DELETE_HANDLE`,
|
||||
|
||||
/* Activities */
|
||||
|
||||
ACTIVITIES_IN_CURRENT_CARD_FETCH: `${PREFIX}/ACTIVITIES_IN_CURRENT_CARD_FETCH`,
|
||||
ACTIVITIES_DETAILS_IN_CURRENT_CARD_TOGGLE: `${PREFIX}/ACTIVITIES_DETAILS_IN_CURRENT_CARD_TOGGLE`,
|
||||
ACTIVITY_CREATE_HANDLE: `${PREFIX}/ACTIVITY_CREATE_HANDLE`,
|
||||
ACTIVITY_UPDATE_HANDLE: `${PREFIX}/ACTIVITY_UPDATE_HANDLE`,
|
||||
ACTIVITY_DELETE_HANDLE: `${PREFIX}/ACTIVITY_DELETE_HANDLE`,
|
||||
|
||||
/* Comment activities */
|
||||
|
||||
COMMENT_ACTIVITY_IN_CURRENT_CARD_CREATE: `${PREFIX}/COMMENT_ACTIVITY_IN_CURRENT_CARD_CREATE`,
|
||||
COMMENT_ACTIVITY_UPDATE: `${PREFIX}/COMMENT_ACTIVITY_UPDATE`,
|
||||
COMMENT_ACTIVITY_DELETE: `${PREFIX}/COMMENT_ACTIVITY_DELETE`,
|
||||
|
||||
/* Notifications */
|
||||
|
||||
NOTIFICATION_CREATE_HANDLE: `${PREFIX}/NOTIFICATION_CREATE_HANDLE`,
|
||||
NOTIFICATION_DELETE: `${PREFIX}/NOTIFICATION_DELETE`,
|
||||
NOTIFICATION_DELETE_HANDLE: `${PREFIX}/NOTIFICATION_DELETE_HANDLE`,
|
||||
};
|
||||
|
||||
@ -1,80 +1,80 @@
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import selectors from '../selectors';
|
||||
import entryActions from '../entry-actions';
|
||||
import { BoardMembershipRoles } from '../constants/Enums';
|
||||
import Card from '../components/Card';
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const selectCardById = selectors.makeSelectCardById();
|
||||
const selectUsersByCardId = selectors.makeSelectUsersByCardId();
|
||||
const selectLabelsByCardId = selectors.makeSelectLabelsByCardId();
|
||||
const selectTasksByCardId = selectors.makeSelectTasksByCardId();
|
||||
const selectNotificationsTotalByCardId = selectors.makeSelectNotificationsTotalByCardId();
|
||||
|
||||
return (state, { id, index }) => {
|
||||
const { projectId } = selectors.selectPath(state);
|
||||
const allProjectsToLists = selectors.selectProjectsToListsForCurrentUser(state);
|
||||
const allBoardMemberships = selectors.selectMembershipsForCurrentBoard(state);
|
||||
const allLabels = selectors.selectLabelsForCurrentBoard(state);
|
||||
const currentUserMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state);
|
||||
|
||||
const { name, dueDate, stopwatch, coverUrl, boardId, listId, isPersisted } = selectCardById(
|
||||
state,
|
||||
id,
|
||||
);
|
||||
|
||||
const users = selectUsersByCardId(state, id);
|
||||
const labels = selectLabelsByCardId(state, id);
|
||||
const tasks = selectTasksByCardId(state, id);
|
||||
const notificationsTotal = selectNotificationsTotalByCardId(state, id);
|
||||
|
||||
const isCurrentUserEditor =
|
||||
!!currentUserMembership && currentUserMembership.role === BoardMembershipRoles.EDITOR;
|
||||
|
||||
return {
|
||||
id,
|
||||
index,
|
||||
name,
|
||||
dueDate,
|
||||
stopwatch,
|
||||
coverUrl,
|
||||
boardId,
|
||||
listId,
|
||||
projectId,
|
||||
isPersisted,
|
||||
notificationsTotal,
|
||||
users,
|
||||
labels,
|
||||
tasks,
|
||||
allProjectsToLists,
|
||||
allBoardMemberships,
|
||||
allLabels,
|
||||
canEdit: isCurrentUserEditor,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch, { id }) =>
|
||||
bindActionCreators(
|
||||
{
|
||||
onUpdate: (data) => entryActions.updateCard(id, data),
|
||||
onMove: (listId, index) => entryActions.moveCard(id, listId, index),
|
||||
onTransfer: (boardId, listId) => entryActions.transferCard(id, boardId, listId),
|
||||
onDuplicate: () => entryActions.duplicateCard(id),
|
||||
onDelete: () => entryActions.deleteCard(id),
|
||||
onUserAdd: (userId) => entryActions.addUserToCard(userId, id),
|
||||
onUserRemove: (userId) => entryActions.removeUserFromCard(userId, id),
|
||||
onBoardFetch: entryActions.fetchBoard,
|
||||
onLabelAdd: (labelId) => entryActions.addLabelToCard(labelId, id),
|
||||
onLabelRemove: (labelId) => entryActions.removeLabelFromCard(labelId, id),
|
||||
onLabelCreate: (data) => entryActions.createLabelInCurrentBoard(data),
|
||||
onLabelUpdate: (labelId, data) => entryActions.updateLabel(labelId, data),
|
||||
onLabelMove: (labelId, index) => entryActions.moveLabel(labelId, index),
|
||||
onLabelDelete: (labelId) => entryActions.deleteLabel(labelId),
|
||||
},
|
||||
dispatch,
|
||||
);
|
||||
|
||||
export default connect(makeMapStateToProps, mapDispatchToProps)(Card);
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import selectors from '../selectors';
|
||||
import entryActions from '../entry-actions';
|
||||
import { BoardMembershipRoles } from '../constants/Enums';
|
||||
import Card from '../components/Card';
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const selectCardById = selectors.makeSelectCardById();
|
||||
const selectUsersByCardId = selectors.makeSelectUsersByCardId();
|
||||
const selectLabelsByCardId = selectors.makeSelectLabelsByCardId();
|
||||
const selectTasksByCardId = selectors.makeSelectTasksByCardId();
|
||||
const selectNotificationsTotalByCardId = selectors.makeSelectNotificationsTotalByCardId();
|
||||
|
||||
return (state, { id, index }) => {
|
||||
const { projectId } = selectors.selectPath(state);
|
||||
const allProjectsToLists = selectors.selectProjectsToListsForCurrentUser(state);
|
||||
const allBoardMemberships = selectors.selectMembershipsForCurrentBoard(state);
|
||||
const allLabels = selectors.selectLabelsForCurrentBoard(state);
|
||||
const currentUserMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state);
|
||||
|
||||
const { name, dueDate, stopwatch, coverUrl, boardId, listId, isPersisted } = selectCardById(
|
||||
state,
|
||||
id,
|
||||
);
|
||||
|
||||
const users = selectUsersByCardId(state, id);
|
||||
const labels = selectLabelsByCardId(state, id);
|
||||
const tasks = selectTasksByCardId(state, id);
|
||||
const notificationsTotal = selectNotificationsTotalByCardId(state, id);
|
||||
|
||||
const isCurrentUserEditor =
|
||||
!!currentUserMembership && currentUserMembership.role === BoardMembershipRoles.EDITOR;
|
||||
|
||||
return {
|
||||
id,
|
||||
index,
|
||||
name,
|
||||
dueDate,
|
||||
stopwatch,
|
||||
coverUrl,
|
||||
boardId,
|
||||
listId,
|
||||
projectId,
|
||||
isPersisted,
|
||||
notificationsTotal,
|
||||
users,
|
||||
labels,
|
||||
tasks,
|
||||
allProjectsToLists,
|
||||
allBoardMemberships,
|
||||
allLabels,
|
||||
canEdit: isCurrentUserEditor,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch, { id }) =>
|
||||
bindActionCreators(
|
||||
{
|
||||
onUpdate: (data) => entryActions.updateCard(id, data),
|
||||
onMove: (listId, index) => entryActions.moveCard(id, listId, index),
|
||||
onTransfer: (boardId, listId) => entryActions.transferCard(id, boardId, listId),
|
||||
onDuplicate: () => entryActions.duplicateCard(id),
|
||||
onDelete: () => entryActions.deleteCard(id),
|
||||
onUserAdd: (userId) => entryActions.addUserToCard(userId, id),
|
||||
onUserRemove: (userId) => entryActions.removeUserFromCard(userId, id),
|
||||
onBoardFetch: entryActions.fetchBoard,
|
||||
onLabelAdd: (labelId) => entryActions.addLabelToCard(labelId, id),
|
||||
onLabelRemove: (labelId) => entryActions.removeLabelFromCard(labelId, id),
|
||||
onLabelCreate: (data) => entryActions.createLabelInCurrentBoard(data),
|
||||
onLabelUpdate: (labelId, data) => entryActions.updateLabel(labelId, data),
|
||||
onLabelMove: (labelId, index) => entryActions.moveLabel(labelId, index),
|
||||
onLabelDelete: (labelId) => entryActions.deleteLabel(labelId),
|
||||
},
|
||||
dispatch,
|
||||
);
|
||||
|
||||
export default connect(makeMapStateToProps, mapDispatchToProps)(Card);
|
||||
|
||||
@ -1,115 +1,115 @@
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import omit from 'lodash/omit';
|
||||
import { push } from '../lib/redux-router';
|
||||
|
||||
import selectors from '../selectors';
|
||||
import entryActions from '../entry-actions';
|
||||
import Paths from '../constants/Paths';
|
||||
import { BoardMembershipRoles } from '../constants/Enums';
|
||||
import CardModal from '../components/CardModal';
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const { projectId } = selectors.selectPath(state);
|
||||
const allProjectsToLists = selectors.selectProjectsToListsForCurrentUser(state);
|
||||
const isCurrentUserManager = selectors.selectIsCurrentUserManagerForCurrentProject(state);
|
||||
const allBoardMemberships = selectors.selectMembershipsForCurrentBoard(state);
|
||||
const allLabels = selectors.selectLabelsForCurrentBoard(state);
|
||||
const currentUserMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state);
|
||||
|
||||
const {
|
||||
name,
|
||||
description,
|
||||
dueDate,
|
||||
stopwatch,
|
||||
isSubscribed,
|
||||
isActivitiesFetching,
|
||||
isAllActivitiesFetched,
|
||||
isActivitiesDetailsVisible,
|
||||
isActivitiesDetailsFetching,
|
||||
boardId,
|
||||
listId,
|
||||
} = selectors.selectCurrentCard(state);
|
||||
|
||||
const users = selectors.selectUsersForCurrentCard(state);
|
||||
const labels = selectors.selectLabelsForCurrentCard(state);
|
||||
const tasks = selectors.selectTasksForCurrentCard(state);
|
||||
const attachments = selectors.selectAttachmentsForCurrentCard(state);
|
||||
const activities = selectors.selectActivitiesForCurrentCard(state);
|
||||
|
||||
let isCurrentUserEditor = false;
|
||||
let isCurrentUserEditorOrCanComment = false;
|
||||
|
||||
if (currentUserMembership) {
|
||||
isCurrentUserEditor = currentUserMembership.role === BoardMembershipRoles.EDITOR;
|
||||
isCurrentUserEditorOrCanComment = isCurrentUserEditor || currentUserMembership.canComment;
|
||||
}
|
||||
|
||||
return {
|
||||
name,
|
||||
description,
|
||||
dueDate,
|
||||
stopwatch,
|
||||
isSubscribed,
|
||||
isActivitiesFetching,
|
||||
isAllActivitiesFetched,
|
||||
isActivitiesDetailsVisible,
|
||||
isActivitiesDetailsFetching,
|
||||
listId,
|
||||
boardId,
|
||||
projectId,
|
||||
users,
|
||||
labels,
|
||||
tasks,
|
||||
attachments,
|
||||
activities,
|
||||
allProjectsToLists,
|
||||
allBoardMemberships,
|
||||
allLabels,
|
||||
canEdit: isCurrentUserEditor,
|
||||
canEditCommentActivities: isCurrentUserEditorOrCanComment,
|
||||
canEditAllCommentActivities: isCurrentUserManager,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) =>
|
||||
bindActionCreators(
|
||||
{
|
||||
onUpdate: entryActions.updateCurrentCard,
|
||||
onMove: entryActions.moveCurrentCard,
|
||||
onTransfer: entryActions.transferCurrentCard,
|
||||
onDuplicate: entryActions.duplicateCurrentCard,
|
||||
onDelete: entryActions.deleteCurrentCard,
|
||||
onUserAdd: entryActions.addUserToCurrentCard,
|
||||
onUserRemove: entryActions.removeUserFromCurrentCard,
|
||||
onBoardFetch: entryActions.fetchBoard,
|
||||
onLabelAdd: entryActions.addLabelToCurrentCard,
|
||||
onLabelRemove: entryActions.removeLabelFromCurrentCard,
|
||||
onLabelCreate: entryActions.createLabelInCurrentBoard,
|
||||
onLabelUpdate: entryActions.updateLabel,
|
||||
onLabelMove: entryActions.moveLabel,
|
||||
onLabelDelete: entryActions.deleteLabel,
|
||||
onTaskCreate: entryActions.createTaskInCurrentCard,
|
||||
onTaskUpdate: entryActions.updateTask,
|
||||
onTaskMove: entryActions.moveTask,
|
||||
onTaskDelete: entryActions.deleteTask,
|
||||
onAttachmentCreate: entryActions.createAttachmentInCurrentCard,
|
||||
onAttachmentUpdate: entryActions.updateAttachment,
|
||||
onAttachmentDelete: entryActions.deleteAttachment,
|
||||
onActivitiesFetch: entryActions.fetchActivitiesInCurrentCard,
|
||||
onActivitiesDetailsToggle: entryActions.toggleActivitiesDetailsInCurrentCard,
|
||||
onCommentActivityCreate: entryActions.createCommentActivityInCurrentCard,
|
||||
onCommentActivityUpdate: entryActions.updateCommentActivity,
|
||||
onCommentActivityDelete: entryActions.deleteCommentActivity,
|
||||
push,
|
||||
},
|
||||
dispatch,
|
||||
);
|
||||
|
||||
const mergeProps = (stateProps, dispatchProps) => ({
|
||||
...stateProps,
|
||||
...omit(dispatchProps, 'push'),
|
||||
onClose: () => dispatchProps.push(Paths.BOARDS.replace(':id', stateProps.boardId)),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(CardModal);
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import omit from 'lodash/omit';
|
||||
import { push } from '../lib/redux-router';
|
||||
|
||||
import selectors from '../selectors';
|
||||
import entryActions from '../entry-actions';
|
||||
import Paths from '../constants/Paths';
|
||||
import { BoardMembershipRoles } from '../constants/Enums';
|
||||
import CardModal from '../components/CardModal';
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const { projectId } = selectors.selectPath(state);
|
||||
const allProjectsToLists = selectors.selectProjectsToListsForCurrentUser(state);
|
||||
const isCurrentUserManager = selectors.selectIsCurrentUserManagerForCurrentProject(state);
|
||||
const allBoardMemberships = selectors.selectMembershipsForCurrentBoard(state);
|
||||
const allLabels = selectors.selectLabelsForCurrentBoard(state);
|
||||
const currentUserMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state);
|
||||
|
||||
const {
|
||||
name,
|
||||
description,
|
||||
dueDate,
|
||||
stopwatch,
|
||||
isSubscribed,
|
||||
isActivitiesFetching,
|
||||
isAllActivitiesFetched,
|
||||
isActivitiesDetailsVisible,
|
||||
isActivitiesDetailsFetching,
|
||||
boardId,
|
||||
listId,
|
||||
} = selectors.selectCurrentCard(state);
|
||||
|
||||
const users = selectors.selectUsersForCurrentCard(state);
|
||||
const labels = selectors.selectLabelsForCurrentCard(state);
|
||||
const tasks = selectors.selectTasksForCurrentCard(state);
|
||||
const attachments = selectors.selectAttachmentsForCurrentCard(state);
|
||||
const activities = selectors.selectActivitiesForCurrentCard(state);
|
||||
|
||||
let isCurrentUserEditor = false;
|
||||
let isCurrentUserEditorOrCanComment = false;
|
||||
|
||||
if (currentUserMembership) {
|
||||
isCurrentUserEditor = currentUserMembership.role === BoardMembershipRoles.EDITOR;
|
||||
isCurrentUserEditorOrCanComment = isCurrentUserEditor || currentUserMembership.canComment;
|
||||
}
|
||||
|
||||
return {
|
||||
name,
|
||||
description,
|
||||
dueDate,
|
||||
stopwatch,
|
||||
isSubscribed,
|
||||
isActivitiesFetching,
|
||||
isAllActivitiesFetched,
|
||||
isActivitiesDetailsVisible,
|
||||
isActivitiesDetailsFetching,
|
||||
listId,
|
||||
boardId,
|
||||
projectId,
|
||||
users,
|
||||
labels,
|
||||
tasks,
|
||||
attachments,
|
||||
activities,
|
||||
allProjectsToLists,
|
||||
allBoardMemberships,
|
||||
allLabels,
|
||||
canEdit: isCurrentUserEditor,
|
||||
canEditCommentActivities: isCurrentUserEditorOrCanComment,
|
||||
canEditAllCommentActivities: isCurrentUserManager,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) =>
|
||||
bindActionCreators(
|
||||
{
|
||||
onUpdate: entryActions.updateCurrentCard,
|
||||
onMove: entryActions.moveCurrentCard,
|
||||
onTransfer: entryActions.transferCurrentCard,
|
||||
onDuplicate: entryActions.duplicateCurrentCard,
|
||||
onDelete: entryActions.deleteCurrentCard,
|
||||
onUserAdd: entryActions.addUserToCurrentCard,
|
||||
onUserRemove: entryActions.removeUserFromCurrentCard,
|
||||
onBoardFetch: entryActions.fetchBoard,
|
||||
onLabelAdd: entryActions.addLabelToCurrentCard,
|
||||
onLabelRemove: entryActions.removeLabelFromCurrentCard,
|
||||
onLabelCreate: entryActions.createLabelInCurrentBoard,
|
||||
onLabelUpdate: entryActions.updateLabel,
|
||||
onLabelMove: entryActions.moveLabel,
|
||||
onLabelDelete: entryActions.deleteLabel,
|
||||
onTaskCreate: entryActions.createTaskInCurrentCard,
|
||||
onTaskUpdate: entryActions.updateTask,
|
||||
onTaskMove: entryActions.moveTask,
|
||||
onTaskDelete: entryActions.deleteTask,
|
||||
onAttachmentCreate: entryActions.createAttachmentInCurrentCard,
|
||||
onAttachmentUpdate: entryActions.updateAttachment,
|
||||
onAttachmentDelete: entryActions.deleteAttachment,
|
||||
onActivitiesFetch: entryActions.fetchActivitiesInCurrentCard,
|
||||
onActivitiesDetailsToggle: entryActions.toggleActivitiesDetailsInCurrentCard,
|
||||
onCommentActivityCreate: entryActions.createCommentActivityInCurrentCard,
|
||||
onCommentActivityUpdate: entryActions.updateCommentActivity,
|
||||
onCommentActivityDelete: entryActions.deleteCommentActivity,
|
||||
push,
|
||||
},
|
||||
dispatch,
|
||||
);
|
||||
|
||||
const mergeProps = (stateProps, dispatchProps) => ({
|
||||
...stateProps,
|
||||
...omit(dispatchProps, 'push'),
|
||||
onClose: () => dispatchProps.push(Paths.BOARDS.replace(':id', stateProps.boardId)),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(CardModal);
|
||||
|
||||
@ -1,123 +1,123 @@
|
||||
import EntryActionTypes from '../constants/EntryActionTypes';
|
||||
|
||||
const createCard = (listId, data, autoOpen) => ({
|
||||
type: EntryActionTypes.CARD_CREATE,
|
||||
payload: {
|
||||
listId,
|
||||
data,
|
||||
autoOpen,
|
||||
},
|
||||
});
|
||||
|
||||
const handleCardCreate = (card) => ({
|
||||
type: EntryActionTypes.CARD_CREATE_HANDLE,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
const updateCard = (id, data) => ({
|
||||
type: EntryActionTypes.CARD_UPDATE,
|
||||
payload: {
|
||||
id,
|
||||
data,
|
||||
},
|
||||
});
|
||||
|
||||
const updateCurrentCard = (data) => ({
|
||||
type: EntryActionTypes.CURRENT_CARD_UPDATE,
|
||||
payload: {
|
||||
data,
|
||||
},
|
||||
});
|
||||
|
||||
const handleCardUpdate = (card) => ({
|
||||
type: EntryActionTypes.CARD_UPDATE_HANDLE,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
const moveCard = (id, listId, index = 0) => ({
|
||||
type: EntryActionTypes.CARD_MOVE,
|
||||
payload: {
|
||||
id,
|
||||
listId,
|
||||
index,
|
||||
},
|
||||
});
|
||||
|
||||
const moveCurrentCard = (listId, index = 0) => ({
|
||||
type: EntryActionTypes.CURRENT_CARD_MOVE,
|
||||
payload: {
|
||||
listId,
|
||||
index,
|
||||
},
|
||||
});
|
||||
|
||||
const transferCard = (id, boardId, listId, index = 0) => ({
|
||||
type: EntryActionTypes.CARD_TRANSFER,
|
||||
payload: {
|
||||
id,
|
||||
boardId,
|
||||
listId,
|
||||
index,
|
||||
},
|
||||
});
|
||||
|
||||
const transferCurrentCard = (boardId, listId, index = 0) => ({
|
||||
type: EntryActionTypes.CURRENT_CARD_TRANSFER,
|
||||
payload: {
|
||||
boardId,
|
||||
listId,
|
||||
index,
|
||||
},
|
||||
});
|
||||
|
||||
const duplicateCard = (id) => ({
|
||||
type: EntryActionTypes.CARD_DUPLICATE,
|
||||
payload: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
|
||||
const duplicateCurrentCard = () => ({
|
||||
type: EntryActionTypes.CURRENT_CARD_DUPLICATE,
|
||||
payload: {},
|
||||
});
|
||||
|
||||
const deleteCard = (id) => ({
|
||||
type: EntryActionTypes.CARD_DELETE,
|
||||
payload: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
|
||||
const deleteCurrentCard = () => ({
|
||||
type: EntryActionTypes.CURRENT_CARD_DELETE,
|
||||
payload: {},
|
||||
});
|
||||
|
||||
const handleCardDelete = (card) => ({
|
||||
type: EntryActionTypes.CARD_DELETE_HANDLE,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
export default {
|
||||
createCard,
|
||||
handleCardCreate,
|
||||
updateCard,
|
||||
updateCurrentCard,
|
||||
handleCardUpdate,
|
||||
moveCard,
|
||||
moveCurrentCard,
|
||||
transferCard,
|
||||
transferCurrentCard,
|
||||
duplicateCard,
|
||||
duplicateCurrentCard,
|
||||
deleteCard,
|
||||
deleteCurrentCard,
|
||||
handleCardDelete,
|
||||
};
|
||||
import EntryActionTypes from '../constants/EntryActionTypes';
|
||||
|
||||
const createCard = (listId, data, autoOpen) => ({
|
||||
type: EntryActionTypes.CARD_CREATE,
|
||||
payload: {
|
||||
listId,
|
||||
data,
|
||||
autoOpen,
|
||||
},
|
||||
});
|
||||
|
||||
const handleCardCreate = (card) => ({
|
||||
type: EntryActionTypes.CARD_CREATE_HANDLE,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
const updateCard = (id, data) => ({
|
||||
type: EntryActionTypes.CARD_UPDATE,
|
||||
payload: {
|
||||
id,
|
||||
data,
|
||||
},
|
||||
});
|
||||
|
||||
const updateCurrentCard = (data) => ({
|
||||
type: EntryActionTypes.CURRENT_CARD_UPDATE,
|
||||
payload: {
|
||||
data,
|
||||
},
|
||||
});
|
||||
|
||||
const handleCardUpdate = (card) => ({
|
||||
type: EntryActionTypes.CARD_UPDATE_HANDLE,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
const moveCard = (id, listId, index = 0) => ({
|
||||
type: EntryActionTypes.CARD_MOVE,
|
||||
payload: {
|
||||
id,
|
||||
listId,
|
||||
index,
|
||||
},
|
||||
});
|
||||
|
||||
const moveCurrentCard = (listId, index = 0) => ({
|
||||
type: EntryActionTypes.CURRENT_CARD_MOVE,
|
||||
payload: {
|
||||
listId,
|
||||
index,
|
||||
},
|
||||
});
|
||||
|
||||
const transferCard = (id, boardId, listId, index = 0) => ({
|
||||
type: EntryActionTypes.CARD_TRANSFER,
|
||||
payload: {
|
||||
id,
|
||||
boardId,
|
||||
listId,
|
||||
index,
|
||||
},
|
||||
});
|
||||
|
||||
const transferCurrentCard = (boardId, listId, index = 0) => ({
|
||||
type: EntryActionTypes.CURRENT_CARD_TRANSFER,
|
||||
payload: {
|
||||
boardId,
|
||||
listId,
|
||||
index,
|
||||
},
|
||||
});
|
||||
|
||||
const duplicateCard = (id) => ({
|
||||
type: EntryActionTypes.CARD_DUPLICATE,
|
||||
payload: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
|
||||
const duplicateCurrentCard = () => ({
|
||||
type: EntryActionTypes.CURRENT_CARD_DUPLICATE,
|
||||
payload: {},
|
||||
});
|
||||
|
||||
const deleteCard = (id) => ({
|
||||
type: EntryActionTypes.CARD_DELETE,
|
||||
payload: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
|
||||
const deleteCurrentCard = () => ({
|
||||
type: EntryActionTypes.CURRENT_CARD_DELETE,
|
||||
payload: {},
|
||||
});
|
||||
|
||||
const handleCardDelete = (card) => ({
|
||||
type: EntryActionTypes.CARD_DELETE_HANDLE,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
export default {
|
||||
createCard,
|
||||
handleCardCreate,
|
||||
updateCard,
|
||||
updateCurrentCard,
|
||||
handleCardUpdate,
|
||||
moveCard,
|
||||
moveCurrentCard,
|
||||
transferCard,
|
||||
transferCurrentCard,
|
||||
duplicateCard,
|
||||
duplicateCurrentCard,
|
||||
deleteCard,
|
||||
deleteCurrentCard,
|
||||
handleCardDelete,
|
||||
};
|
||||
|
||||
@ -1,239 +1,239 @@
|
||||
export default {
|
||||
format: {
|
||||
date: 'M/d/yyyy',
|
||||
time: 'p',
|
||||
dateTime: '$t(format:date) $t(format:time)',
|
||||
longDate: 'MMM d',
|
||||
longDateTime: "MMMM d 'at' p",
|
||||
fullDate: 'MMM d, y',
|
||||
fullDateTime: "MMMM d, y 'at' p",
|
||||
},
|
||||
|
||||
translation: {
|
||||
common: {
|
||||
aboutPlanka: 'About Planka',
|
||||
account: 'Account',
|
||||
actions: 'Actions',
|
||||
addAttachment_title: 'Add Attachment',
|
||||
addComment: 'Add comment',
|
||||
addManager_title: 'Add Manager',
|
||||
addMember_title: 'Add Member',
|
||||
addUser_title: 'Add User',
|
||||
administrator: 'Administrator',
|
||||
all: 'All',
|
||||
allChangesWillBeAutomaticallySavedAfterConnectionRestored:
|
||||
'All changes will be automatically saved<br />after connection restored.',
|
||||
areYouSureYouWantToDeleteThisAttachment: 'Are you sure you want to delete this attachment?',
|
||||
areYouSureYouWantToDeleteThisBoard: 'Are you sure you want to delete this board?',
|
||||
areYouSureYouWantToDeleteThisCard: 'Are you sure you want to delete this card?',
|
||||
areYouSureYouWantToDeleteThisComment: 'Are you sure you want to delete this comment?',
|
||||
areYouSureYouWantToDeleteThisLabel: 'Are you sure you want to delete this label?',
|
||||
areYouSureYouWantToDeleteThisList: 'Are you sure you want to delete this list?',
|
||||
areYouSureYouWantToDeleteThisProject: 'Are you sure you want to delete this project?',
|
||||
areYouSureYouWantToDeleteThisTask: 'Are you sure you want to delete this task?',
|
||||
areYouSureYouWantToDeleteThisUser: 'Are you sure you want to delete this user?',
|
||||
areYouSureYouWantToLeaveBoard: 'Are you sure you want to leave the board?',
|
||||
areYouSureYouWantToLeaveProject: 'Are you sure you want to leave the project?',
|
||||
areYouSureYouWantToRemoveThisManagerFromProject:
|
||||
'Are you sure you want to remove this manager from the project?',
|
||||
areYouSureYouWantToRemoveThisMemberFromBoard:
|
||||
'Are you sure you want to remove this member from the board?',
|
||||
attachment: 'Attachment',
|
||||
attachments: 'Attachments',
|
||||
authentication: 'Authentication',
|
||||
background: 'Background',
|
||||
board: 'Board',
|
||||
boardNotFound_title: 'Board Not Found',
|
||||
canComment: 'Can comment',
|
||||
canEditContentOfBoard: 'Can edit the content of the board.',
|
||||
canOnlyViewBoard: 'Can only view the board.',
|
||||
cardActions_title: 'Card Actions',
|
||||
cardNotFound_title: 'Card Not Found',
|
||||
cardOrActionAreDeleted: 'Card or action are deleted.',
|
||||
color: 'Color',
|
||||
copy_inline: 'copy',
|
||||
createBoard_title: 'Create Board',
|
||||
createLabel_title: 'Create Label',
|
||||
createNewOneOrSelectExistingOne: 'Create a new one or select<br />an existing one.',
|
||||
createProject_title: 'Create Project',
|
||||
createTextFile_title: 'Create Text File',
|
||||
currentPassword: 'Current password',
|
||||
dangerZone_title: 'Danger Zone',
|
||||
date: 'Date',
|
||||
dueDate_title: 'Due Date',
|
||||
deleteAttachment_title: 'Delete Attachment',
|
||||
deleteBoard_title: 'Delete Board',
|
||||
deleteCard_title: 'Delete Card',
|
||||
deleteComment_title: 'Delete Comment',
|
||||
deleteLabel_title: 'Delete Label',
|
||||
deleteList_title: 'Delete List',
|
||||
deleteProject_title: 'Delete Project',
|
||||
deleteTask_title: 'Delete Task',
|
||||
deleteUser_title: 'Delete User',
|
||||
description: 'Description',
|
||||
detectAutomatically: 'Detect automatically',
|
||||
dropFileToUpload: 'Drop file to upload',
|
||||
editor: 'Editor',
|
||||
editAttachment_title: 'Edit Attachment',
|
||||
editAvatar_title: 'Edit Avatar',
|
||||
editBoard_title: 'Edit Board',
|
||||
editDueDate_title: 'Edit Due Date',
|
||||
editEmail_title: 'Edit E-mail',
|
||||
editInformation_title: 'Edit Information',
|
||||
editLabel_title: 'Edit Label',
|
||||
editPassword_title: 'Edit Password',
|
||||
editPermissions_title: 'Edit Permissions',
|
||||
editStopwatch_title: 'Edit Stopwatch',
|
||||
editUsername_title: 'Edit Username',
|
||||
email: 'E-mail',
|
||||
emailAlreadyInUse: 'E-mail already in use',
|
||||
enterCardTitle: 'Enter card title... [Ctrl+Enter] to auto-open.',
|
||||
enterDescription: 'Enter description...',
|
||||
enterFilename: 'Enter filename',
|
||||
enterListTitle: 'Enter list title...',
|
||||
enterProjectTitle: 'Enter project title',
|
||||
enterTaskDescription: 'Enter task description...',
|
||||
filterByLabels_title: 'Filter By Labels',
|
||||
filterByMembers_title: 'Filter By Members',
|
||||
fromComputer_title: 'From Computer',
|
||||
fromTrello: 'From Trello',
|
||||
general: 'General',
|
||||
hours: 'Hours',
|
||||
importBoard_title: 'Import Board',
|
||||
invalidCurrentPassword: 'Invalid current password',
|
||||
labels: 'Labels',
|
||||
language: 'Language',
|
||||
leaveBoard_title: 'Leave Board',
|
||||
leaveProject_title: 'Leave Project',
|
||||
list: 'List',
|
||||
listActions_title: 'List Actions',
|
||||
managers: 'Managers',
|
||||
members: 'Members',
|
||||
minutes: 'Minutes',
|
||||
moveCard_title: 'Move Card',
|
||||
name: 'Name',
|
||||
newEmail: 'New e-mail',
|
||||
newPassword: 'New password',
|
||||
newUsername: 'New username',
|
||||
noConnectionToServer: 'No connection to server',
|
||||
noBoards: 'No boards',
|
||||
noLists: 'No lists',
|
||||
noProjects: 'No projects',
|
||||
notifications: 'Notifications',
|
||||
noUnreadNotifications: 'No unread notifications.',
|
||||
openBoard_title: 'Open Board',
|
||||
optional_inline: 'optional',
|
||||
organization: 'Organization',
|
||||
phone: 'Phone',
|
||||
preferences: 'Preferences',
|
||||
pressPasteShortcutToAddAttachmentFromClipboard:
|
||||
'Tip: press Ctrl-V (Cmd-V on Mac) to add an attachment from the clipboard.',
|
||||
project: 'Project',
|
||||
projectNotFound_title: 'Project Not Found',
|
||||
removeManager_title: 'Remove Manager',
|
||||
removeMember_title: 'Remove Member',
|
||||
searchLabels: 'Search labels...',
|
||||
searchMembers: 'Search members...',
|
||||
searchUsers: 'Search users...',
|
||||
seconds: 'Seconds',
|
||||
selectBoard: 'Select board',
|
||||
selectList: 'Select list',
|
||||
selectPermissions_title: 'Select Permissions',
|
||||
selectProject: 'Select project',
|
||||
settings: 'Settings',
|
||||
stopwatch: 'Stopwatch',
|
||||
subscribeToMyOwnCardsByDefault: 'Subscribe to my own cards by default',
|
||||
taskActions_title: 'Task Actions',
|
||||
tasks: 'Tasks',
|
||||
thereIsNoPreviewAvailableForThisAttachment:
|
||||
'There is no preview available for this attachment.',
|
||||
time: 'Time',
|
||||
title: 'Title',
|
||||
userActions_title: 'User Actions',
|
||||
userAddedThisCardToList: '<0>{{user}}</0><1> added this card to {{list}}</1>',
|
||||
userLeftNewCommentToCard: '{{user}} left a new comment «{{comment}}» to <2>{{card}}</2>',
|
||||
userMovedCardFromListToList: '{{user}} moved <2>{{card}}</2> from {{fromList}} to {{toList}}',
|
||||
userMovedThisCardFromListToList:
|
||||
'<0>{{user}}</0><1> moved this card from {{fromList}} to {{toList}}</1>',
|
||||
username: 'Username',
|
||||
usernameAlreadyInUse: 'Username already in use',
|
||||
users: 'Users',
|
||||
version: 'Version',
|
||||
viewer: 'Viewer',
|
||||
writeComment: 'Write a comment...',
|
||||
},
|
||||
|
||||
action: {
|
||||
addAnotherCard: 'Add another card',
|
||||
addAnotherList: 'Add another list',
|
||||
addAnotherTask: 'Add another task',
|
||||
addCard: 'Add card',
|
||||
addCard_title: 'Add Card',
|
||||
addComment: 'Add comment',
|
||||
addList: 'Add list',
|
||||
addMember: 'Add member',
|
||||
addMoreDetailedDescription: 'Add more detailed description',
|
||||
addTask: 'Add task',
|
||||
addToCard: 'Add to card',
|
||||
addUser: 'Add user',
|
||||
createBoard: 'Create board',
|
||||
createFile: 'Create file',
|
||||
createLabel: 'Create label',
|
||||
createNewLabel: 'Create new label',
|
||||
createProject: 'Create project',
|
||||
delete: 'Delete',
|
||||
deleteAttachment: 'Delete attachment',
|
||||
deleteAvatar: 'Delete avatar',
|
||||
deleteBoard: 'Delete board',
|
||||
deleteCard: 'Delete card',
|
||||
deleteCard_title: 'Delete Card',
|
||||
deleteComment: 'Delete comment',
|
||||
deleteImage: 'Delete image',
|
||||
deleteLabel: 'Delete label',
|
||||
deleteList: 'Delete list',
|
||||
deleteList_title: 'Delete List',
|
||||
deleteProject: 'Delete project',
|
||||
deleteProject_title: 'Delete Project',
|
||||
deleteTask: 'Delete task',
|
||||
deleteTask_title: 'Delete Task',
|
||||
deleteUser: 'Delete user',
|
||||
duplicate: 'Duplicate',
|
||||
duplicateCard_title: 'Duplicate Card',
|
||||
edit: 'Edit',
|
||||
editDueDate_title: 'Edit Due Date',
|
||||
editDescription_title: 'Edit Description',
|
||||
editEmail_title: 'Edit E-mail',
|
||||
editInformation_title: 'Edit Information',
|
||||
editPassword_title: 'Edit Password',
|
||||
editPermissions: 'Edit permissions',
|
||||
editStopwatch_title: 'Edit Stopwatch',
|
||||
editTitle_title: 'Edit Title',
|
||||
editUsername_title: 'Edit Username',
|
||||
hideDetails: 'Hide details',
|
||||
import: 'Import',
|
||||
leaveBoard: 'Leave board',
|
||||
leaveProject: 'Leave project',
|
||||
logOut_title: 'Log Out',
|
||||
makeCover_title: 'Make Cover',
|
||||
move: 'Move',
|
||||
moveCard_title: 'Move Card',
|
||||
remove: 'Remove',
|
||||
removeBackground: 'Remove background',
|
||||
removeCover_title: 'Remove Cover',
|
||||
removeFromBoard: 'Remove from board',
|
||||
removeFromProject: 'Remove from project',
|
||||
removeManager: 'Remove manager',
|
||||
removeMember: 'Remove member',
|
||||
save: 'Save',
|
||||
showAllAttachments: 'Show all attachments ({{hidden}} hidden)',
|
||||
showDetails: 'Show details',
|
||||
showFewerAttachments: 'Show fewer attachments',
|
||||
start: 'Start',
|
||||
stop: 'Stop',
|
||||
subscribe: 'Subscribe',
|
||||
unsubscribe: 'Unsubscribe',
|
||||
uploadNewAvatar: 'Upload new avatar',
|
||||
uploadNewImage: 'Upload new image',
|
||||
},
|
||||
},
|
||||
};
|
||||
export default {
|
||||
format: {
|
||||
date: 'M/d/yyyy',
|
||||
time: 'p',
|
||||
dateTime: '$t(format:date) $t(format:time)',
|
||||
longDate: 'MMM d',
|
||||
longDateTime: "MMMM d 'at' p",
|
||||
fullDate: 'MMM d, y',
|
||||
fullDateTime: "MMMM d, y 'at' p",
|
||||
},
|
||||
|
||||
translation: {
|
||||
common: {
|
||||
aboutPlanka: 'About Planka',
|
||||
account: 'Account',
|
||||
actions: 'Actions',
|
||||
addAttachment_title: 'Add Attachment',
|
||||
addComment: 'Add comment',
|
||||
addManager_title: 'Add Manager',
|
||||
addMember_title: 'Add Member',
|
||||
addUser_title: 'Add User',
|
||||
administrator: 'Administrator',
|
||||
all: 'All',
|
||||
allChangesWillBeAutomaticallySavedAfterConnectionRestored:
|
||||
'All changes will be automatically saved<br />after connection restored.',
|
||||
areYouSureYouWantToDeleteThisAttachment: 'Are you sure you want to delete this attachment?',
|
||||
areYouSureYouWantToDeleteThisBoard: 'Are you sure you want to delete this board?',
|
||||
areYouSureYouWantToDeleteThisCard: 'Are you sure you want to delete this card?',
|
||||
areYouSureYouWantToDeleteThisComment: 'Are you sure you want to delete this comment?',
|
||||
areYouSureYouWantToDeleteThisLabel: 'Are you sure you want to delete this label?',
|
||||
areYouSureYouWantToDeleteThisList: 'Are you sure you want to delete this list?',
|
||||
areYouSureYouWantToDeleteThisProject: 'Are you sure you want to delete this project?',
|
||||
areYouSureYouWantToDeleteThisTask: 'Are you sure you want to delete this task?',
|
||||
areYouSureYouWantToDeleteThisUser: 'Are you sure you want to delete this user?',
|
||||
areYouSureYouWantToLeaveBoard: 'Are you sure you want to leave the board?',
|
||||
areYouSureYouWantToLeaveProject: 'Are you sure you want to leave the project?',
|
||||
areYouSureYouWantToRemoveThisManagerFromProject:
|
||||
'Are you sure you want to remove this manager from the project?',
|
||||
areYouSureYouWantToRemoveThisMemberFromBoard:
|
||||
'Are you sure you want to remove this member from the board?',
|
||||
attachment: 'Attachment',
|
||||
attachments: 'Attachments',
|
||||
authentication: 'Authentication',
|
||||
background: 'Background',
|
||||
board: 'Board',
|
||||
boardNotFound_title: 'Board Not Found',
|
||||
canComment: 'Can comment',
|
||||
canEditContentOfBoard: 'Can edit the content of the board.',
|
||||
canOnlyViewBoard: 'Can only view the board.',
|
||||
cardActions_title: 'Card Actions',
|
||||
cardNotFound_title: 'Card Not Found',
|
||||
cardOrActionAreDeleted: 'Card or action are deleted.',
|
||||
color: 'Color',
|
||||
copy_inline: 'copy',
|
||||
createBoard_title: 'Create Board',
|
||||
createLabel_title: 'Create Label',
|
||||
createNewOneOrSelectExistingOne: 'Create a new one or select<br />an existing one.',
|
||||
createProject_title: 'Create Project',
|
||||
createTextFile_title: 'Create Text File',
|
||||
currentPassword: 'Current password',
|
||||
dangerZone_title: 'Danger Zone',
|
||||
date: 'Date',
|
||||
dueDate_title: 'Due Date',
|
||||
deleteAttachment_title: 'Delete Attachment',
|
||||
deleteBoard_title: 'Delete Board',
|
||||
deleteCard_title: 'Delete Card',
|
||||
deleteComment_title: 'Delete Comment',
|
||||
deleteLabel_title: 'Delete Label',
|
||||
deleteList_title: 'Delete List',
|
||||
deleteProject_title: 'Delete Project',
|
||||
deleteTask_title: 'Delete Task',
|
||||
deleteUser_title: 'Delete User',
|
||||
description: 'Description',
|
||||
detectAutomatically: 'Detect automatically',
|
||||
dropFileToUpload: 'Drop file to upload',
|
||||
editor: 'Editor',
|
||||
editAttachment_title: 'Edit Attachment',
|
||||
editAvatar_title: 'Edit Avatar',
|
||||
editBoard_title: 'Edit Board',
|
||||
editDueDate_title: 'Edit Due Date',
|
||||
editEmail_title: 'Edit E-mail',
|
||||
editInformation_title: 'Edit Information',
|
||||
editLabel_title: 'Edit Label',
|
||||
editPassword_title: 'Edit Password',
|
||||
editPermissions_title: 'Edit Permissions',
|
||||
editStopwatch_title: 'Edit Stopwatch',
|
||||
editUsername_title: 'Edit Username',
|
||||
email: 'E-mail',
|
||||
emailAlreadyInUse: 'E-mail already in use',
|
||||
enterCardTitle: 'Enter card title... [Ctrl+Enter] to auto-open.',
|
||||
enterDescription: 'Enter description...',
|
||||
enterFilename: 'Enter filename',
|
||||
enterListTitle: 'Enter list title...',
|
||||
enterProjectTitle: 'Enter project title',
|
||||
enterTaskDescription: 'Enter task description...',
|
||||
filterByLabels_title: 'Filter By Labels',
|
||||
filterByMembers_title: 'Filter By Members',
|
||||
fromComputer_title: 'From Computer',
|
||||
fromTrello: 'From Trello',
|
||||
general: 'General',
|
||||
hours: 'Hours',
|
||||
importBoard_title: 'Import Board',
|
||||
invalidCurrentPassword: 'Invalid current password',
|
||||
labels: 'Labels',
|
||||
language: 'Language',
|
||||
leaveBoard_title: 'Leave Board',
|
||||
leaveProject_title: 'Leave Project',
|
||||
list: 'List',
|
||||
listActions_title: 'List Actions',
|
||||
managers: 'Managers',
|
||||
members: 'Members',
|
||||
minutes: 'Minutes',
|
||||
moveCard_title: 'Move Card',
|
||||
name: 'Name',
|
||||
newEmail: 'New e-mail',
|
||||
newPassword: 'New password',
|
||||
newUsername: 'New username',
|
||||
noConnectionToServer: 'No connection to server',
|
||||
noBoards: 'No boards',
|
||||
noLists: 'No lists',
|
||||
noProjects: 'No projects',
|
||||
notifications: 'Notifications',
|
||||
noUnreadNotifications: 'No unread notifications.',
|
||||
openBoard_title: 'Open Board',
|
||||
optional_inline: 'optional',
|
||||
organization: 'Organization',
|
||||
phone: 'Phone',
|
||||
preferences: 'Preferences',
|
||||
pressPasteShortcutToAddAttachmentFromClipboard:
|
||||
'Tip: press Ctrl-V (Cmd-V on Mac) to add an attachment from the clipboard.',
|
||||
project: 'Project',
|
||||
projectNotFound_title: 'Project Not Found',
|
||||
removeManager_title: 'Remove Manager',
|
||||
removeMember_title: 'Remove Member',
|
||||
searchLabels: 'Search labels...',
|
||||
searchMembers: 'Search members...',
|
||||
searchUsers: 'Search users...',
|
||||
seconds: 'Seconds',
|
||||
selectBoard: 'Select board',
|
||||
selectList: 'Select list',
|
||||
selectPermissions_title: 'Select Permissions',
|
||||
selectProject: 'Select project',
|
||||
settings: 'Settings',
|
||||
stopwatch: 'Stopwatch',
|
||||
subscribeToMyOwnCardsByDefault: 'Subscribe to my own cards by default',
|
||||
taskActions_title: 'Task Actions',
|
||||
tasks: 'Tasks',
|
||||
thereIsNoPreviewAvailableForThisAttachment:
|
||||
'There is no preview available for this attachment.',
|
||||
time: 'Time',
|
||||
title: 'Title',
|
||||
userActions_title: 'User Actions',
|
||||
userAddedThisCardToList: '<0>{{user}}</0><1> added this card to {{list}}</1>',
|
||||
userLeftNewCommentToCard: '{{user}} left a new comment «{{comment}}» to <2>{{card}}</2>',
|
||||
userMovedCardFromListToList: '{{user}} moved <2>{{card}}</2> from {{fromList}} to {{toList}}',
|
||||
userMovedThisCardFromListToList:
|
||||
'<0>{{user}}</0><1> moved this card from {{fromList}} to {{toList}}</1>',
|
||||
username: 'Username',
|
||||
usernameAlreadyInUse: 'Username already in use',
|
||||
users: 'Users',
|
||||
version: 'Version',
|
||||
viewer: 'Viewer',
|
||||
writeComment: 'Write a comment...',
|
||||
},
|
||||
|
||||
action: {
|
||||
addAnotherCard: 'Add another card',
|
||||
addAnotherList: 'Add another list',
|
||||
addAnotherTask: 'Add another task',
|
||||
addCard: 'Add card',
|
||||
addCard_title: 'Add Card',
|
||||
addComment: 'Add comment',
|
||||
addList: 'Add list',
|
||||
addMember: 'Add member',
|
||||
addMoreDetailedDescription: 'Add more detailed description',
|
||||
addTask: 'Add task',
|
||||
addToCard: 'Add to card',
|
||||
addUser: 'Add user',
|
||||
createBoard: 'Create board',
|
||||
createFile: 'Create file',
|
||||
createLabel: 'Create label',
|
||||
createNewLabel: 'Create new label',
|
||||
createProject: 'Create project',
|
||||
delete: 'Delete',
|
||||
deleteAttachment: 'Delete attachment',
|
||||
deleteAvatar: 'Delete avatar',
|
||||
deleteBoard: 'Delete board',
|
||||
deleteCard: 'Delete card',
|
||||
deleteCard_title: 'Delete Card',
|
||||
deleteComment: 'Delete comment',
|
||||
deleteImage: 'Delete image',
|
||||
deleteLabel: 'Delete label',
|
||||
deleteList: 'Delete list',
|
||||
deleteList_title: 'Delete List',
|
||||
deleteProject: 'Delete project',
|
||||
deleteProject_title: 'Delete Project',
|
||||
deleteTask: 'Delete task',
|
||||
deleteTask_title: 'Delete Task',
|
||||
deleteUser: 'Delete user',
|
||||
duplicate: 'Duplicate',
|
||||
duplicateCard_title: 'Duplicate Card',
|
||||
edit: 'Edit',
|
||||
editDueDate_title: 'Edit Due Date',
|
||||
editDescription_title: 'Edit Description',
|
||||
editEmail_title: 'Edit E-mail',
|
||||
editInformation_title: 'Edit Information',
|
||||
editPassword_title: 'Edit Password',
|
||||
editPermissions: 'Edit permissions',
|
||||
editStopwatch_title: 'Edit Stopwatch',
|
||||
editTitle_title: 'Edit Title',
|
||||
editUsername_title: 'Edit Username',
|
||||
hideDetails: 'Hide details',
|
||||
import: 'Import',
|
||||
leaveBoard: 'Leave board',
|
||||
leaveProject: 'Leave project',
|
||||
logOut_title: 'Log Out',
|
||||
makeCover_title: 'Make Cover',
|
||||
move: 'Move',
|
||||
moveCard_title: 'Move Card',
|
||||
remove: 'Remove',
|
||||
removeBackground: 'Remove background',
|
||||
removeCover_title: 'Remove Cover',
|
||||
removeFromBoard: 'Remove from board',
|
||||
removeFromProject: 'Remove from project',
|
||||
removeManager: 'Remove manager',
|
||||
removeMember: 'Remove member',
|
||||
save: 'Save',
|
||||
showAllAttachments: 'Show all attachments ({{hidden}} hidden)',
|
||||
showDetails: 'Show details',
|
||||
showFewerAttachments: 'Show fewer attachments',
|
||||
start: 'Start',
|
||||
stop: 'Stop',
|
||||
subscribe: 'Subscribe',
|
||||
unsubscribe: 'Unsubscribe',
|
||||
uploadNewAvatar: 'Upload new avatar',
|
||||
uploadNewImage: 'Upload new image',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,201 +1,201 @@
|
||||
import dateFns from 'date-fns/locale/fr';
|
||||
|
||||
export default {
|
||||
dateFns,
|
||||
|
||||
format: {
|
||||
date: 'P',
|
||||
time: 'HH:mm',
|
||||
dateTime: '$t(format:date) $t(format:time)',
|
||||
longDate: 'd MMM',
|
||||
longDateTime: "d MMMM 'à' p",
|
||||
fullDate: 'd MMM y',
|
||||
fullDateTime: "d MMMM y 'à' p",
|
||||
},
|
||||
|
||||
translation: {
|
||||
common: {
|
||||
account: 'Compte',
|
||||
actions: 'Actions',
|
||||
addAttachment_title: 'Ajouter une pièce jointe',
|
||||
addComment: 'Ajouter un commentaire',
|
||||
addMember_title: 'Ajouter un membre',
|
||||
addUser_title: 'Ajouter un utilisateur',
|
||||
administrator: 'Administrateur',
|
||||
all: 'Tout',
|
||||
allChangesWillBeAutomaticallySavedAfterConnectionRestored:
|
||||
'Toutes les modifications seront automatiquement enregistrées<br />une fois la connexion rétablie.',
|
||||
areYouSureYouWantToDeleteThisAttachment: 'Voulez-vous vraiment supprimer cette pièce jointe?',
|
||||
areYouSureYouWantToDeleteThisBoard: 'Êtes-vous sûr de vouloir supprimer ce forum?',
|
||||
areYouSureYouWantToDeleteThisCard: 'Voulez-vous vraiment supprimer cette carte?',
|
||||
areYouSureYouWantToDeleteThisComment: 'Êtes-vous sûr de vouloir supprimer ce commentaire?',
|
||||
areYouSureYouWantToDeleteThisLabel: 'Voulez-vous vraiment supprimer ce libellé?',
|
||||
areYouSureYouWantToDeleteThisList: 'Êtes-vous sûr de vouloir supprimer cette liste?',
|
||||
areYouSureYouWantToDeleteThisProject: 'Êtes-vous sûr de vouloir supprimer ce projet?',
|
||||
areYouSureYouWantToDeleteThisTask: 'Êtes-vous sûr de vouloir supprimer cette tâche?',
|
||||
areYouSureYouWantToDeleteThisUser: 'Êtes-vous sûr de vouloir supprimer cet utilisateur?',
|
||||
areYouSureYouWantToRemoveThisMemberFromProject:
|
||||
'Êtes-vous sûr de vouloir supprimer ce membre du projet?',
|
||||
attachment: 'Attachement',
|
||||
attachments: 'Pièces jointes',
|
||||
authentication: 'Authentification',
|
||||
board: 'Tableau',
|
||||
boardNotFound_title: 'Carte non trouvée',
|
||||
cardActions_title: 'Actions sur la carte',
|
||||
cardNotFound_title: 'Carte non trouvée',
|
||||
cardOrActionAreDeleted: "La carte ou l'action sont supprimées.",
|
||||
color: 'Couleur',
|
||||
createBoard_title: 'Créer un tableau',
|
||||
createLabel_title: 'Créer une étiquette',
|
||||
createNewOneOrSelectExistingOne: 'Créez-en un nouveau ou sélectionnez<br />un existant.',
|
||||
createProject_title: 'Créer un projet',
|
||||
createTextFile_title: 'Créer un fichier texte',
|
||||
currentPassword: 'Mot de passe actuel',
|
||||
date: 'Date',
|
||||
dueDate_title: "Date d'échéance",
|
||||
deleteAttachment_title: 'Supprimer la pièce jointe',
|
||||
deleteBoard_title: 'Supprimer le tableau',
|
||||
deleteCard_title: 'Supprimer la carte',
|
||||
deleteComment_title: 'Supprimer le commentaire',
|
||||
deleteLabel_title: "Supprimer l'étiquette",
|
||||
deleteList_title: 'Supprimer la liste',
|
||||
deleteProject_title: 'Supprimer le projet',
|
||||
deleteTask_title: 'Supprimer la tâche',
|
||||
deleteUser_title: "Supprimer l'utilisateur",
|
||||
description: 'Description',
|
||||
dropFileToUpload: 'Déposer le fichier à télécharger',
|
||||
editAttachment_title: 'Modifier la pièce jointe',
|
||||
editAvatar_title: 'Modifier Avatar',
|
||||
editBoard_title: 'Modifier le tableau',
|
||||
editDueDate_title: "Modifier la date d'échéance",
|
||||
editEmail_title: "Modifier l'e-mail",
|
||||
editLabel_title: "Modifier l'étiquette",
|
||||
editPassword_title: 'Modifier le mot de passe',
|
||||
editStopwatch_title: 'Modifier la minuterie',
|
||||
editUsername_title: "Modifier le nom d'utilisateur",
|
||||
email: 'E-mail',
|
||||
emailAlreadyInUse: 'Email déjà utilisé',
|
||||
enterCardTitle: 'Entrer le titre de la carte...',
|
||||
enterDescription: 'Entrez la description...',
|
||||
enterFilename: 'Entrez le nom du fichier',
|
||||
enterListTitle: 'Entrer le titre de la liste...',
|
||||
enterProjectTitle: 'Saisir le titre du projet',
|
||||
enterTaskDescription: 'Saisir la description de la tâche...',
|
||||
filterByLabels_title: 'Filtrer par libellés',
|
||||
filterByMembers_title: 'Filtrer par membres',
|
||||
fromComputer_title: "Depuis l'ordinateur",
|
||||
hours: 'Les heures',
|
||||
invalidCurrentPassword: 'Mot de passe actuel invalide',
|
||||
labels: 'Étiquettes',
|
||||
list: 'Lister',
|
||||
listActions_title: 'Liste des actions',
|
||||
members: 'Membres',
|
||||
minutes: 'Minutes',
|
||||
moveCard_title: 'Déplacer la carte',
|
||||
name: 'Nom',
|
||||
newEmail: 'Nouveau courriel',
|
||||
newPassword: 'Nouveau mot de passe',
|
||||
newUsername: "Nouveau nom d'utilisateur",
|
||||
noConnectionToServer: 'Pas de connexion au serveur',
|
||||
noBoards: 'Pas de planches',
|
||||
noLists: 'Pas de listes',
|
||||
noProjects: 'Pas de projets',
|
||||
notifications: 'Notifications',
|
||||
noUnreadNotifications: 'Aucune notification non lue.',
|
||||
openBoard_title: 'Open Board',
|
||||
optional_inline: 'optionnel',
|
||||
organization: 'Organisation',
|
||||
phone: 'Téléphone',
|
||||
preferences: 'Préférences',
|
||||
pressPasteShortcutToAddAttachmentFromClipboard: 'Conseil',
|
||||
project: 'Projet',
|
||||
projectNotFound_title: 'Projet introuvable',
|
||||
removeMember_title: 'Supprimer le membre',
|
||||
seconds: 'Secondes',
|
||||
selectBoard: 'Sélectionner une carte',
|
||||
selectList: 'Sélectionner une liste',
|
||||
selectProject: 'Sélectionner un projet',
|
||||
settings: 'Réglages',
|
||||
stopwatch: 'Minuteur',
|
||||
subscribeToMyOwnCardsByDefault: 'Abonnez-vous à mes propres cartes par défaut',
|
||||
taskActions_title: 'Actions de tâche',
|
||||
tasks: 'Tâches',
|
||||
time: 'Temps',
|
||||
title: 'Titre',
|
||||
userActions_title: "Actions de l'utilisateur",
|
||||
userAddedThisCardToList: '<0> {{user}} </0> <1> a ajouté cette carte à {{list}} </1>',
|
||||
userLeftNewCommentToCard:
|
||||
'{{user}} a laissé un nouveau commentaire {{comment}} à <2> {{card}} </2>',
|
||||
userMovedCardFromListToList:
|
||||
'{{user}} a déplacé <2> {{card}} </2> de {{fromList}} vers {{toList}}',
|
||||
userMovedThisCardFromListToList:
|
||||
'<0> {{user}} </0> <1> a déplacé cette carte de {{fromList}} vers {{toList}} </1>',
|
||||
username: "Nom d'utilisateur",
|
||||
usernameAlreadyInUse: "Nom d'utilisateur déjà utilisé",
|
||||
users: 'Utilisateurs',
|
||||
writeComment: 'Écrire un commentaire...',
|
||||
},
|
||||
|
||||
action: {
|
||||
addAnotherCard: 'Ajouter une autre carte',
|
||||
addAnotherList: 'Ajouter une autre liste',
|
||||
addAnotherTask: 'Ajouter une autre tâche',
|
||||
addCard: 'Ajouter une carte',
|
||||
addCard_title: 'Ajouter une carte',
|
||||
addComment: 'Ajouter un commentaire',
|
||||
addList: 'Ajouter la liste',
|
||||
addMoreDetailedDescription: 'Ajouter une description plus détaillée',
|
||||
addTask: 'Ajouter une tâche',
|
||||
addToCard: 'Ajouter à la carte',
|
||||
addUser: 'Ajouter un utilisateur',
|
||||
createBoard: 'Créer un tableau',
|
||||
createFile: 'Créer un fichier',
|
||||
createLabel: 'Créer une étiquette',
|
||||
createNewLabel: 'Créer une nouvelle étiquette',
|
||||
createProject: 'Créer un projet',
|
||||
delete: 'Supprimer',
|
||||
deleteAttachment: 'Supprimer la pièce jointe',
|
||||
deleteAvatar: "Supprimer l'avatar",
|
||||
deleteBoard: 'Supprimer le tableau',
|
||||
deleteCard: 'Supprimer la carte',
|
||||
deleteCard_title: 'Supprimer la carte',
|
||||
deleteComment: 'Supprimer le commentaire',
|
||||
deleteImage: "Supprimer l'image",
|
||||
deleteLabel: "Supprimer l'étiquette",
|
||||
deleteList: 'Supprimer la liste',
|
||||
deleteList_title: 'Supprimer la liste',
|
||||
deleteProject: 'Supprimer le projet',
|
||||
deleteProject_title: 'Supprimer le projet',
|
||||
deleteTask: 'Supprimer la tâche',
|
||||
deleteTask_title: 'Supprimer la tâche',
|
||||
deleteUser: "Supprimer l'utilisateur",
|
||||
duplicate: 'Dupliquer',
|
||||
edit: 'Modifier',
|
||||
editDueDate_title: "Modifier la date d'échéance",
|
||||
editDescription_title: 'Éditer la description',
|
||||
editEmail_title: "Modifier l'e-mail",
|
||||
editPassword_title: 'Modifier le mot de passe',
|
||||
editStopwatch_title: 'Modifier la minuterie',
|
||||
editTitle_title: 'Modifier le titre',
|
||||
editUsername_title: "Modifier le nom d'utilisateur",
|
||||
logOut_title: 'Se déconnecter',
|
||||
makeCover_title: 'Faire la jaquette',
|
||||
move: 'Déplacer',
|
||||
moveCard_title: 'Déplacer la carte',
|
||||
remove: 'Supprimer',
|
||||
removeBackground: "Supprimer l'arrière-plan",
|
||||
removeCover_title: 'Supprimer la jaquette',
|
||||
removeFromProject: 'Supprimer du projet',
|
||||
removeMember: 'Supprimer le membre',
|
||||
save: 'Sauvegarder',
|
||||
showAllAttachments: 'Afficher toutes les pièces jointes ({{hidden}} masquées)',
|
||||
showFewerAttachments: 'Afficher moins de pièces jointes',
|
||||
start: 'Début',
|
||||
stop: 'Arrêter',
|
||||
subscribe: "S'abonner",
|
||||
unsubscribe: 'Se désabonner',
|
||||
uploadNewAvatar: 'Télécharger un nouvel avatar',
|
||||
uploadNewImage: 'Télécharger une nouvelle image',
|
||||
},
|
||||
},
|
||||
};
|
||||
import dateFns from 'date-fns/locale/fr';
|
||||
|
||||
export default {
|
||||
dateFns,
|
||||
|
||||
format: {
|
||||
date: 'P',
|
||||
time: 'HH:mm',
|
||||
dateTime: '$t(format:date) $t(format:time)',
|
||||
longDate: 'd MMM',
|
||||
longDateTime: "d MMMM 'à' p",
|
||||
fullDate: 'd MMM y',
|
||||
fullDateTime: "d MMMM y 'à' p",
|
||||
},
|
||||
|
||||
translation: {
|
||||
common: {
|
||||
account: 'Compte',
|
||||
actions: 'Actions',
|
||||
addAttachment_title: 'Ajouter une pièce jointe',
|
||||
addComment: 'Ajouter un commentaire',
|
||||
addMember_title: 'Ajouter un membre',
|
||||
addUser_title: 'Ajouter un utilisateur',
|
||||
administrator: 'Administrateur',
|
||||
all: 'Tout',
|
||||
allChangesWillBeAutomaticallySavedAfterConnectionRestored:
|
||||
'Toutes les modifications seront automatiquement enregistrées<br />une fois la connexion rétablie.',
|
||||
areYouSureYouWantToDeleteThisAttachment: 'Voulez-vous vraiment supprimer cette pièce jointe?',
|
||||
areYouSureYouWantToDeleteThisBoard: 'Êtes-vous sûr de vouloir supprimer ce forum?',
|
||||
areYouSureYouWantToDeleteThisCard: 'Voulez-vous vraiment supprimer cette carte?',
|
||||
areYouSureYouWantToDeleteThisComment: 'Êtes-vous sûr de vouloir supprimer ce commentaire?',
|
||||
areYouSureYouWantToDeleteThisLabel: 'Voulez-vous vraiment supprimer ce libellé?',
|
||||
areYouSureYouWantToDeleteThisList: 'Êtes-vous sûr de vouloir supprimer cette liste?',
|
||||
areYouSureYouWantToDeleteThisProject: 'Êtes-vous sûr de vouloir supprimer ce projet?',
|
||||
areYouSureYouWantToDeleteThisTask: 'Êtes-vous sûr de vouloir supprimer cette tâche?',
|
||||
areYouSureYouWantToDeleteThisUser: 'Êtes-vous sûr de vouloir supprimer cet utilisateur?',
|
||||
areYouSureYouWantToRemoveThisMemberFromProject:
|
||||
'Êtes-vous sûr de vouloir supprimer ce membre du projet?',
|
||||
attachment: 'Attachement',
|
||||
attachments: 'Pièces jointes',
|
||||
authentication: 'Authentification',
|
||||
board: 'Tableau',
|
||||
boardNotFound_title: 'Carte non trouvée',
|
||||
cardActions_title: 'Actions sur la carte',
|
||||
cardNotFound_title: 'Carte non trouvée',
|
||||
cardOrActionAreDeleted: "La carte ou l'action sont supprimées.",
|
||||
color: 'Couleur',
|
||||
createBoard_title: 'Créer un tableau',
|
||||
createLabel_title: 'Créer une étiquette',
|
||||
createNewOneOrSelectExistingOne: 'Créez-en un nouveau ou sélectionnez<br />un existant.',
|
||||
createProject_title: 'Créer un projet',
|
||||
createTextFile_title: 'Créer un fichier texte',
|
||||
currentPassword: 'Mot de passe actuel',
|
||||
date: 'Date',
|
||||
dueDate_title: "Date d'échéance",
|
||||
deleteAttachment_title: 'Supprimer la pièce jointe',
|
||||
deleteBoard_title: 'Supprimer le tableau',
|
||||
deleteCard_title: 'Supprimer la carte',
|
||||
deleteComment_title: 'Supprimer le commentaire',
|
||||
deleteLabel_title: "Supprimer l'étiquette",
|
||||
deleteList_title: 'Supprimer la liste',
|
||||
deleteProject_title: 'Supprimer le projet',
|
||||
deleteTask_title: 'Supprimer la tâche',
|
||||
deleteUser_title: "Supprimer l'utilisateur",
|
||||
description: 'Description',
|
||||
dropFileToUpload: 'Déposer le fichier à télécharger',
|
||||
editAttachment_title: 'Modifier la pièce jointe',
|
||||
editAvatar_title: 'Modifier Avatar',
|
||||
editBoard_title: 'Modifier le tableau',
|
||||
editDueDate_title: "Modifier la date d'échéance",
|
||||
editEmail_title: "Modifier l'e-mail",
|
||||
editLabel_title: "Modifier l'étiquette",
|
||||
editPassword_title: 'Modifier le mot de passe',
|
||||
editStopwatch_title: 'Modifier la minuterie',
|
||||
editUsername_title: "Modifier le nom d'utilisateur",
|
||||
email: 'E-mail',
|
||||
emailAlreadyInUse: 'Email déjà utilisé',
|
||||
enterCardTitle: 'Entrer le titre de la carte...',
|
||||
enterDescription: 'Entrez la description...',
|
||||
enterFilename: 'Entrez le nom du fichier',
|
||||
enterListTitle: 'Entrer le titre de la liste...',
|
||||
enterProjectTitle: 'Saisir le titre du projet',
|
||||
enterTaskDescription: 'Saisir la description de la tâche...',
|
||||
filterByLabels_title: 'Filtrer par libellés',
|
||||
filterByMembers_title: 'Filtrer par membres',
|
||||
fromComputer_title: "Depuis l'ordinateur",
|
||||
hours: 'Les heures',
|
||||
invalidCurrentPassword: 'Mot de passe actuel invalide',
|
||||
labels: 'Étiquettes',
|
||||
list: 'Lister',
|
||||
listActions_title: 'Liste des actions',
|
||||
members: 'Membres',
|
||||
minutes: 'Minutes',
|
||||
moveCard_title: 'Déplacer la carte',
|
||||
name: 'Nom',
|
||||
newEmail: 'Nouveau courriel',
|
||||
newPassword: 'Nouveau mot de passe',
|
||||
newUsername: "Nouveau nom d'utilisateur",
|
||||
noConnectionToServer: 'Pas de connexion au serveur',
|
||||
noBoards: 'Pas de planches',
|
||||
noLists: 'Pas de listes',
|
||||
noProjects: 'Pas de projets',
|
||||
notifications: 'Notifications',
|
||||
noUnreadNotifications: 'Aucune notification non lue.',
|
||||
openBoard_title: 'Open Board',
|
||||
optional_inline: 'optionnel',
|
||||
organization: 'Organisation',
|
||||
phone: 'Téléphone',
|
||||
preferences: 'Préférences',
|
||||
pressPasteShortcutToAddAttachmentFromClipboard: 'Conseil',
|
||||
project: 'Projet',
|
||||
projectNotFound_title: 'Projet introuvable',
|
||||
removeMember_title: 'Supprimer le membre',
|
||||
seconds: 'Secondes',
|
||||
selectBoard: 'Sélectionner une carte',
|
||||
selectList: 'Sélectionner une liste',
|
||||
selectProject: 'Sélectionner un projet',
|
||||
settings: 'Réglages',
|
||||
stopwatch: 'Minuteur',
|
||||
subscribeToMyOwnCardsByDefault: 'Abonnez-vous à mes propres cartes par défaut',
|
||||
taskActions_title: 'Actions de tâche',
|
||||
tasks: 'Tâches',
|
||||
time: 'Temps',
|
||||
title: 'Titre',
|
||||
userActions_title: "Actions de l'utilisateur",
|
||||
userAddedThisCardToList: '<0> {{user}} </0> <1> a ajouté cette carte à {{list}} </1>',
|
||||
userLeftNewCommentToCard:
|
||||
'{{user}} a laissé un nouveau commentaire {{comment}} à <2> {{card}} </2>',
|
||||
userMovedCardFromListToList:
|
||||
'{{user}} a déplacé <2> {{card}} </2> de {{fromList}} vers {{toList}}',
|
||||
userMovedThisCardFromListToList:
|
||||
'<0> {{user}} </0> <1> a déplacé cette carte de {{fromList}} vers {{toList}} </1>',
|
||||
username: "Nom d'utilisateur",
|
||||
usernameAlreadyInUse: "Nom d'utilisateur déjà utilisé",
|
||||
users: 'Utilisateurs',
|
||||
writeComment: 'Écrire un commentaire...',
|
||||
},
|
||||
|
||||
action: {
|
||||
addAnotherCard: 'Ajouter une autre carte',
|
||||
addAnotherList: 'Ajouter une autre liste',
|
||||
addAnotherTask: 'Ajouter une autre tâche',
|
||||
addCard: 'Ajouter une carte',
|
||||
addCard_title: 'Ajouter une carte',
|
||||
addComment: 'Ajouter un commentaire',
|
||||
addList: 'Ajouter la liste',
|
||||
addMoreDetailedDescription: 'Ajouter une description plus détaillée',
|
||||
addTask: 'Ajouter une tâche',
|
||||
addToCard: 'Ajouter à la carte',
|
||||
addUser: 'Ajouter un utilisateur',
|
||||
createBoard: 'Créer un tableau',
|
||||
createFile: 'Créer un fichier',
|
||||
createLabel: 'Créer une étiquette',
|
||||
createNewLabel: 'Créer une nouvelle étiquette',
|
||||
createProject: 'Créer un projet',
|
||||
delete: 'Supprimer',
|
||||
deleteAttachment: 'Supprimer la pièce jointe',
|
||||
deleteAvatar: "Supprimer l'avatar",
|
||||
deleteBoard: 'Supprimer le tableau',
|
||||
deleteCard: 'Supprimer la carte',
|
||||
deleteCard_title: 'Supprimer la carte',
|
||||
deleteComment: 'Supprimer le commentaire',
|
||||
deleteImage: "Supprimer l'image",
|
||||
deleteLabel: "Supprimer l'étiquette",
|
||||
deleteList: 'Supprimer la liste',
|
||||
deleteList_title: 'Supprimer la liste',
|
||||
deleteProject: 'Supprimer le projet',
|
||||
deleteProject_title: 'Supprimer le projet',
|
||||
deleteTask: 'Supprimer la tâche',
|
||||
deleteTask_title: 'Supprimer la tâche',
|
||||
deleteUser: "Supprimer l'utilisateur",
|
||||
duplicate: 'Dupliquer',
|
||||
edit: 'Modifier',
|
||||
editDueDate_title: "Modifier la date d'échéance",
|
||||
editDescription_title: 'Éditer la description',
|
||||
editEmail_title: "Modifier l'e-mail",
|
||||
editPassword_title: 'Modifier le mot de passe',
|
||||
editStopwatch_title: 'Modifier la minuterie',
|
||||
editTitle_title: 'Modifier le titre',
|
||||
editUsername_title: "Modifier le nom d'utilisateur",
|
||||
logOut_title: 'Se déconnecter',
|
||||
makeCover_title: 'Faire la jaquette',
|
||||
move: 'Déplacer',
|
||||
moveCard_title: 'Déplacer la carte',
|
||||
remove: 'Supprimer',
|
||||
removeBackground: "Supprimer l'arrière-plan",
|
||||
removeCover_title: 'Supprimer la jaquette',
|
||||
removeFromProject: 'Supprimer du projet',
|
||||
removeMember: 'Supprimer le membre',
|
||||
save: 'Sauvegarder',
|
||||
showAllAttachments: 'Afficher toutes les pièces jointes ({{hidden}} masquées)',
|
||||
showFewerAttachments: 'Afficher moins de pièces jointes',
|
||||
start: 'Début',
|
||||
stop: 'Arrêter',
|
||||
subscribe: "S'abonner",
|
||||
unsubscribe: 'Se désabonner',
|
||||
uploadNewAvatar: 'Télécharger un nouvel avatar',
|
||||
uploadNewImage: 'Télécharger une nouvelle image',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,358 +1,358 @@
|
||||
import pick from 'lodash/pick';
|
||||
import { attr, fk, many, oneToOne } from 'redux-orm';
|
||||
|
||||
import BaseModel from './BaseModel';
|
||||
import ActionTypes from '../constants/ActionTypes';
|
||||
import Config from '../constants/Config';
|
||||
import { ActivityTypes } from '../constants/Enums';
|
||||
|
||||
export default class extends BaseModel {
|
||||
static modelName = 'Card';
|
||||
|
||||
static fields = {
|
||||
id: attr(),
|
||||
position: attr(),
|
||||
name: attr(),
|
||||
description: attr(),
|
||||
dueDate: attr(),
|
||||
stopwatch: attr(),
|
||||
isSubscribed: attr({
|
||||
getDefault: () => false,
|
||||
}),
|
||||
isActivitiesFetching: attr({
|
||||
getDefault: () => false,
|
||||
}),
|
||||
isAllActivitiesFetched: attr({
|
||||
getDefault: () => false,
|
||||
}),
|
||||
isActivitiesDetailsVisible: attr({
|
||||
getDefault: () => false,
|
||||
}),
|
||||
isActivitiesDetailsFetching: attr({
|
||||
getDefault: () => false,
|
||||
}),
|
||||
boardId: fk({
|
||||
to: 'Board',
|
||||
as: 'board',
|
||||
relatedName: 'cards',
|
||||
}),
|
||||
listId: fk({
|
||||
to: 'List',
|
||||
as: 'list',
|
||||
relatedName: 'cards',
|
||||
}),
|
||||
coverAttachmentId: oneToOne({
|
||||
to: 'Attachment',
|
||||
as: 'coverAttachment',
|
||||
relatedName: 'coveredCard',
|
||||
}),
|
||||
users: many('User', 'cards'),
|
||||
labels: many('Label', 'cards'),
|
||||
};
|
||||
|
||||
static reducer({ type, payload }, Card) {
|
||||
switch (type) {
|
||||
case ActionTypes.LOCATION_CHANGE_HANDLE:
|
||||
case ActionTypes.CORE_INITIALIZE:
|
||||
case ActionTypes.PROJECT_MANAGER_CREATE_HANDLE:
|
||||
case ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE:
|
||||
if (payload.cards) {
|
||||
payload.cards.forEach((card) => {
|
||||
Card.upsert(card);
|
||||
});
|
||||
}
|
||||
|
||||
if (payload.cardMemberships) {
|
||||
payload.cardMemberships.forEach(({ cardId, userId }) => {
|
||||
Card.withId(cardId).users.add(userId);
|
||||
});
|
||||
}
|
||||
|
||||
if (payload.cardLabels) {
|
||||
payload.cardLabels.forEach(({ cardId, labelId }) => {
|
||||
Card.withId(cardId).labels.add(labelId);
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
case ActionTypes.SOCKET_RECONNECT_HANDLE:
|
||||
Card.all()
|
||||
.toModelArray()
|
||||
.forEach((cardModel) => {
|
||||
cardModel.deleteWithClearable();
|
||||
});
|
||||
|
||||
if (payload.cards) {
|
||||
payload.cards.forEach((card) => {
|
||||
Card.upsert(card);
|
||||
});
|
||||
}
|
||||
|
||||
if (payload.cardMemberships) {
|
||||
payload.cardMemberships.forEach(({ cardId, userId }) => {
|
||||
Card.withId(cardId).users.add(userId);
|
||||
});
|
||||
}
|
||||
|
||||
if (payload.cardLabels) {
|
||||
payload.cardLabels.forEach(({ cardId, labelId }) => {
|
||||
Card.withId(cardId).labels.add(labelId);
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
case ActionTypes.USER_TO_CARD_ADD: {
|
||||
const cardModel = Card.withId(payload.cardId);
|
||||
cardModel.users.add(payload.id);
|
||||
|
||||
if (payload.isCurrent) {
|
||||
cardModel.isSubscribed = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.USER_TO_CARD_ADD__SUCCESS:
|
||||
case ActionTypes.USER_TO_CARD_ADD_HANDLE:
|
||||
try {
|
||||
Card.withId(payload.cardMembership.cardId).users.add(payload.cardMembership.userId);
|
||||
} catch {} // eslint-disable-line no-empty
|
||||
|
||||
break;
|
||||
case ActionTypes.USER_FROM_CARD_REMOVE:
|
||||
Card.withId(payload.cardId).users.remove(payload.id);
|
||||
|
||||
break;
|
||||
case ActionTypes.USER_FROM_CARD_REMOVE__SUCCESS:
|
||||
case ActionTypes.USER_FROM_CARD_REMOVE_HANDLE:
|
||||
try {
|
||||
Card.withId(payload.cardMembership.cardId).users.remove(payload.cardMembership.userId);
|
||||
} catch {} // eslint-disable-line no-empty
|
||||
|
||||
break;
|
||||
case ActionTypes.BOARD_FETCH__SUCCESS:
|
||||
payload.cards.forEach((card) => {
|
||||
Card.upsert(card);
|
||||
});
|
||||
|
||||
payload.cardMemberships.forEach(({ cardId, userId }) => {
|
||||
Card.withId(cardId).users.add(userId);
|
||||
});
|
||||
|
||||
payload.cardLabels.forEach(({ cardId, labelId }) => {
|
||||
Card.withId(cardId).labels.add(labelId);
|
||||
});
|
||||
|
||||
break;
|
||||
case ActionTypes.LABEL_TO_CARD_ADD:
|
||||
Card.withId(payload.cardId).labels.add(payload.id);
|
||||
|
||||
break;
|
||||
case ActionTypes.LABEL_TO_CARD_ADD__SUCCESS:
|
||||
case ActionTypes.LABEL_TO_CARD_ADD_HANDLE:
|
||||
try {
|
||||
Card.withId(payload.cardLabel.cardId).labels.add(payload.cardLabel.labelId);
|
||||
} catch {} // eslint-disable-line no-empty
|
||||
|
||||
break;
|
||||
case ActionTypes.LABEL_FROM_CARD_REMOVE:
|
||||
Card.withId(payload.cardId).labels.remove(payload.id);
|
||||
|
||||
break;
|
||||
case ActionTypes.LABEL_FROM_CARD_REMOVE__SUCCESS:
|
||||
case ActionTypes.LABEL_FROM_CARD_REMOVE_HANDLE:
|
||||
try {
|
||||
Card.withId(payload.cardLabel.cardId).labels.remove(payload.cardLabel.labelId);
|
||||
} catch {} // eslint-disable-line no-empty
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_CREATE:
|
||||
case ActionTypes.CARD_UPDATE__SUCCESS:
|
||||
case ActionTypes.CARD_UPDATE_HANDLE:
|
||||
Card.upsert(payload.card);
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_CREATE__SUCCESS:
|
||||
Card.withId(payload.localId).delete();
|
||||
Card.upsert(payload.card);
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_CREATE_HANDLE: {
|
||||
const cardModel = Card.upsert(payload.card);
|
||||
|
||||
payload.cardMemberships.forEach(({ userId }) => {
|
||||
cardModel.users.add(userId);
|
||||
});
|
||||
|
||||
payload.cardLabels.forEach(({ labelId }) => {
|
||||
cardModel.labels.add(labelId);
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.CARD_UPDATE:
|
||||
Card.withId(payload.id).update(payload.data);
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_DUPLICATE: {
|
||||
const cardModel = Card.withId(payload.id);
|
||||
|
||||
const nextCardModel = Card.upsert({
|
||||
...pick(cardModel.ref, [
|
||||
'boardId',
|
||||
'listId',
|
||||
'position',
|
||||
'name',
|
||||
'description',
|
||||
'dueDate',
|
||||
'stopwatch',
|
||||
]),
|
||||
...payload.card,
|
||||
});
|
||||
|
||||
cardModel.users.toRefArray().forEach(({ id }) => {
|
||||
nextCardModel.users.add(id);
|
||||
});
|
||||
|
||||
cardModel.labels.toRefArray().forEach(({ id }) => {
|
||||
nextCardModel.labels.add(id);
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.CARD_DUPLICATE__SUCCESS: {
|
||||
Card.withId(payload.localId).deleteWithRelated();
|
||||
const cardModel = Card.upsert(payload.card);
|
||||
|
||||
payload.cardMemberships.forEach(({ userId }) => {
|
||||
cardModel.users.add(userId);
|
||||
});
|
||||
|
||||
payload.cardLabels.forEach(({ labelId }) => {
|
||||
cardModel.labels.add(labelId);
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.CARD_DELETE:
|
||||
Card.withId(payload.id).deleteWithRelated();
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_DELETE__SUCCESS:
|
||||
case ActionTypes.CARD_DELETE_HANDLE: {
|
||||
const cardModel = Card.withId(payload.card.id);
|
||||
|
||||
if (cardModel) {
|
||||
cardModel.deleteWithRelated();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.ACTIVITIES_FETCH:
|
||||
Card.withId(payload.cardId).update({
|
||||
isActivitiesFetching: true,
|
||||
});
|
||||
|
||||
break;
|
||||
case ActionTypes.ACTIVITIES_FETCH__SUCCESS:
|
||||
Card.withId(payload.cardId).update({
|
||||
isActivitiesFetching: false,
|
||||
isAllActivitiesFetched: payload.activities.length < Config.ACTIVITIES_LIMIT,
|
||||
});
|
||||
|
||||
break;
|
||||
case ActionTypes.ACTIVITIES_DETAILS_TOGGLE: {
|
||||
const cardModel = Card.withId(payload.cardId);
|
||||
cardModel.isActivitiesDetailsVisible = payload.isVisible;
|
||||
|
||||
if (payload.isVisible) {
|
||||
cardModel.isActivitiesDetailsFetching = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.ACTIVITIES_DETAILS_TOGGLE__SUCCESS: {
|
||||
const cardModel = Card.withId(payload.cardId);
|
||||
|
||||
cardModel.update({
|
||||
isAllActivitiesFetched: payload.activities.length < Config.ACTIVITIES_LIMIT,
|
||||
isActivitiesDetailsFetching: false,
|
||||
});
|
||||
|
||||
cardModel.deleteActivities();
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.NOTIFICATION_CREATE_HANDLE:
|
||||
payload.cards.forEach((card) => {
|
||||
Card.upsert(card);
|
||||
});
|
||||
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
getOrderedTasksQuerySet() {
|
||||
return this.tasks.orderBy('position');
|
||||
}
|
||||
|
||||
getOrderedAttachmentsQuerySet() {
|
||||
return this.attachments.orderBy('createdAt', false);
|
||||
}
|
||||
|
||||
getFilteredOrderedInCardActivitiesQuerySet() {
|
||||
const filter = {
|
||||
isInCard: true,
|
||||
};
|
||||
|
||||
if (!this.isActivitiesDetailsVisible) {
|
||||
filter.type = ActivityTypes.COMMENT_CARD;
|
||||
}
|
||||
|
||||
return this.activities.filter(filter).orderBy('createdAt', false);
|
||||
}
|
||||
|
||||
getUnreadNotificationsQuerySet() {
|
||||
return this.notifications.filter({
|
||||
isRead: false,
|
||||
});
|
||||
}
|
||||
|
||||
isAvailableForUser(userId) {
|
||||
return this.board && this.board.isAvailableForUser(userId);
|
||||
}
|
||||
|
||||
deleteClearable() {
|
||||
this.users.clear();
|
||||
this.labels.clear();
|
||||
}
|
||||
|
||||
deleteActivities() {
|
||||
this.activities.toModelArray().forEach((activityModel) => {
|
||||
if (activityModel.notification) {
|
||||
activityModel.update({
|
||||
isInCard: false,
|
||||
});
|
||||
} else {
|
||||
activityModel.delete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
deleteRelated() {
|
||||
this.deleteClearable();
|
||||
this.tasks.delete();
|
||||
this.attachments.delete();
|
||||
this.deleteActivities();
|
||||
}
|
||||
|
||||
deleteWithClearable() {
|
||||
this.deleteClearable();
|
||||
this.delete();
|
||||
}
|
||||
|
||||
deleteWithRelated() {
|
||||
this.deleteRelated();
|
||||
this.delete();
|
||||
}
|
||||
}
|
||||
import pick from 'lodash/pick';
|
||||
import { attr, fk, many, oneToOne } from 'redux-orm';
|
||||
|
||||
import BaseModel from './BaseModel';
|
||||
import ActionTypes from '../constants/ActionTypes';
|
||||
import Config from '../constants/Config';
|
||||
import { ActivityTypes } from '../constants/Enums';
|
||||
|
||||
export default class extends BaseModel {
|
||||
static modelName = 'Card';
|
||||
|
||||
static fields = {
|
||||
id: attr(),
|
||||
position: attr(),
|
||||
name: attr(),
|
||||
description: attr(),
|
||||
dueDate: attr(),
|
||||
stopwatch: attr(),
|
||||
isSubscribed: attr({
|
||||
getDefault: () => false,
|
||||
}),
|
||||
isActivitiesFetching: attr({
|
||||
getDefault: () => false,
|
||||
}),
|
||||
isAllActivitiesFetched: attr({
|
||||
getDefault: () => false,
|
||||
}),
|
||||
isActivitiesDetailsVisible: attr({
|
||||
getDefault: () => false,
|
||||
}),
|
||||
isActivitiesDetailsFetching: attr({
|
||||
getDefault: () => false,
|
||||
}),
|
||||
boardId: fk({
|
||||
to: 'Board',
|
||||
as: 'board',
|
||||
relatedName: 'cards',
|
||||
}),
|
||||
listId: fk({
|
||||
to: 'List',
|
||||
as: 'list',
|
||||
relatedName: 'cards',
|
||||
}),
|
||||
coverAttachmentId: oneToOne({
|
||||
to: 'Attachment',
|
||||
as: 'coverAttachment',
|
||||
relatedName: 'coveredCard',
|
||||
}),
|
||||
users: many('User', 'cards'),
|
||||
labels: many('Label', 'cards'),
|
||||
};
|
||||
|
||||
static reducer({ type, payload }, Card) {
|
||||
switch (type) {
|
||||
case ActionTypes.LOCATION_CHANGE_HANDLE:
|
||||
case ActionTypes.CORE_INITIALIZE:
|
||||
case ActionTypes.PROJECT_MANAGER_CREATE_HANDLE:
|
||||
case ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE:
|
||||
if (payload.cards) {
|
||||
payload.cards.forEach((card) => {
|
||||
Card.upsert(card);
|
||||
});
|
||||
}
|
||||
|
||||
if (payload.cardMemberships) {
|
||||
payload.cardMemberships.forEach(({ cardId, userId }) => {
|
||||
Card.withId(cardId).users.add(userId);
|
||||
});
|
||||
}
|
||||
|
||||
if (payload.cardLabels) {
|
||||
payload.cardLabels.forEach(({ cardId, labelId }) => {
|
||||
Card.withId(cardId).labels.add(labelId);
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
case ActionTypes.SOCKET_RECONNECT_HANDLE:
|
||||
Card.all()
|
||||
.toModelArray()
|
||||
.forEach((cardModel) => {
|
||||
cardModel.deleteWithClearable();
|
||||
});
|
||||
|
||||
if (payload.cards) {
|
||||
payload.cards.forEach((card) => {
|
||||
Card.upsert(card);
|
||||
});
|
||||
}
|
||||
|
||||
if (payload.cardMemberships) {
|
||||
payload.cardMemberships.forEach(({ cardId, userId }) => {
|
||||
Card.withId(cardId).users.add(userId);
|
||||
});
|
||||
}
|
||||
|
||||
if (payload.cardLabels) {
|
||||
payload.cardLabels.forEach(({ cardId, labelId }) => {
|
||||
Card.withId(cardId).labels.add(labelId);
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
case ActionTypes.USER_TO_CARD_ADD: {
|
||||
const cardModel = Card.withId(payload.cardId);
|
||||
cardModel.users.add(payload.id);
|
||||
|
||||
if (payload.isCurrent) {
|
||||
cardModel.isSubscribed = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.USER_TO_CARD_ADD__SUCCESS:
|
||||
case ActionTypes.USER_TO_CARD_ADD_HANDLE:
|
||||
try {
|
||||
Card.withId(payload.cardMembership.cardId).users.add(payload.cardMembership.userId);
|
||||
} catch {} // eslint-disable-line no-empty
|
||||
|
||||
break;
|
||||
case ActionTypes.USER_FROM_CARD_REMOVE:
|
||||
Card.withId(payload.cardId).users.remove(payload.id);
|
||||
|
||||
break;
|
||||
case ActionTypes.USER_FROM_CARD_REMOVE__SUCCESS:
|
||||
case ActionTypes.USER_FROM_CARD_REMOVE_HANDLE:
|
||||
try {
|
||||
Card.withId(payload.cardMembership.cardId).users.remove(payload.cardMembership.userId);
|
||||
} catch {} // eslint-disable-line no-empty
|
||||
|
||||
break;
|
||||
case ActionTypes.BOARD_FETCH__SUCCESS:
|
||||
payload.cards.forEach((card) => {
|
||||
Card.upsert(card);
|
||||
});
|
||||
|
||||
payload.cardMemberships.forEach(({ cardId, userId }) => {
|
||||
Card.withId(cardId).users.add(userId);
|
||||
});
|
||||
|
||||
payload.cardLabels.forEach(({ cardId, labelId }) => {
|
||||
Card.withId(cardId).labels.add(labelId);
|
||||
});
|
||||
|
||||
break;
|
||||
case ActionTypes.LABEL_TO_CARD_ADD:
|
||||
Card.withId(payload.cardId).labels.add(payload.id);
|
||||
|
||||
break;
|
||||
case ActionTypes.LABEL_TO_CARD_ADD__SUCCESS:
|
||||
case ActionTypes.LABEL_TO_CARD_ADD_HANDLE:
|
||||
try {
|
||||
Card.withId(payload.cardLabel.cardId).labels.add(payload.cardLabel.labelId);
|
||||
} catch {} // eslint-disable-line no-empty
|
||||
|
||||
break;
|
||||
case ActionTypes.LABEL_FROM_CARD_REMOVE:
|
||||
Card.withId(payload.cardId).labels.remove(payload.id);
|
||||
|
||||
break;
|
||||
case ActionTypes.LABEL_FROM_CARD_REMOVE__SUCCESS:
|
||||
case ActionTypes.LABEL_FROM_CARD_REMOVE_HANDLE:
|
||||
try {
|
||||
Card.withId(payload.cardLabel.cardId).labels.remove(payload.cardLabel.labelId);
|
||||
} catch {} // eslint-disable-line no-empty
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_CREATE:
|
||||
case ActionTypes.CARD_UPDATE__SUCCESS:
|
||||
case ActionTypes.CARD_UPDATE_HANDLE:
|
||||
Card.upsert(payload.card);
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_CREATE__SUCCESS:
|
||||
Card.withId(payload.localId).delete();
|
||||
Card.upsert(payload.card);
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_CREATE_HANDLE: {
|
||||
const cardModel = Card.upsert(payload.card);
|
||||
|
||||
payload.cardMemberships.forEach(({ userId }) => {
|
||||
cardModel.users.add(userId);
|
||||
});
|
||||
|
||||
payload.cardLabels.forEach(({ labelId }) => {
|
||||
cardModel.labels.add(labelId);
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.CARD_UPDATE:
|
||||
Card.withId(payload.id).update(payload.data);
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_DUPLICATE: {
|
||||
const cardModel = Card.withId(payload.id);
|
||||
|
||||
const nextCardModel = Card.upsert({
|
||||
...pick(cardModel.ref, [
|
||||
'boardId',
|
||||
'listId',
|
||||
'position',
|
||||
'name',
|
||||
'description',
|
||||
'dueDate',
|
||||
'stopwatch',
|
||||
]),
|
||||
...payload.card,
|
||||
});
|
||||
|
||||
cardModel.users.toRefArray().forEach(({ id }) => {
|
||||
nextCardModel.users.add(id);
|
||||
});
|
||||
|
||||
cardModel.labels.toRefArray().forEach(({ id }) => {
|
||||
nextCardModel.labels.add(id);
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.CARD_DUPLICATE__SUCCESS: {
|
||||
Card.withId(payload.localId).deleteWithRelated();
|
||||
const cardModel = Card.upsert(payload.card);
|
||||
|
||||
payload.cardMemberships.forEach(({ userId }) => {
|
||||
cardModel.users.add(userId);
|
||||
});
|
||||
|
||||
payload.cardLabels.forEach(({ labelId }) => {
|
||||
cardModel.labels.add(labelId);
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.CARD_DELETE:
|
||||
Card.withId(payload.id).deleteWithRelated();
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_DELETE__SUCCESS:
|
||||
case ActionTypes.CARD_DELETE_HANDLE: {
|
||||
const cardModel = Card.withId(payload.card.id);
|
||||
|
||||
if (cardModel) {
|
||||
cardModel.deleteWithRelated();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.ACTIVITIES_FETCH:
|
||||
Card.withId(payload.cardId).update({
|
||||
isActivitiesFetching: true,
|
||||
});
|
||||
|
||||
break;
|
||||
case ActionTypes.ACTIVITIES_FETCH__SUCCESS:
|
||||
Card.withId(payload.cardId).update({
|
||||
isActivitiesFetching: false,
|
||||
isAllActivitiesFetched: payload.activities.length < Config.ACTIVITIES_LIMIT,
|
||||
});
|
||||
|
||||
break;
|
||||
case ActionTypes.ACTIVITIES_DETAILS_TOGGLE: {
|
||||
const cardModel = Card.withId(payload.cardId);
|
||||
cardModel.isActivitiesDetailsVisible = payload.isVisible;
|
||||
|
||||
if (payload.isVisible) {
|
||||
cardModel.isActivitiesDetailsFetching = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.ACTIVITIES_DETAILS_TOGGLE__SUCCESS: {
|
||||
const cardModel = Card.withId(payload.cardId);
|
||||
|
||||
cardModel.update({
|
||||
isAllActivitiesFetched: payload.activities.length < Config.ACTIVITIES_LIMIT,
|
||||
isActivitiesDetailsFetching: false,
|
||||
});
|
||||
|
||||
cardModel.deleteActivities();
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.NOTIFICATION_CREATE_HANDLE:
|
||||
payload.cards.forEach((card) => {
|
||||
Card.upsert(card);
|
||||
});
|
||||
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
getOrderedTasksQuerySet() {
|
||||
return this.tasks.orderBy('position');
|
||||
}
|
||||
|
||||
getOrderedAttachmentsQuerySet() {
|
||||
return this.attachments.orderBy('createdAt', false);
|
||||
}
|
||||
|
||||
getFilteredOrderedInCardActivitiesQuerySet() {
|
||||
const filter = {
|
||||
isInCard: true,
|
||||
};
|
||||
|
||||
if (!this.isActivitiesDetailsVisible) {
|
||||
filter.type = ActivityTypes.COMMENT_CARD;
|
||||
}
|
||||
|
||||
return this.activities.filter(filter).orderBy('createdAt', false);
|
||||
}
|
||||
|
||||
getUnreadNotificationsQuerySet() {
|
||||
return this.notifications.filter({
|
||||
isRead: false,
|
||||
});
|
||||
}
|
||||
|
||||
isAvailableForUser(userId) {
|
||||
return this.board && this.board.isAvailableForUser(userId);
|
||||
}
|
||||
|
||||
deleteClearable() {
|
||||
this.users.clear();
|
||||
this.labels.clear();
|
||||
}
|
||||
|
||||
deleteActivities() {
|
||||
this.activities.toModelArray().forEach((activityModel) => {
|
||||
if (activityModel.notification) {
|
||||
activityModel.update({
|
||||
isInCard: false,
|
||||
});
|
||||
} else {
|
||||
activityModel.delete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
deleteRelated() {
|
||||
this.deleteClearable();
|
||||
this.tasks.delete();
|
||||
this.attachments.delete();
|
||||
this.deleteActivities();
|
||||
}
|
||||
|
||||
deleteWithClearable() {
|
||||
this.deleteClearable();
|
||||
this.delete();
|
||||
}
|
||||
|
||||
deleteWithRelated() {
|
||||
this.deleteRelated();
|
||||
this.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,100 +1,100 @@
|
||||
import { attr, fk } from 'redux-orm';
|
||||
|
||||
import { createLocalId } from '../utils/local-id';
|
||||
import BaseModel from './BaseModel';
|
||||
import ActionTypes from '../constants/ActionTypes';
|
||||
|
||||
export default class extends BaseModel {
|
||||
static modelName = 'Task';
|
||||
|
||||
static fields = {
|
||||
id: attr(),
|
||||
position: attr(),
|
||||
name: attr(),
|
||||
isCompleted: attr({
|
||||
getDefault: () => false,
|
||||
}),
|
||||
cardId: fk({
|
||||
to: 'Card',
|
||||
as: 'card',
|
||||
relatedName: 'tasks',
|
||||
}),
|
||||
};
|
||||
|
||||
static reducer({ type, payload }, Task) {
|
||||
switch (type) {
|
||||
case ActionTypes.LOCATION_CHANGE_HANDLE:
|
||||
case ActionTypes.CORE_INITIALIZE:
|
||||
case ActionTypes.PROJECT_MANAGER_CREATE_HANDLE:
|
||||
case ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE:
|
||||
if (payload.tasks) {
|
||||
payload.tasks.forEach((task) => {
|
||||
Task.upsert(task);
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
case ActionTypes.SOCKET_RECONNECT_HANDLE:
|
||||
Task.all().delete();
|
||||
|
||||
if (payload.tasks) {
|
||||
payload.tasks.forEach((task) => {
|
||||
Task.upsert(task);
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
case ActionTypes.BOARD_FETCH__SUCCESS:
|
||||
case ActionTypes.CARD_CREATE_HANDLE:
|
||||
case ActionTypes.CARD_DUPLICATE__SUCCESS:
|
||||
payload.tasks.forEach((task) => {
|
||||
Task.upsert(task);
|
||||
});
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_DUPLICATE:
|
||||
payload.taskIds.forEach((taskId, index) => {
|
||||
const taskModel = Task.withId(taskId);
|
||||
|
||||
Task.upsert({
|
||||
...taskModel.ref,
|
||||
id: `${createLocalId()}-${index}`, // TODO: hack?
|
||||
cardId: payload.card.id,
|
||||
});
|
||||
});
|
||||
|
||||
break;
|
||||
case ActionTypes.TASK_CREATE:
|
||||
case ActionTypes.TASK_CREATE_HANDLE:
|
||||
case ActionTypes.TASK_UPDATE__SUCCESS:
|
||||
case ActionTypes.TASK_UPDATE_HANDLE:
|
||||
Task.upsert(payload.task);
|
||||
|
||||
break;
|
||||
case ActionTypes.TASK_CREATE__SUCCESS:
|
||||
Task.withId(payload.localId).delete();
|
||||
Task.upsert(payload.task);
|
||||
|
||||
break;
|
||||
case ActionTypes.TASK_UPDATE:
|
||||
Task.withId(payload.id).update(payload.data);
|
||||
|
||||
break;
|
||||
case ActionTypes.TASK_DELETE:
|
||||
Task.withId(payload.id).delete();
|
||||
|
||||
break;
|
||||
case ActionTypes.TASK_DELETE__SUCCESS:
|
||||
case ActionTypes.TASK_DELETE_HANDLE: {
|
||||
const taskModel = Task.withId(payload.task.id);
|
||||
|
||||
if (taskModel) {
|
||||
taskModel.delete();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
import { attr, fk } from 'redux-orm';
|
||||
|
||||
import { createLocalId } from '../utils/local-id';
|
||||
import BaseModel from './BaseModel';
|
||||
import ActionTypes from '../constants/ActionTypes';
|
||||
|
||||
export default class extends BaseModel {
|
||||
static modelName = 'Task';
|
||||
|
||||
static fields = {
|
||||
id: attr(),
|
||||
position: attr(),
|
||||
name: attr(),
|
||||
isCompleted: attr({
|
||||
getDefault: () => false,
|
||||
}),
|
||||
cardId: fk({
|
||||
to: 'Card',
|
||||
as: 'card',
|
||||
relatedName: 'tasks',
|
||||
}),
|
||||
};
|
||||
|
||||
static reducer({ type, payload }, Task) {
|
||||
switch (type) {
|
||||
case ActionTypes.LOCATION_CHANGE_HANDLE:
|
||||
case ActionTypes.CORE_INITIALIZE:
|
||||
case ActionTypes.PROJECT_MANAGER_CREATE_HANDLE:
|
||||
case ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE:
|
||||
if (payload.tasks) {
|
||||
payload.tasks.forEach((task) => {
|
||||
Task.upsert(task);
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
case ActionTypes.SOCKET_RECONNECT_HANDLE:
|
||||
Task.all().delete();
|
||||
|
||||
if (payload.tasks) {
|
||||
payload.tasks.forEach((task) => {
|
||||
Task.upsert(task);
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
case ActionTypes.BOARD_FETCH__SUCCESS:
|
||||
case ActionTypes.CARD_CREATE_HANDLE:
|
||||
case ActionTypes.CARD_DUPLICATE__SUCCESS:
|
||||
payload.tasks.forEach((task) => {
|
||||
Task.upsert(task);
|
||||
});
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_DUPLICATE:
|
||||
payload.taskIds.forEach((taskId, index) => {
|
||||
const taskModel = Task.withId(taskId);
|
||||
|
||||
Task.upsert({
|
||||
...taskModel.ref,
|
||||
id: `${createLocalId()}-${index}`, // TODO: hack?
|
||||
cardId: payload.card.id,
|
||||
});
|
||||
});
|
||||
|
||||
break;
|
||||
case ActionTypes.TASK_CREATE:
|
||||
case ActionTypes.TASK_CREATE_HANDLE:
|
||||
case ActionTypes.TASK_UPDATE__SUCCESS:
|
||||
case ActionTypes.TASK_UPDATE_HANDLE:
|
||||
Task.upsert(payload.task);
|
||||
|
||||
break;
|
||||
case ActionTypes.TASK_CREATE__SUCCESS:
|
||||
Task.withId(payload.localId).delete();
|
||||
Task.upsert(payload.task);
|
||||
|
||||
break;
|
||||
case ActionTypes.TASK_UPDATE:
|
||||
Task.withId(payload.id).update(payload.data);
|
||||
|
||||
break;
|
||||
case ActionTypes.TASK_DELETE:
|
||||
Task.withId(payload.id).delete();
|
||||
|
||||
break;
|
||||
case ActionTypes.TASK_DELETE__SUCCESS:
|
||||
case ActionTypes.TASK_DELETE_HANDLE: {
|
||||
const taskModel = Task.withId(payload.task.id);
|
||||
|
||||
if (taskModel) {
|
||||
taskModel.delete();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,225 +1,225 @@
|
||||
import { call, put, select } from 'redux-saga/effects';
|
||||
|
||||
import { goToBoard, goToCard } from './router';
|
||||
import request from '../request';
|
||||
import selectors from '../../../selectors';
|
||||
import actions from '../../../actions';
|
||||
import api from '../../../api';
|
||||
import i18n from '../../../i18n';
|
||||
import { createLocalId } from '../../../utils/local-id';
|
||||
|
||||
export function* createCard(listId, data, autoOpen) {
|
||||
const { boardId } = yield select(selectors.selectListById, listId);
|
||||
|
||||
const nextData = {
|
||||
...data,
|
||||
position: yield select(selectors.selectNextCardPosition, listId),
|
||||
};
|
||||
|
||||
const localId = yield call(createLocalId);
|
||||
|
||||
yield put(
|
||||
actions.createCard({
|
||||
...nextData,
|
||||
boardId,
|
||||
listId,
|
||||
id: localId,
|
||||
}),
|
||||
);
|
||||
|
||||
let card;
|
||||
try {
|
||||
({ item: card } = yield call(request, api.createCard, listId, nextData));
|
||||
} catch (error) {
|
||||
yield put(actions.createCard.failure(localId, error));
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(actions.createCard.success(localId, card));
|
||||
|
||||
if (autoOpen) {
|
||||
yield call(goToCard, card.id);
|
||||
}
|
||||
}
|
||||
|
||||
export function* handleCardCreate({ id }) {
|
||||
let card;
|
||||
let cardMemberships;
|
||||
let cardLabels;
|
||||
let tasks;
|
||||
let attachments;
|
||||
|
||||
try {
|
||||
({
|
||||
item: card,
|
||||
included: { cardMemberships, cardLabels, tasks, attachments },
|
||||
} = yield call(request, api.getCard, id));
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(actions.handleCardCreate(card, cardMemberships, cardLabels, tasks, attachments));
|
||||
}
|
||||
|
||||
export function* updateCard(id, data) {
|
||||
yield put(actions.updateCard(id, data));
|
||||
|
||||
let card;
|
||||
try {
|
||||
({ item: card } = yield call(request, api.updateCard, id, data));
|
||||
} catch (error) {
|
||||
yield put(actions.updateCard.failure(id, error));
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(actions.updateCard.success(card));
|
||||
}
|
||||
|
||||
export function* updateCurrentCard(data) {
|
||||
const { cardId } = yield select(selectors.selectPath);
|
||||
|
||||
yield call(updateCard, cardId, data);
|
||||
}
|
||||
|
||||
// TODO: handle card transfer
|
||||
export function* handleCardUpdate(card) {
|
||||
yield put(actions.handleCardUpdate(card));
|
||||
}
|
||||
|
||||
export function* moveCard(id, listId, index) {
|
||||
const position = yield select(selectors.selectNextCardPosition, listId, index, id);
|
||||
|
||||
yield call(updateCard, id, {
|
||||
listId,
|
||||
position,
|
||||
});
|
||||
}
|
||||
|
||||
export function* moveCurrentCard(listId, index) {
|
||||
const { cardId } = yield select(selectors.selectPath);
|
||||
|
||||
yield call(moveCard, cardId, listId, index);
|
||||
}
|
||||
|
||||
export function* transferCard(id, boardId, listId, index) {
|
||||
const { cardId: currentCardId, boardId: currentBoardId } = yield select(selectors.selectPath);
|
||||
const position = yield select(selectors.selectNextCardPosition, listId, index, id);
|
||||
|
||||
if (id === currentCardId) {
|
||||
yield call(goToBoard, currentBoardId);
|
||||
}
|
||||
|
||||
yield call(updateCard, id, {
|
||||
boardId,
|
||||
listId,
|
||||
position,
|
||||
});
|
||||
}
|
||||
|
||||
export function* transferCurrentCard(boardId, listId, index) {
|
||||
const { cardId } = yield select(selectors.selectPath);
|
||||
|
||||
yield call(transferCard, cardId, boardId, listId, index);
|
||||
}
|
||||
|
||||
export function* duplicateCard(id) {
|
||||
const { listId, name } = yield select(selectors.selectCardById, id);
|
||||
const index = yield select(selectors.selectCardIndexById, id);
|
||||
|
||||
const nextData = {
|
||||
position: yield select(selectors.selectNextCardPosition, listId, index + 1),
|
||||
name: `${name} (${i18n.t('common.copy', {
|
||||
context: 'inline',
|
||||
})})`,
|
||||
};
|
||||
|
||||
const localId = yield call(createLocalId);
|
||||
const taskIds = yield select(selectors.selectTaskIdsByCardId, id);
|
||||
|
||||
yield put(
|
||||
actions.duplicateCard(
|
||||
id,
|
||||
{
|
||||
...nextData,
|
||||
id: localId,
|
||||
},
|
||||
taskIds,
|
||||
),
|
||||
);
|
||||
|
||||
let card;
|
||||
let cardMemberships;
|
||||
let cardLabels;
|
||||
let tasks;
|
||||
|
||||
try {
|
||||
({
|
||||
item: card,
|
||||
included: { cardMemberships, cardLabels, tasks },
|
||||
} = yield call(request, api.duplicateCard, id, nextData));
|
||||
} catch (error) {
|
||||
yield put(actions.duplicateCard.failure(localId, error));
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(actions.duplicateCard.success(localId, card, cardMemberships, cardLabels, tasks));
|
||||
}
|
||||
|
||||
export function* duplicateCurrentCard() {
|
||||
const { cardId } = yield select(selectors.selectPath);
|
||||
|
||||
yield call(duplicateCard, cardId);
|
||||
}
|
||||
|
||||
export function* deleteCard(id) {
|
||||
const { cardId, boardId } = yield select(selectors.selectPath);
|
||||
|
||||
if (id === cardId) {
|
||||
yield call(goToBoard, boardId);
|
||||
}
|
||||
|
||||
yield put(actions.deleteCard(id));
|
||||
|
||||
let card;
|
||||
try {
|
||||
({ item: card } = yield call(request, api.deleteCard, id));
|
||||
} catch (error) {
|
||||
yield put(actions.deleteCard.failure(id, error));
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(actions.deleteCard.success(card));
|
||||
}
|
||||
|
||||
export function* deleteCurrentCard() {
|
||||
const { cardId } = yield select(selectors.selectPath);
|
||||
|
||||
yield call(deleteCard, cardId);
|
||||
}
|
||||
|
||||
export function* handleCardDelete(card) {
|
||||
const { cardId, boardId } = yield select(selectors.selectPath);
|
||||
|
||||
if (card.id === cardId) {
|
||||
yield call(goToBoard, boardId);
|
||||
}
|
||||
|
||||
yield put(actions.handleCardDelete(card));
|
||||
}
|
||||
|
||||
export default {
|
||||
createCard,
|
||||
handleCardCreate,
|
||||
updateCard,
|
||||
updateCurrentCard,
|
||||
handleCardUpdate,
|
||||
moveCard,
|
||||
moveCurrentCard,
|
||||
transferCard,
|
||||
transferCurrentCard,
|
||||
duplicateCard,
|
||||
duplicateCurrentCard,
|
||||
deleteCard,
|
||||
deleteCurrentCard,
|
||||
handleCardDelete,
|
||||
};
|
||||
import { call, put, select } from 'redux-saga/effects';
|
||||
|
||||
import { goToBoard, goToCard } from './router';
|
||||
import request from '../request';
|
||||
import selectors from '../../../selectors';
|
||||
import actions from '../../../actions';
|
||||
import api from '../../../api';
|
||||
import i18n from '../../../i18n';
|
||||
import { createLocalId } from '../../../utils/local-id';
|
||||
|
||||
export function* createCard(listId, data, autoOpen) {
|
||||
const { boardId } = yield select(selectors.selectListById, listId);
|
||||
|
||||
const nextData = {
|
||||
...data,
|
||||
position: yield select(selectors.selectNextCardPosition, listId),
|
||||
};
|
||||
|
||||
const localId = yield call(createLocalId);
|
||||
|
||||
yield put(
|
||||
actions.createCard({
|
||||
...nextData,
|
||||
boardId,
|
||||
listId,
|
||||
id: localId,
|
||||
}),
|
||||
);
|
||||
|
||||
let card;
|
||||
try {
|
||||
({ item: card } = yield call(request, api.createCard, listId, nextData));
|
||||
} catch (error) {
|
||||
yield put(actions.createCard.failure(localId, error));
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(actions.createCard.success(localId, card));
|
||||
|
||||
if (autoOpen) {
|
||||
yield call(goToCard, card.id);
|
||||
}
|
||||
}
|
||||
|
||||
export function* handleCardCreate({ id }) {
|
||||
let card;
|
||||
let cardMemberships;
|
||||
let cardLabels;
|
||||
let tasks;
|
||||
let attachments;
|
||||
|
||||
try {
|
||||
({
|
||||
item: card,
|
||||
included: { cardMemberships, cardLabels, tasks, attachments },
|
||||
} = yield call(request, api.getCard, id));
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(actions.handleCardCreate(card, cardMemberships, cardLabels, tasks, attachments));
|
||||
}
|
||||
|
||||
export function* updateCard(id, data) {
|
||||
yield put(actions.updateCard(id, data));
|
||||
|
||||
let card;
|
||||
try {
|
||||
({ item: card } = yield call(request, api.updateCard, id, data));
|
||||
} catch (error) {
|
||||
yield put(actions.updateCard.failure(id, error));
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(actions.updateCard.success(card));
|
||||
}
|
||||
|
||||
export function* updateCurrentCard(data) {
|
||||
const { cardId } = yield select(selectors.selectPath);
|
||||
|
||||
yield call(updateCard, cardId, data);
|
||||
}
|
||||
|
||||
// TODO: handle card transfer
|
||||
export function* handleCardUpdate(card) {
|
||||
yield put(actions.handleCardUpdate(card));
|
||||
}
|
||||
|
||||
export function* moveCard(id, listId, index) {
|
||||
const position = yield select(selectors.selectNextCardPosition, listId, index, id);
|
||||
|
||||
yield call(updateCard, id, {
|
||||
listId,
|
||||
position,
|
||||
});
|
||||
}
|
||||
|
||||
export function* moveCurrentCard(listId, index) {
|
||||
const { cardId } = yield select(selectors.selectPath);
|
||||
|
||||
yield call(moveCard, cardId, listId, index);
|
||||
}
|
||||
|
||||
export function* transferCard(id, boardId, listId, index) {
|
||||
const { cardId: currentCardId, boardId: currentBoardId } = yield select(selectors.selectPath);
|
||||
const position = yield select(selectors.selectNextCardPosition, listId, index, id);
|
||||
|
||||
if (id === currentCardId) {
|
||||
yield call(goToBoard, currentBoardId);
|
||||
}
|
||||
|
||||
yield call(updateCard, id, {
|
||||
boardId,
|
||||
listId,
|
||||
position,
|
||||
});
|
||||
}
|
||||
|
||||
export function* transferCurrentCard(boardId, listId, index) {
|
||||
const { cardId } = yield select(selectors.selectPath);
|
||||
|
||||
yield call(transferCard, cardId, boardId, listId, index);
|
||||
}
|
||||
|
||||
export function* duplicateCard(id) {
|
||||
const { listId, name } = yield select(selectors.selectCardById, id);
|
||||
const index = yield select(selectors.selectCardIndexById, id);
|
||||
|
||||
const nextData = {
|
||||
position: yield select(selectors.selectNextCardPosition, listId, index + 1),
|
||||
name: `${name} (${i18n.t('common.copy', {
|
||||
context: 'inline',
|
||||
})})`,
|
||||
};
|
||||
|
||||
const localId = yield call(createLocalId);
|
||||
const taskIds = yield select(selectors.selectTaskIdsByCardId, id);
|
||||
|
||||
yield put(
|
||||
actions.duplicateCard(
|
||||
id,
|
||||
{
|
||||
...nextData,
|
||||
id: localId,
|
||||
},
|
||||
taskIds,
|
||||
),
|
||||
);
|
||||
|
||||
let card;
|
||||
let cardMemberships;
|
||||
let cardLabels;
|
||||
let tasks;
|
||||
|
||||
try {
|
||||
({
|
||||
item: card,
|
||||
included: { cardMemberships, cardLabels, tasks },
|
||||
} = yield call(request, api.duplicateCard, id, nextData));
|
||||
} catch (error) {
|
||||
yield put(actions.duplicateCard.failure(localId, error));
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(actions.duplicateCard.success(localId, card, cardMemberships, cardLabels, tasks));
|
||||
}
|
||||
|
||||
export function* duplicateCurrentCard() {
|
||||
const { cardId } = yield select(selectors.selectPath);
|
||||
|
||||
yield call(duplicateCard, cardId);
|
||||
}
|
||||
|
||||
export function* deleteCard(id) {
|
||||
const { cardId, boardId } = yield select(selectors.selectPath);
|
||||
|
||||
if (id === cardId) {
|
||||
yield call(goToBoard, boardId);
|
||||
}
|
||||
|
||||
yield put(actions.deleteCard(id));
|
||||
|
||||
let card;
|
||||
try {
|
||||
({ item: card } = yield call(request, api.deleteCard, id));
|
||||
} catch (error) {
|
||||
yield put(actions.deleteCard.failure(id, error));
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(actions.deleteCard.success(card));
|
||||
}
|
||||
|
||||
export function* deleteCurrentCard() {
|
||||
const { cardId } = yield select(selectors.selectPath);
|
||||
|
||||
yield call(deleteCard, cardId);
|
||||
}
|
||||
|
||||
export function* handleCardDelete(card) {
|
||||
const { cardId, boardId } = yield select(selectors.selectPath);
|
||||
|
||||
if (card.id === cardId) {
|
||||
yield call(goToBoard, boardId);
|
||||
}
|
||||
|
||||
yield put(actions.handleCardDelete(card));
|
||||
}
|
||||
|
||||
export default {
|
||||
createCard,
|
||||
handleCardCreate,
|
||||
updateCard,
|
||||
updateCurrentCard,
|
||||
handleCardUpdate,
|
||||
moveCard,
|
||||
moveCurrentCard,
|
||||
transferCard,
|
||||
transferCurrentCard,
|
||||
duplicateCard,
|
||||
duplicateCurrentCard,
|
||||
deleteCard,
|
||||
deleteCurrentCard,
|
||||
handleCardDelete,
|
||||
};
|
||||
|
||||
@ -1,43 +1,43 @@
|
||||
import { all, takeEvery } from 'redux-saga/effects';
|
||||
|
||||
import services from '../services';
|
||||
import EntryActionTypes from '../../../constants/EntryActionTypes';
|
||||
|
||||
export default function* cardsWatchers() {
|
||||
yield all([
|
||||
takeEvery(EntryActionTypes.CARD_CREATE, ({ payload: { listId, data, autoOpen } }) =>
|
||||
services.createCard(listId, data, autoOpen),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CARD_CREATE_HANDLE, ({ payload: { card } }) =>
|
||||
services.handleCardCreate(card),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CARD_UPDATE, ({ payload: { id, data } }) =>
|
||||
services.updateCard(id, data),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CURRENT_CARD_UPDATE, ({ payload: { data } }) =>
|
||||
services.updateCurrentCard(data),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CARD_UPDATE_HANDLE, ({ payload: { card } }) =>
|
||||
services.handleCardUpdate(card),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CARD_MOVE, ({ payload: { id, listId, index } }) =>
|
||||
services.moveCard(id, listId, index),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CURRENT_CARD_MOVE, ({ payload: { listId, index } }) =>
|
||||
services.moveCurrentCard(listId, index),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CARD_TRANSFER, ({ payload: { id, boardId, listId, index } }) =>
|
||||
services.transferCard(id, boardId, listId, index),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CURRENT_CARD_TRANSFER, ({ payload: { boardId, listId, index } }) =>
|
||||
services.transferCurrentCard(boardId, listId, index),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CARD_DUPLICATE, ({ payload: { id } }) => services.duplicateCard(id)),
|
||||
takeEvery(EntryActionTypes.CURRENT_CARD_DUPLICATE, () => services.duplicateCurrentCard()),
|
||||
takeEvery(EntryActionTypes.CARD_DELETE, ({ payload: { id } }) => services.deleteCard(id)),
|
||||
takeEvery(EntryActionTypes.CURRENT_CARD_DELETE, () => services.deleteCurrentCard()),
|
||||
takeEvery(EntryActionTypes.CARD_DELETE_HANDLE, ({ payload: { card } }) =>
|
||||
services.handleCardDelete(card),
|
||||
),
|
||||
]);
|
||||
}
|
||||
import { all, takeEvery } from 'redux-saga/effects';
|
||||
|
||||
import services from '../services';
|
||||
import EntryActionTypes from '../../../constants/EntryActionTypes';
|
||||
|
||||
export default function* cardsWatchers() {
|
||||
yield all([
|
||||
takeEvery(EntryActionTypes.CARD_CREATE, ({ payload: { listId, data, autoOpen } }) =>
|
||||
services.createCard(listId, data, autoOpen),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CARD_CREATE_HANDLE, ({ payload: { card } }) =>
|
||||
services.handleCardCreate(card),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CARD_UPDATE, ({ payload: { id, data } }) =>
|
||||
services.updateCard(id, data),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CURRENT_CARD_UPDATE, ({ payload: { data } }) =>
|
||||
services.updateCurrentCard(data),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CARD_UPDATE_HANDLE, ({ payload: { card } }) =>
|
||||
services.handleCardUpdate(card),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CARD_MOVE, ({ payload: { id, listId, index } }) =>
|
||||
services.moveCard(id, listId, index),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CURRENT_CARD_MOVE, ({ payload: { listId, index } }) =>
|
||||
services.moveCurrentCard(listId, index),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CARD_TRANSFER, ({ payload: { id, boardId, listId, index } }) =>
|
||||
services.transferCard(id, boardId, listId, index),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CURRENT_CARD_TRANSFER, ({ payload: { boardId, listId, index } }) =>
|
||||
services.transferCurrentCard(boardId, listId, index),
|
||||
),
|
||||
takeEvery(EntryActionTypes.CARD_DUPLICATE, ({ payload: { id } }) => services.duplicateCard(id)),
|
||||
takeEvery(EntryActionTypes.CURRENT_CARD_DUPLICATE, () => services.duplicateCurrentCard()),
|
||||
takeEvery(EntryActionTypes.CARD_DELETE, ({ payload: { id } }) => services.deleteCard(id)),
|
||||
takeEvery(EntryActionTypes.CURRENT_CARD_DELETE, () => services.deleteCurrentCard()),
|
||||
takeEvery(EntryActionTypes.CARD_DELETE_HANDLE, ({ payload: { card } }) =>
|
||||
services.handleCardDelete(card),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -1,350 +1,350 @@
|
||||
import { createSelector } from 'redux-orm';
|
||||
|
||||
import orm from '../orm';
|
||||
import { selectPath } from './router';
|
||||
import { selectCurrentUserId } from './users';
|
||||
import { isLocalId } from '../utils/local-id';
|
||||
|
||||
export const makeSelectCardById = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return {
|
||||
...cardModel.ref,
|
||||
coverUrl: cardModel.coverAttachment && cardModel.coverAttachment.coverUrl,
|
||||
isPersisted: !isLocalId(id),
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
export const selectCardById = makeSelectCardById();
|
||||
|
||||
export const makeSelectCardIndexById = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
const cardModels = cardModel.list.getFilteredOrderedCardsModelArray();
|
||||
return cardModels.findIndex((cardModelItem) => cardModelItem.id === cardModel.id);
|
||||
},
|
||||
);
|
||||
|
||||
export const selectCardIndexById = makeSelectCardIndexById();
|
||||
|
||||
export const makeSelectUsersByCardId = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.users.toRefArray();
|
||||
},
|
||||
);
|
||||
|
||||
export const selectUsersByCardId = makeSelectUsersByCardId();
|
||||
|
||||
export const makeSelectLabelsByCardId = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.labels.toRefArray();
|
||||
},
|
||||
);
|
||||
|
||||
export const selectLabelsByCardId = makeSelectLabelsByCardId();
|
||||
|
||||
export const makeSelectTaskIdsByCardId = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel
|
||||
.getOrderedTasksQuerySet()
|
||||
.toRefArray()
|
||||
.map((task) => task.id);
|
||||
},
|
||||
);
|
||||
|
||||
export const selectTaskIdsByCardId = makeSelectTaskIdsByCardId();
|
||||
|
||||
export const makeSelectTasksByCardId = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.getOrderedTasksQuerySet().toRefArray();
|
||||
},
|
||||
);
|
||||
|
||||
export const selectTasksByCardId = makeSelectTasksByCardId();
|
||||
|
||||
export const makeSelectLastActivityIdByCardId = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
const lastActivityModel = cardModel.getFilteredOrderedInCardActivitiesQuerySet().last();
|
||||
|
||||
return lastActivityModel && lastActivityModel.id;
|
||||
},
|
||||
);
|
||||
|
||||
export const selectLastActivityIdByCardId = makeSelectLastActivityIdByCardId();
|
||||
|
||||
export const makeSelectNotificationsByCardId = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.getUnreadNotificationsQuerySet().toRefArray();
|
||||
},
|
||||
);
|
||||
|
||||
export const selectNotificationsByCardId = makeSelectNotificationsByCardId();
|
||||
|
||||
export const makeSelectNotificationsTotalByCardId = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.getUnreadNotificationsQuerySet().count();
|
||||
},
|
||||
);
|
||||
|
||||
export const selectNotificationsTotalByCardId = makeSelectNotificationsTotalByCardId();
|
||||
|
||||
export const selectCurrentCard = createSelector(
|
||||
orm,
|
||||
(state) => selectPath(state).cardId,
|
||||
({ Card }, id) => {
|
||||
if (!id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.ref;
|
||||
},
|
||||
);
|
||||
|
||||
export const selectUsersForCurrentCard = createSelector(
|
||||
orm,
|
||||
(state) => selectPath(state).cardId,
|
||||
({ Card }, id) => {
|
||||
if (!id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.users.toRefArray();
|
||||
},
|
||||
);
|
||||
|
||||
export const selectLabelsForCurrentCard = createSelector(
|
||||
orm,
|
||||
(state) => selectPath(state).cardId,
|
||||
({ Card }, id) => {
|
||||
if (!id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.labels.toRefArray();
|
||||
},
|
||||
);
|
||||
|
||||
export const selectTasksForCurrentCard = createSelector(
|
||||
orm,
|
||||
(state) => selectPath(state).cardId,
|
||||
({ Card }, id) => {
|
||||
if (!id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel
|
||||
.getOrderedTasksQuerySet()
|
||||
.toRefArray()
|
||||
.map((task) => ({
|
||||
...task,
|
||||
isPersisted: !isLocalId(task.id),
|
||||
}));
|
||||
},
|
||||
);
|
||||
|
||||
export const selectAttachmentsForCurrentCard = createSelector(
|
||||
orm,
|
||||
(state) => selectPath(state).cardId,
|
||||
({ Card }, id) => {
|
||||
if (!id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel
|
||||
.getOrderedAttachmentsQuerySet()
|
||||
.toRefArray()
|
||||
.map((attachment) => ({
|
||||
...attachment,
|
||||
isCover: attachment.id === cardModel.coverAttachmentId,
|
||||
isPersisted: !isLocalId(attachment.id),
|
||||
}));
|
||||
},
|
||||
);
|
||||
|
||||
export const selectActivitiesForCurrentCard = createSelector(
|
||||
orm,
|
||||
(state) => selectPath(state).cardId,
|
||||
(state) => selectCurrentUserId(state),
|
||||
({ Card }, id, currentUserId) => {
|
||||
if (!id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel
|
||||
.getFilteredOrderedInCardActivitiesQuerySet()
|
||||
.toModelArray()
|
||||
.map((activityModel) => ({
|
||||
...activityModel.ref,
|
||||
isPersisted: !isLocalId(activityModel.id),
|
||||
user: {
|
||||
...activityModel.user.ref,
|
||||
isCurrent: activityModel.user.id === currentUserId,
|
||||
},
|
||||
}));
|
||||
},
|
||||
);
|
||||
|
||||
export const selectNotificationIdsForCurrentCard = createSelector(
|
||||
orm,
|
||||
(state) => selectPath(state).cardId,
|
||||
({ Card }, id) => {
|
||||
if (!id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel
|
||||
.getUnreadNotificationsQuerySet()
|
||||
.toRefArray()
|
||||
.map((notification) => notification.id);
|
||||
},
|
||||
);
|
||||
|
||||
export default {
|
||||
makeSelectCardById,
|
||||
selectCardById,
|
||||
makeSelectCardIndexById,
|
||||
selectCardIndexById,
|
||||
makeSelectUsersByCardId,
|
||||
selectUsersByCardId,
|
||||
makeSelectLabelsByCardId,
|
||||
selectLabelsByCardId,
|
||||
makeSelectTaskIdsByCardId,
|
||||
selectTaskIdsByCardId,
|
||||
makeSelectTasksByCardId,
|
||||
selectTasksByCardId,
|
||||
makeSelectLastActivityIdByCardId,
|
||||
selectLastActivityIdByCardId,
|
||||
makeSelectNotificationsByCardId,
|
||||
selectNotificationsByCardId,
|
||||
makeSelectNotificationsTotalByCardId,
|
||||
selectNotificationsTotalByCardId,
|
||||
selectCurrentCard,
|
||||
selectUsersForCurrentCard,
|
||||
selectLabelsForCurrentCard,
|
||||
selectTasksForCurrentCard,
|
||||
selectAttachmentsForCurrentCard,
|
||||
selectActivitiesForCurrentCard,
|
||||
selectNotificationIdsForCurrentCard,
|
||||
};
|
||||
import { createSelector } from 'redux-orm';
|
||||
|
||||
import orm from '../orm';
|
||||
import { selectPath } from './router';
|
||||
import { selectCurrentUserId } from './users';
|
||||
import { isLocalId } from '../utils/local-id';
|
||||
|
||||
export const makeSelectCardById = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return {
|
||||
...cardModel.ref,
|
||||
coverUrl: cardModel.coverAttachment && cardModel.coverAttachment.coverUrl,
|
||||
isPersisted: !isLocalId(id),
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
export const selectCardById = makeSelectCardById();
|
||||
|
||||
export const makeSelectCardIndexById = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
const cardModels = cardModel.list.getFilteredOrderedCardsModelArray();
|
||||
return cardModels.findIndex((cardModelItem) => cardModelItem.id === cardModel.id);
|
||||
},
|
||||
);
|
||||
|
||||
export const selectCardIndexById = makeSelectCardIndexById();
|
||||
|
||||
export const makeSelectUsersByCardId = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.users.toRefArray();
|
||||
},
|
||||
);
|
||||
|
||||
export const selectUsersByCardId = makeSelectUsersByCardId();
|
||||
|
||||
export const makeSelectLabelsByCardId = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.labels.toRefArray();
|
||||
},
|
||||
);
|
||||
|
||||
export const selectLabelsByCardId = makeSelectLabelsByCardId();
|
||||
|
||||
export const makeSelectTaskIdsByCardId = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel
|
||||
.getOrderedTasksQuerySet()
|
||||
.toRefArray()
|
||||
.map((task) => task.id);
|
||||
},
|
||||
);
|
||||
|
||||
export const selectTaskIdsByCardId = makeSelectTaskIdsByCardId();
|
||||
|
||||
export const makeSelectTasksByCardId = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.getOrderedTasksQuerySet().toRefArray();
|
||||
},
|
||||
);
|
||||
|
||||
export const selectTasksByCardId = makeSelectTasksByCardId();
|
||||
|
||||
export const makeSelectLastActivityIdByCardId = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
const lastActivityModel = cardModel.getFilteredOrderedInCardActivitiesQuerySet().last();
|
||||
|
||||
return lastActivityModel && lastActivityModel.id;
|
||||
},
|
||||
);
|
||||
|
||||
export const selectLastActivityIdByCardId = makeSelectLastActivityIdByCardId();
|
||||
|
||||
export const makeSelectNotificationsByCardId = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.getUnreadNotificationsQuerySet().toRefArray();
|
||||
},
|
||||
);
|
||||
|
||||
export const selectNotificationsByCardId = makeSelectNotificationsByCardId();
|
||||
|
||||
export const makeSelectNotificationsTotalByCardId = () =>
|
||||
createSelector(
|
||||
orm,
|
||||
(_, id) => id,
|
||||
({ Card }, id) => {
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.getUnreadNotificationsQuerySet().count();
|
||||
},
|
||||
);
|
||||
|
||||
export const selectNotificationsTotalByCardId = makeSelectNotificationsTotalByCardId();
|
||||
|
||||
export const selectCurrentCard = createSelector(
|
||||
orm,
|
||||
(state) => selectPath(state).cardId,
|
||||
({ Card }, id) => {
|
||||
if (!id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.ref;
|
||||
},
|
||||
);
|
||||
|
||||
export const selectUsersForCurrentCard = createSelector(
|
||||
orm,
|
||||
(state) => selectPath(state).cardId,
|
||||
({ Card }, id) => {
|
||||
if (!id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.users.toRefArray();
|
||||
},
|
||||
);
|
||||
|
||||
export const selectLabelsForCurrentCard = createSelector(
|
||||
orm,
|
||||
(state) => selectPath(state).cardId,
|
||||
({ Card }, id) => {
|
||||
if (!id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel.labels.toRefArray();
|
||||
},
|
||||
);
|
||||
|
||||
export const selectTasksForCurrentCard = createSelector(
|
||||
orm,
|
||||
(state) => selectPath(state).cardId,
|
||||
({ Card }, id) => {
|
||||
if (!id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel
|
||||
.getOrderedTasksQuerySet()
|
||||
.toRefArray()
|
||||
.map((task) => ({
|
||||
...task,
|
||||
isPersisted: !isLocalId(task.id),
|
||||
}));
|
||||
},
|
||||
);
|
||||
|
||||
export const selectAttachmentsForCurrentCard = createSelector(
|
||||
orm,
|
||||
(state) => selectPath(state).cardId,
|
||||
({ Card }, id) => {
|
||||
if (!id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel
|
||||
.getOrderedAttachmentsQuerySet()
|
||||
.toRefArray()
|
||||
.map((attachment) => ({
|
||||
...attachment,
|
||||
isCover: attachment.id === cardModel.coverAttachmentId,
|
||||
isPersisted: !isLocalId(attachment.id),
|
||||
}));
|
||||
},
|
||||
);
|
||||
|
||||
export const selectActivitiesForCurrentCard = createSelector(
|
||||
orm,
|
||||
(state) => selectPath(state).cardId,
|
||||
(state) => selectCurrentUserId(state),
|
||||
({ Card }, id, currentUserId) => {
|
||||
if (!id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel
|
||||
.getFilteredOrderedInCardActivitiesQuerySet()
|
||||
.toModelArray()
|
||||
.map((activityModel) => ({
|
||||
...activityModel.ref,
|
||||
isPersisted: !isLocalId(activityModel.id),
|
||||
user: {
|
||||
...activityModel.user.ref,
|
||||
isCurrent: activityModel.user.id === currentUserId,
|
||||
},
|
||||
}));
|
||||
},
|
||||
);
|
||||
|
||||
export const selectNotificationIdsForCurrentCard = createSelector(
|
||||
orm,
|
||||
(state) => selectPath(state).cardId,
|
||||
({ Card }, id) => {
|
||||
if (!id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const cardModel = Card.withId(id);
|
||||
|
||||
if (!cardModel) {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
return cardModel
|
||||
.getUnreadNotificationsQuerySet()
|
||||
.toRefArray()
|
||||
.map((notification) => notification.id);
|
||||
},
|
||||
);
|
||||
|
||||
export default {
|
||||
makeSelectCardById,
|
||||
selectCardById,
|
||||
makeSelectCardIndexById,
|
||||
selectCardIndexById,
|
||||
makeSelectUsersByCardId,
|
||||
selectUsersByCardId,
|
||||
makeSelectLabelsByCardId,
|
||||
selectLabelsByCardId,
|
||||
makeSelectTaskIdsByCardId,
|
||||
selectTaskIdsByCardId,
|
||||
makeSelectTasksByCardId,
|
||||
selectTasksByCardId,
|
||||
makeSelectLastActivityIdByCardId,
|
||||
selectLastActivityIdByCardId,
|
||||
makeSelectNotificationsByCardId,
|
||||
selectNotificationsByCardId,
|
||||
makeSelectNotificationsTotalByCardId,
|
||||
selectNotificationsTotalByCardId,
|
||||
selectCurrentCard,
|
||||
selectUsersForCurrentCard,
|
||||
selectLabelsForCurrentCard,
|
||||
selectTasksForCurrentCard,
|
||||
selectAttachmentsForCurrentCard,
|
||||
selectActivitiesForCurrentCard,
|
||||
selectNotificationIdsForCurrentCard,
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,69 +1,61 @@
|
||||
{
|
||||
"name": "planka",
|
||||
"version": "0.0.1-beta.1",
|
||||
"private": true,
|
||||
"homepage": "https://plankanban.github.io/planka",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/plankanban/planka.git"
|
||||
},
|
||||
"license": "AGPL-3.0",
|
||||
"author": "Maksim Eltyshev",
|
||||
"scripts": {
|
||||
"client:build": "npm run build --prefix client",
|
||||
"client:lint": "npm run lint --prefix client",
|
||||
"client:start": "npm start --prefix client",
|
||||
"client:test": "npm test --prefix client",
|
||||
"docker:build": "docker build -t ghcr.io/plankanban/planka:local -f Dockerfile .",
|
||||
"docker:build:base": "docker build -t ghcr.io/plankanban/planka:base-local -f Dockerfile.base .",
|
||||
"postinstall": "(cd server && npm i && cd ../client && npm i)",
|
||||
"lint": "npm run server:lint && npm run client:lint",
|
||||
"prepare": "husky install",
|
||||
"server:console": "npm run console --prefix server",
|
||||
"server:db:init": "npm run db:init --prefix server",
|
||||
"server:db:migrate": "npm run db:migrate --prefix server",
|
||||
"server:db:seed": "npm run db:seed --prefix server",
|
||||
"server:lint": "npm run lint --prefix server",
|
||||
"server:start": "npm start --prefix server",
|
||||
"server:start:prod": "npm run start:prod --prefix server",
|
||||
"server:test": "npm test --prefix server",
|
||||
"start": "concurrently -n server,client \"npm run server:start\" \"npm run client:start\"",
|
||||
"test": "npm run server:test && npm run client:test"
|
||||
},
|
||||
"lint-staged": {
|
||||
"client/**/*.{js,jsx}": [
|
||||
"npm run client:lint"
|
||||
],
|
||||
"server/**/*.js": [
|
||||
"npm run server:lint"
|
||||
]
|
||||
},
|
||||
"prettier": {
|
||||
"printWidth": 100,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"plugins": [
|
||||
"prettier"
|
||||
],
|
||||
"extends": [
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"no-undef": "off",
|
||||
"prettier/prettier": "error"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"concurrently": "^8.2.2",
|
||||
"husky": "^8.0.3",
|
||||
"lint-staged": "^15.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.53.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-prettier": "^5.0.1",
|
||||
"prettier": "^3.1.0"
|
||||
}
|
||||
}
|
||||
{
|
||||
"name": "planka",
|
||||
"version": "0.0.1-beta.1",
|
||||
"private": true,
|
||||
"homepage": "https://plankanban.github.io/planka",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/plankanban/planka.git"
|
||||
},
|
||||
"license": "AGPL-3.0",
|
||||
"author": "Maksim Eltyshev",
|
||||
"scripts": {
|
||||
"client:build": "npm run build --prefix client",
|
||||
"client:lint": "npm run lint --prefix client",
|
||||
"client:start": "npm start --prefix client",
|
||||
"client:test": "npm test --prefix client",
|
||||
"docker:build": "docker build -t ghcr.io/plankanban/planka:local -f Dockerfile .",
|
||||
"docker:build:base": "docker build -t ghcr.io/plankanban/planka:base-local -f Dockerfile.base .",
|
||||
"postinstall": "(cd server && npm i && cd ../client && npm i)",
|
||||
"lint": "npm run server:lint && npm run client:lint",
|
||||
"prepare": "husky install",
|
||||
"server:console": "npm run console --prefix server",
|
||||
"server:db:init": "npm run db:init --prefix server",
|
||||
"server:db:migrate": "npm run db:migrate --prefix server",
|
||||
"server:db:seed": "npm run db:seed --prefix server",
|
||||
"server:lint": "npm run lint --prefix server",
|
||||
"server:start": "npm start --prefix server",
|
||||
"server:start:prod": "npm run start:prod --prefix server",
|
||||
"server:test": "npm test --prefix server",
|
||||
"start": "concurrently -n server,client \"npm run server:start\" \"npm run client:start\"",
|
||||
"test": "npm run server:test && npm run client:test"
|
||||
},
|
||||
"prettier": {
|
||||
"printWidth": 100,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"plugins": [
|
||||
"prettier"
|
||||
],
|
||||
"extends": [
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"no-undef": "off",
|
||||
"prettier/prettier": "error"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"concurrently": "^8.2.2",
|
||||
"husky": "^8.0.3",
|
||||
"lint-staged": "^15.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.53.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-prettier": "^5.0.1",
|
||||
"prettier": "^3.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,82 +1,82 @@
|
||||
const Errors = {
|
||||
NOT_ENOUGH_RIGHTS: {
|
||||
notEnoughRights: 'Not enough rights',
|
||||
},
|
||||
CARD_NOT_FOUND: {
|
||||
cardNotFound: 'Card not found',
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
inputs: {
|
||||
id: {
|
||||
type: 'string',
|
||||
regex: /^[0-9]+$/,
|
||||
required: true,
|
||||
},
|
||||
position: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
|
||||
exits: {
|
||||
notEnoughRights: {
|
||||
responseType: 'forbidden',
|
||||
},
|
||||
cardNotFound: {
|
||||
responseType: 'notFound',
|
||||
},
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
const { currentUser } = this.req;
|
||||
|
||||
const { card, list, board } = await sails.helpers.cards
|
||||
.getProjectPath(inputs.id)
|
||||
.intercept('pathNotFound', () => Errors.CARD_NOT_FOUND);
|
||||
|
||||
const boardMembership = await BoardMembership.findOne({
|
||||
boardId: card.boardId,
|
||||
userId: currentUser.id,
|
||||
});
|
||||
|
||||
if (!boardMembership) {
|
||||
throw Errors.CARD_NOT_FOUND; // Forbidden
|
||||
}
|
||||
|
||||
if (boardMembership.role !== BoardMembership.Roles.EDITOR) {
|
||||
throw Errors.NOT_ENOUGH_RIGHTS;
|
||||
}
|
||||
|
||||
const values = _.pick(inputs, ['position', 'name']);
|
||||
|
||||
const {
|
||||
card: nextCard,
|
||||
cardMemberships,
|
||||
cardLabels,
|
||||
tasks,
|
||||
} = await sails.helpers.cards.duplicateOne.with({
|
||||
board,
|
||||
list,
|
||||
record: card,
|
||||
values: {
|
||||
...values,
|
||||
creatorUser: currentUser,
|
||||
},
|
||||
request: this.req,
|
||||
});
|
||||
|
||||
return {
|
||||
item: nextCard,
|
||||
included: {
|
||||
cardMemberships,
|
||||
cardLabels,
|
||||
tasks,
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
const Errors = {
|
||||
NOT_ENOUGH_RIGHTS: {
|
||||
notEnoughRights: 'Not enough rights',
|
||||
},
|
||||
CARD_NOT_FOUND: {
|
||||
cardNotFound: 'Card not found',
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
inputs: {
|
||||
id: {
|
||||
type: 'string',
|
||||
regex: /^[0-9]+$/,
|
||||
required: true,
|
||||
},
|
||||
position: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
|
||||
exits: {
|
||||
notEnoughRights: {
|
||||
responseType: 'forbidden',
|
||||
},
|
||||
cardNotFound: {
|
||||
responseType: 'notFound',
|
||||
},
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
const { currentUser } = this.req;
|
||||
|
||||
const { card, list, board } = await sails.helpers.cards
|
||||
.getProjectPath(inputs.id)
|
||||
.intercept('pathNotFound', () => Errors.CARD_NOT_FOUND);
|
||||
|
||||
const boardMembership = await BoardMembership.findOne({
|
||||
boardId: card.boardId,
|
||||
userId: currentUser.id,
|
||||
});
|
||||
|
||||
if (!boardMembership) {
|
||||
throw Errors.CARD_NOT_FOUND; // Forbidden
|
||||
}
|
||||
|
||||
if (boardMembership.role !== BoardMembership.Roles.EDITOR) {
|
||||
throw Errors.NOT_ENOUGH_RIGHTS;
|
||||
}
|
||||
|
||||
const values = _.pick(inputs, ['position', 'name']);
|
||||
|
||||
const {
|
||||
card: nextCard,
|
||||
cardMemberships,
|
||||
cardLabels,
|
||||
tasks,
|
||||
} = await sails.helpers.cards.duplicateOne.with({
|
||||
board,
|
||||
list,
|
||||
record: card,
|
||||
values: {
|
||||
...values,
|
||||
creatorUser: currentUser,
|
||||
},
|
||||
request: this.req,
|
||||
});
|
||||
|
||||
return {
|
||||
item: nextCard,
|
||||
included: {
|
||||
cardMemberships,
|
||||
cardLabels,
|
||||
tasks,
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,156 +1,156 @@
|
||||
const POSITION_GAP = 65535; // TODO: move to config
|
||||
|
||||
module.exports = {
|
||||
inputs: {
|
||||
user: {
|
||||
type: 'ref',
|
||||
required: true,
|
||||
},
|
||||
board: {
|
||||
type: 'ref',
|
||||
required: true,
|
||||
},
|
||||
trelloBoard: {
|
||||
type: 'json',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
const trelloToPlankaLabels = {};
|
||||
|
||||
const getTrelloLists = () => inputs.trelloBoard.lists.filter((list) => !list.closed);
|
||||
|
||||
const getUsedTrelloLabels = () => {
|
||||
const result = {};
|
||||
inputs.trelloBoard.cards
|
||||
.map((card) => card.labels)
|
||||
.flat()
|
||||
.forEach((label) => {
|
||||
result[label.id] = label;
|
||||
});
|
||||
|
||||
return Object.values(result);
|
||||
};
|
||||
|
||||
const getTrelloCardsOfList = (listId) =>
|
||||
inputs.trelloBoard.cards.filter((card) => card.idList === listId && !card.closed);
|
||||
|
||||
const getAllTrelloCheckItemsOfCard = (cardId) =>
|
||||
inputs.trelloBoard.checklists
|
||||
.filter((checklist) => checklist.idCard === cardId)
|
||||
.map((checklist) => checklist.checkItems)
|
||||
.flat();
|
||||
|
||||
const getTrelloCommentsOfCard = (cardId) =>
|
||||
inputs.trelloBoard.actions.filter(
|
||||
(action) =>
|
||||
action.type === 'commentCard' &&
|
||||
action.data &&
|
||||
action.data.card &&
|
||||
action.data.card.id === cardId,
|
||||
);
|
||||
|
||||
const getPlankaLabelColor = (trelloLabelColor) =>
|
||||
Label.COLORS.find((color) => color.indexOf(trelloLabelColor) !== -1) || 'desert-sand';
|
||||
|
||||
const importCardLabels = async (plankaCard, trelloCard) => {
|
||||
return Promise.all(
|
||||
trelloCard.labels.map(async (trelloLabel) => {
|
||||
return CardLabel.create({
|
||||
cardId: plankaCard.id,
|
||||
labelId: trelloToPlankaLabels[trelloLabel.id].id,
|
||||
});
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const importTasks = async (plankaCard, trelloCard) => {
|
||||
// TODO find workaround for tasks/checklist mismapping, see issue trello2planka#5
|
||||
return Promise.all(
|
||||
getAllTrelloCheckItemsOfCard(trelloCard.id).map(async (trelloCheckItem) => {
|
||||
return Task.create({
|
||||
cardId: plankaCard.id,
|
||||
position: trelloCheckItem.pos,
|
||||
name: trelloCheckItem.name,
|
||||
isCompleted: trelloCheckItem.state === 'complete',
|
||||
}).fetch();
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const importComments = async (plankaCard, trelloCard) => {
|
||||
const trelloComments = getTrelloCommentsOfCard(trelloCard.id);
|
||||
trelloComments.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
|
||||
|
||||
return Promise.all(
|
||||
trelloComments.map(async (trelloComment) => {
|
||||
return Action.create({
|
||||
cardId: plankaCard.id,
|
||||
userId: inputs.user.id,
|
||||
type: 'commentCard',
|
||||
data: {
|
||||
text:
|
||||
`${trelloComment.data.text}\n\n---\n*Note: imported comment, originally posted by ` +
|
||||
`\n${trelloComment.memberCreator.fullName} (${trelloComment.memberCreator.username}) on ${trelloComment.date}*`,
|
||||
},
|
||||
}).fetch();
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const importCards = async (plankaList, trelloList) => {
|
||||
return Promise.all(
|
||||
getTrelloCardsOfList(trelloList.id).map(async (trelloCard) => {
|
||||
const plankaCard = await Card.create({
|
||||
boardId: inputs.board.id,
|
||||
listId: plankaList.id,
|
||||
creatorUserId: inputs.user.id,
|
||||
position: trelloCard.pos,
|
||||
name: trelloCard.name,
|
||||
description: trelloCard.desc || null,
|
||||
dueDate: trelloCard.due,
|
||||
}).fetch();
|
||||
|
||||
await importCardLabels(plankaCard, trelloCard);
|
||||
await importTasks(plankaCard, trelloCard);
|
||||
await importComments(plankaCard, trelloCard);
|
||||
|
||||
return plankaCard;
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const importLabels = async () => {
|
||||
return Promise.all(
|
||||
getUsedTrelloLabels().map(async (trelloLabel, index) => {
|
||||
const plankaLabel = await Label.create({
|
||||
boardId: inputs.board.id,
|
||||
position: POSITION_GAP * (index + 1),
|
||||
name: trelloLabel.name || null,
|
||||
color: getPlankaLabelColor(trelloLabel.color),
|
||||
}).fetch();
|
||||
|
||||
trelloToPlankaLabels[trelloLabel.id] = plankaLabel;
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const importLists = async () => {
|
||||
return Promise.all(
|
||||
getTrelloLists().map(async (trelloList) => {
|
||||
const plankaList = await List.create({
|
||||
boardId: inputs.board.id,
|
||||
name: trelloList.name,
|
||||
position: trelloList.pos,
|
||||
}).fetch();
|
||||
|
||||
return importCards(plankaList, trelloList);
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
await importLabels();
|
||||
await importLists();
|
||||
},
|
||||
};
|
||||
const POSITION_GAP = 65535; // TODO: move to config
|
||||
|
||||
module.exports = {
|
||||
inputs: {
|
||||
user: {
|
||||
type: 'ref',
|
||||
required: true,
|
||||
},
|
||||
board: {
|
||||
type: 'ref',
|
||||
required: true,
|
||||
},
|
||||
trelloBoard: {
|
||||
type: 'json',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
const trelloToPlankaLabels = {};
|
||||
|
||||
const getTrelloLists = () => inputs.trelloBoard.lists.filter((list) => !list.closed);
|
||||
|
||||
const getUsedTrelloLabels = () => {
|
||||
const result = {};
|
||||
inputs.trelloBoard.cards
|
||||
.map((card) => card.labels)
|
||||
.flat()
|
||||
.forEach((label) => {
|
||||
result[label.id] = label;
|
||||
});
|
||||
|
||||
return Object.values(result);
|
||||
};
|
||||
|
||||
const getTrelloCardsOfList = (listId) =>
|
||||
inputs.trelloBoard.cards.filter((card) => card.idList === listId && !card.closed);
|
||||
|
||||
const getAllTrelloCheckItemsOfCard = (cardId) =>
|
||||
inputs.trelloBoard.checklists
|
||||
.filter((checklist) => checklist.idCard === cardId)
|
||||
.map((checklist) => checklist.checkItems)
|
||||
.flat();
|
||||
|
||||
const getTrelloCommentsOfCard = (cardId) =>
|
||||
inputs.trelloBoard.actions.filter(
|
||||
(action) =>
|
||||
action.type === 'commentCard' &&
|
||||
action.data &&
|
||||
action.data.card &&
|
||||
action.data.card.id === cardId,
|
||||
);
|
||||
|
||||
const getPlankaLabelColor = (trelloLabelColor) =>
|
||||
Label.COLORS.find((color) => color.indexOf(trelloLabelColor) !== -1) || 'desert-sand';
|
||||
|
||||
const importCardLabels = async (plankaCard, trelloCard) => {
|
||||
return Promise.all(
|
||||
trelloCard.labels.map(async (trelloLabel) => {
|
||||
return CardLabel.create({
|
||||
cardId: plankaCard.id,
|
||||
labelId: trelloToPlankaLabels[trelloLabel.id].id,
|
||||
});
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const importTasks = async (plankaCard, trelloCard) => {
|
||||
// TODO find workaround for tasks/checklist mismapping, see issue trello2planka#5
|
||||
return Promise.all(
|
||||
getAllTrelloCheckItemsOfCard(trelloCard.id).map(async (trelloCheckItem) => {
|
||||
return Task.create({
|
||||
cardId: plankaCard.id,
|
||||
position: trelloCheckItem.pos,
|
||||
name: trelloCheckItem.name,
|
||||
isCompleted: trelloCheckItem.state === 'complete',
|
||||
}).fetch();
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const importComments = async (plankaCard, trelloCard) => {
|
||||
const trelloComments = getTrelloCommentsOfCard(trelloCard.id);
|
||||
trelloComments.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
|
||||
|
||||
return Promise.all(
|
||||
trelloComments.map(async (trelloComment) => {
|
||||
return Action.create({
|
||||
cardId: plankaCard.id,
|
||||
userId: inputs.user.id,
|
||||
type: 'commentCard',
|
||||
data: {
|
||||
text:
|
||||
`${trelloComment.data.text}\n\n---\n*Note: imported comment, originally posted by ` +
|
||||
`\n${trelloComment.memberCreator.fullName} (${trelloComment.memberCreator.username}) on ${trelloComment.date}*`,
|
||||
},
|
||||
}).fetch();
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const importCards = async (plankaList, trelloList) => {
|
||||
return Promise.all(
|
||||
getTrelloCardsOfList(trelloList.id).map(async (trelloCard) => {
|
||||
const plankaCard = await Card.create({
|
||||
boardId: inputs.board.id,
|
||||
listId: plankaList.id,
|
||||
creatorUserId: inputs.user.id,
|
||||
position: trelloCard.pos,
|
||||
name: trelloCard.name,
|
||||
description: trelloCard.desc || null,
|
||||
dueDate: trelloCard.due,
|
||||
}).fetch();
|
||||
|
||||
await importCardLabels(plankaCard, trelloCard);
|
||||
await importTasks(plankaCard, trelloCard);
|
||||
await importComments(plankaCard, trelloCard);
|
||||
|
||||
return plankaCard;
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const importLabels = async () => {
|
||||
return Promise.all(
|
||||
getUsedTrelloLabels().map(async (trelloLabel, index) => {
|
||||
const plankaLabel = await Label.create({
|
||||
boardId: inputs.board.id,
|
||||
position: POSITION_GAP * (index + 1),
|
||||
name: trelloLabel.name || null,
|
||||
color: getPlankaLabelColor(trelloLabel.color),
|
||||
}).fetch();
|
||||
|
||||
trelloToPlankaLabels[trelloLabel.id] = plankaLabel;
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const importLists = async () => {
|
||||
return Promise.all(
|
||||
getTrelloLists().map(async (trelloList) => {
|
||||
const plankaList = await List.create({
|
||||
boardId: inputs.board.id,
|
||||
name: trelloList.name,
|
||||
position: trelloList.pos,
|
||||
}).fetch();
|
||||
|
||||
return importCards(plankaList, trelloList);
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
await importLabels();
|
||||
await importLists();
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,144 +1,144 @@
|
||||
const valuesValidator = (value) => {
|
||||
if (!_.isPlainObject(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_.isUndefined(value.position) && !_.isFinite(value.position)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_.isPlainObject(value.creatorUser)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
inputs: {
|
||||
record: {
|
||||
type: 'ref',
|
||||
required: true,
|
||||
},
|
||||
values: {
|
||||
type: 'ref',
|
||||
custom: valuesValidator,
|
||||
required: true,
|
||||
},
|
||||
board: {
|
||||
type: 'ref',
|
||||
required: true,
|
||||
},
|
||||
list: {
|
||||
type: 'ref',
|
||||
required: true,
|
||||
},
|
||||
request: {
|
||||
type: 'ref',
|
||||
},
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
const { values } = inputs;
|
||||
|
||||
const cards = await sails.helpers.lists.getCards(inputs.record.listId);
|
||||
|
||||
const { position, repositions } = sails.helpers.utils.insertToPositionables(
|
||||
values.position,
|
||||
cards,
|
||||
);
|
||||
|
||||
repositions.forEach(async ({ id, position: nextPosition }) => {
|
||||
await Card.update({
|
||||
id,
|
||||
listId: inputs.record.listId,
|
||||
}).set({
|
||||
position: nextPosition,
|
||||
});
|
||||
|
||||
sails.sockets.broadcast(`board:${inputs.record.boardId}`, 'cardUpdate', {
|
||||
item: {
|
||||
id,
|
||||
position: nextPosition,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
const card = await Card.create({
|
||||
..._.pick(inputs.record, [
|
||||
'boardId',
|
||||
'listId',
|
||||
'name',
|
||||
'description',
|
||||
'dueDate',
|
||||
'stopwatch',
|
||||
]),
|
||||
...values,
|
||||
position,
|
||||
creatorUserId: values.creatorUser.id,
|
||||
}).fetch();
|
||||
|
||||
const cardMemberships = await sails.helpers.cards.getCardMemberships(inputs.record.id);
|
||||
const cardMembershipsValues = cardMemberships.map((cardMembership) => ({
|
||||
..._.pick(cardMembership, ['userId']),
|
||||
cardId: card.id,
|
||||
}));
|
||||
const nextCardMemberships = await CardMembership.createEach(cardMembershipsValues).fetch();
|
||||
|
||||
const cardLabels = await sails.helpers.cards.getCardLabels(inputs.record.id);
|
||||
const cardLabelsValues = cardLabels.map((cardLabel) => ({
|
||||
..._.pick(cardLabel, ['labelId']),
|
||||
cardId: card.id,
|
||||
}));
|
||||
const nextCardLabels = await CardLabel.createEach(cardLabelsValues).fetch();
|
||||
|
||||
const tasks = await sails.helpers.cards.getTasks(inputs.record.id);
|
||||
const tasksValues = tasks.map((task) => ({
|
||||
..._.pick(task, ['position', 'name', 'isCompleted']),
|
||||
cardId: card.id,
|
||||
}));
|
||||
const nextTasks = await Task.createEach(tasksValues).fetch();
|
||||
|
||||
sails.sockets.broadcast(
|
||||
`board:${card.boardId}`,
|
||||
'cardCreate',
|
||||
{
|
||||
item: card,
|
||||
},
|
||||
inputs.request,
|
||||
);
|
||||
|
||||
if (values.creatorUser.subscribeToOwnCards) {
|
||||
await CardSubscription.create({
|
||||
cardId: card.id,
|
||||
userId: card.creatorUserId,
|
||||
}).tolerate('E_UNIQUE');
|
||||
|
||||
sails.sockets.broadcast(`user:${card.creatorUserId}`, 'cardUpdate', {
|
||||
item: {
|
||||
id: card.id,
|
||||
isSubscribed: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
await sails.helpers.actions.createOne.with({
|
||||
values: {
|
||||
card,
|
||||
type: Action.Types.CREATE_CARD, // TODO: introduce separate type?
|
||||
data: {
|
||||
list: _.pick(inputs.list, ['id', 'name']),
|
||||
},
|
||||
user: values.creatorUser,
|
||||
},
|
||||
board: inputs.board,
|
||||
});
|
||||
|
||||
return {
|
||||
card,
|
||||
cardMemberships: nextCardMemberships,
|
||||
cardLabels: nextCardLabels,
|
||||
tasks: nextTasks,
|
||||
};
|
||||
},
|
||||
};
|
||||
const valuesValidator = (value) => {
|
||||
if (!_.isPlainObject(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_.isUndefined(value.position) && !_.isFinite(value.position)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_.isPlainObject(value.creatorUser)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
inputs: {
|
||||
record: {
|
||||
type: 'ref',
|
||||
required: true,
|
||||
},
|
||||
values: {
|
||||
type: 'ref',
|
||||
custom: valuesValidator,
|
||||
required: true,
|
||||
},
|
||||
board: {
|
||||
type: 'ref',
|
||||
required: true,
|
||||
},
|
||||
list: {
|
||||
type: 'ref',
|
||||
required: true,
|
||||
},
|
||||
request: {
|
||||
type: 'ref',
|
||||
},
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
const { values } = inputs;
|
||||
|
||||
const cards = await sails.helpers.lists.getCards(inputs.record.listId);
|
||||
|
||||
const { position, repositions } = sails.helpers.utils.insertToPositionables(
|
||||
values.position,
|
||||
cards,
|
||||
);
|
||||
|
||||
repositions.forEach(async ({ id, position: nextPosition }) => {
|
||||
await Card.update({
|
||||
id,
|
||||
listId: inputs.record.listId,
|
||||
}).set({
|
||||
position: nextPosition,
|
||||
});
|
||||
|
||||
sails.sockets.broadcast(`board:${inputs.record.boardId}`, 'cardUpdate', {
|
||||
item: {
|
||||
id,
|
||||
position: nextPosition,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
const card = await Card.create({
|
||||
..._.pick(inputs.record, [
|
||||
'boardId',
|
||||
'listId',
|
||||
'name',
|
||||
'description',
|
||||
'dueDate',
|
||||
'stopwatch',
|
||||
]),
|
||||
...values,
|
||||
position,
|
||||
creatorUserId: values.creatorUser.id,
|
||||
}).fetch();
|
||||
|
||||
const cardMemberships = await sails.helpers.cards.getCardMemberships(inputs.record.id);
|
||||
const cardMembershipsValues = cardMemberships.map((cardMembership) => ({
|
||||
..._.pick(cardMembership, ['userId']),
|
||||
cardId: card.id,
|
||||
}));
|
||||
const nextCardMemberships = await CardMembership.createEach(cardMembershipsValues).fetch();
|
||||
|
||||
const cardLabels = await sails.helpers.cards.getCardLabels(inputs.record.id);
|
||||
const cardLabelsValues = cardLabels.map((cardLabel) => ({
|
||||
..._.pick(cardLabel, ['labelId']),
|
||||
cardId: card.id,
|
||||
}));
|
||||
const nextCardLabels = await CardLabel.createEach(cardLabelsValues).fetch();
|
||||
|
||||
const tasks = await sails.helpers.cards.getTasks(inputs.record.id);
|
||||
const tasksValues = tasks.map((task) => ({
|
||||
..._.pick(task, ['position', 'name', 'isCompleted']),
|
||||
cardId: card.id,
|
||||
}));
|
||||
const nextTasks = await Task.createEach(tasksValues).fetch();
|
||||
|
||||
sails.sockets.broadcast(
|
||||
`board:${card.boardId}`,
|
||||
'cardCreate',
|
||||
{
|
||||
item: card,
|
||||
},
|
||||
inputs.request,
|
||||
);
|
||||
|
||||
if (values.creatorUser.subscribeToOwnCards) {
|
||||
await CardSubscription.create({
|
||||
cardId: card.id,
|
||||
userId: card.creatorUserId,
|
||||
}).tolerate('E_UNIQUE');
|
||||
|
||||
sails.sockets.broadcast(`user:${card.creatorUserId}`, 'cardUpdate', {
|
||||
item: {
|
||||
id: card.id,
|
||||
isSubscribed: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
await sails.helpers.actions.createOne.with({
|
||||
values: {
|
||||
card,
|
||||
type: Action.Types.CREATE_CARD, // TODO: introduce separate type?
|
||||
data: {
|
||||
list: _.pick(inputs.list, ['id', 'name']),
|
||||
},
|
||||
user: values.creatorUser,
|
||||
},
|
||||
board: inputs.board,
|
||||
});
|
||||
|
||||
return {
|
||||
card,
|
||||
cardMemberships: nextCardMemberships,
|
||||
cardLabels: nextCardLabels,
|
||||
tasks: nextTasks,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,97 +1,97 @@
|
||||
/**
|
||||
* Route Mappings
|
||||
* (sails.config.routes)
|
||||
*
|
||||
* Your routes tell Sails what to do each time it receives a request.
|
||||
*
|
||||
* For more information on configuring custom routes, check out:
|
||||
* https://sailsjs.com/anatomy/config/routes-js
|
||||
*/
|
||||
|
||||
module.exports.routes = {
|
||||
'GET /api/config': 'show-config',
|
||||
|
||||
'POST /api/access-tokens': 'access-tokens/create',
|
||||
'POST /api/access-tokens/exchange-using-oidc': 'access-tokens/exchange-using-oidc',
|
||||
'DELETE /api/access-tokens/me': 'access-tokens/delete',
|
||||
|
||||
'GET /api/users': 'users/index',
|
||||
'POST /api/users': 'users/create',
|
||||
'GET /api/users/:id': 'users/show',
|
||||
'PATCH /api/users/:id': 'users/update',
|
||||
'PATCH /api/users/:id/email': 'users/update-email',
|
||||
'PATCH /api/users/:id/password': 'users/update-password',
|
||||
'PATCH /api/users/:id/username': 'users/update-username',
|
||||
'POST /api/users/:id/avatar': 'users/update-avatar',
|
||||
'DELETE /api/users/:id': 'users/delete',
|
||||
|
||||
'GET /api/projects': 'projects/index',
|
||||
'POST /api/projects': 'projects/create',
|
||||
'GET /api/projects/:id': 'projects/show',
|
||||
'PATCH /api/projects/:id': 'projects/update',
|
||||
'POST /api/projects/:id/background-image': 'projects/update-background-image',
|
||||
'DELETE /api/projects/:id': 'projects/delete',
|
||||
|
||||
'POST /api/projects/:projectId/managers': 'project-managers/create',
|
||||
'DELETE /api/project-managers/:id': 'project-managers/delete',
|
||||
|
||||
'POST /api/projects/:projectId/boards': 'boards/create',
|
||||
'GET /api/boards/:id': 'boards/show',
|
||||
'PATCH /api/boards/:id': 'boards/update',
|
||||
'DELETE /api/boards/:id': 'boards/delete',
|
||||
|
||||
'POST /api/boards/:boardId/memberships': 'board-memberships/create',
|
||||
'PATCH /api/board-memberships/:id': 'board-memberships/update',
|
||||
'DELETE /api/board-memberships/:id': 'board-memberships/delete',
|
||||
|
||||
'POST /api/boards/:boardId/labels': 'labels/create',
|
||||
'PATCH /api/labels/:id': 'labels/update',
|
||||
'DELETE /api/labels/:id': 'labels/delete',
|
||||
|
||||
'POST /api/boards/:boardId/lists': 'lists/create',
|
||||
'PATCH /api/lists/:id': 'lists/update',
|
||||
'DELETE /api/lists/:id': 'lists/delete',
|
||||
|
||||
'POST /api/lists/:listId/cards': 'cards/create',
|
||||
'GET /api/cards/:id': 'cards/show',
|
||||
'PATCH /api/cards/:id': 'cards/update',
|
||||
'POST /api/cards/:id/duplicate': 'cards/duplicate',
|
||||
'DELETE /api/cards/:id': 'cards/delete',
|
||||
'POST /api/cards/:cardId/memberships': 'card-memberships/create',
|
||||
'DELETE /api/cards/:cardId/memberships': 'card-memberships/delete',
|
||||
'POST /api/cards/:cardId/labels': 'card-labels/create',
|
||||
'DELETE /api/cards/:cardId/labels/:labelId': 'card-labels/delete',
|
||||
|
||||
'POST /api/cards/:cardId/tasks': 'tasks/create',
|
||||
'PATCH /api/tasks/:id': 'tasks/update',
|
||||
'DELETE /api/tasks/:id': 'tasks/delete',
|
||||
|
||||
'POST /api/cards/:cardId/attachments': 'attachments/create',
|
||||
'PATCH /api/attachments/:id': 'attachments/update',
|
||||
'DELETE /api/attachments/:id': 'attachments/delete',
|
||||
|
||||
'GET /api/cards/:cardId/actions': 'actions/index',
|
||||
|
||||
'POST /api/cards/:cardId/comment-actions': 'comment-actions/create',
|
||||
'PATCH /api/comment-actions/:id': 'comment-actions/update',
|
||||
'DELETE /api/comment-actions/:id': 'comment-actions/delete',
|
||||
|
||||
'GET /api/notifications': 'notifications/index',
|
||||
'GET /api/notifications/:id': 'notifications/show',
|
||||
'PATCH /api/notifications/:ids': 'notifications/update',
|
||||
|
||||
'GET /attachments/:id/download/:filename': {
|
||||
action: 'attachments/download',
|
||||
skipAssets: false,
|
||||
},
|
||||
|
||||
'GET /attachments/:id/download/thumbnails/cover-256.:extension': {
|
||||
action: 'attachments/download-thumbnail',
|
||||
skipAssets: false,
|
||||
},
|
||||
|
||||
'GET /*': {
|
||||
view: 'index',
|
||||
skipAssets: true,
|
||||
},
|
||||
};
|
||||
/**
|
||||
* Route Mappings
|
||||
* (sails.config.routes)
|
||||
*
|
||||
* Your routes tell Sails what to do each time it receives a request.
|
||||
*
|
||||
* For more information on configuring custom routes, check out:
|
||||
* https://sailsjs.com/anatomy/config/routes-js
|
||||
*/
|
||||
|
||||
module.exports.routes = {
|
||||
'GET /api/config': 'show-config',
|
||||
|
||||
'POST /api/access-tokens': 'access-tokens/create',
|
||||
'POST /api/access-tokens/exchange-using-oidc': 'access-tokens/exchange-using-oidc',
|
||||
'DELETE /api/access-tokens/me': 'access-tokens/delete',
|
||||
|
||||
'GET /api/users': 'users/index',
|
||||
'POST /api/users': 'users/create',
|
||||
'GET /api/users/:id': 'users/show',
|
||||
'PATCH /api/users/:id': 'users/update',
|
||||
'PATCH /api/users/:id/email': 'users/update-email',
|
||||
'PATCH /api/users/:id/password': 'users/update-password',
|
||||
'PATCH /api/users/:id/username': 'users/update-username',
|
||||
'POST /api/users/:id/avatar': 'users/update-avatar',
|
||||
'DELETE /api/users/:id': 'users/delete',
|
||||
|
||||
'GET /api/projects': 'projects/index',
|
||||
'POST /api/projects': 'projects/create',
|
||||
'GET /api/projects/:id': 'projects/show',
|
||||
'PATCH /api/projects/:id': 'projects/update',
|
||||
'POST /api/projects/:id/background-image': 'projects/update-background-image',
|
||||
'DELETE /api/projects/:id': 'projects/delete',
|
||||
|
||||
'POST /api/projects/:projectId/managers': 'project-managers/create',
|
||||
'DELETE /api/project-managers/:id': 'project-managers/delete',
|
||||
|
||||
'POST /api/projects/:projectId/boards': 'boards/create',
|
||||
'GET /api/boards/:id': 'boards/show',
|
||||
'PATCH /api/boards/:id': 'boards/update',
|
||||
'DELETE /api/boards/:id': 'boards/delete',
|
||||
|
||||
'POST /api/boards/:boardId/memberships': 'board-memberships/create',
|
||||
'PATCH /api/board-memberships/:id': 'board-memberships/update',
|
||||
'DELETE /api/board-memberships/:id': 'board-memberships/delete',
|
||||
|
||||
'POST /api/boards/:boardId/labels': 'labels/create',
|
||||
'PATCH /api/labels/:id': 'labels/update',
|
||||
'DELETE /api/labels/:id': 'labels/delete',
|
||||
|
||||
'POST /api/boards/:boardId/lists': 'lists/create',
|
||||
'PATCH /api/lists/:id': 'lists/update',
|
||||
'DELETE /api/lists/:id': 'lists/delete',
|
||||
|
||||
'POST /api/lists/:listId/cards': 'cards/create',
|
||||
'GET /api/cards/:id': 'cards/show',
|
||||
'PATCH /api/cards/:id': 'cards/update',
|
||||
'POST /api/cards/:id/duplicate': 'cards/duplicate',
|
||||
'DELETE /api/cards/:id': 'cards/delete',
|
||||
'POST /api/cards/:cardId/memberships': 'card-memberships/create',
|
||||
'DELETE /api/cards/:cardId/memberships': 'card-memberships/delete',
|
||||
'POST /api/cards/:cardId/labels': 'card-labels/create',
|
||||
'DELETE /api/cards/:cardId/labels/:labelId': 'card-labels/delete',
|
||||
|
||||
'POST /api/cards/:cardId/tasks': 'tasks/create',
|
||||
'PATCH /api/tasks/:id': 'tasks/update',
|
||||
'DELETE /api/tasks/:id': 'tasks/delete',
|
||||
|
||||
'POST /api/cards/:cardId/attachments': 'attachments/create',
|
||||
'PATCH /api/attachments/:id': 'attachments/update',
|
||||
'DELETE /api/attachments/:id': 'attachments/delete',
|
||||
|
||||
'GET /api/cards/:cardId/actions': 'actions/index',
|
||||
|
||||
'POST /api/cards/:cardId/comment-actions': 'comment-actions/create',
|
||||
'PATCH /api/comment-actions/:id': 'comment-actions/update',
|
||||
'DELETE /api/comment-actions/:id': 'comment-actions/delete',
|
||||
|
||||
'GET /api/notifications': 'notifications/index',
|
||||
'GET /api/notifications/:id': 'notifications/show',
|
||||
'PATCH /api/notifications/:ids': 'notifications/update',
|
||||
|
||||
'GET /attachments/:id/download/:filename': {
|
||||
action: 'attachments/download',
|
||||
skipAssets: false,
|
||||
},
|
||||
|
||||
'GET /attachments/:id/download/thumbnails/cover-256.:extension': {
|
||||
action: 'attachments/download-thumbnail',
|
||||
skipAssets: false,
|
||||
},
|
||||
|
||||
'GET /*': {
|
||||
view: 'index',
|
||||
skipAssets: true,
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
module.exports.up = (knex) =>
|
||||
knex.schema.createTable('card_label', (table) => {
|
||||
/* Columns */
|
||||
|
||||
table.bigInteger('id').primary().defaultTo(knex.raw('next_id()'));
|
||||
|
||||
table.bigInteger('card_id').notNullable();
|
||||
table.bigInteger('label_id').notNullable();
|
||||
|
||||
table.timestamp('created_at', true);
|
||||
table.timestamp('updated_at', true);
|
||||
|
||||
/* Indexes */
|
||||
|
||||
table.unique(['card_id', 'label_id']);
|
||||
table.index('label_id');
|
||||
});
|
||||
|
||||
module.exports.down = (knex) => knex.schema.dropTable('card_label');
|
||||
module.exports.up = (knex) =>
|
||||
knex.schema.createTable('card_label', (table) => {
|
||||
/* Columns */
|
||||
|
||||
table.bigInteger('id').primary().defaultTo(knex.raw('next_id()'));
|
||||
|
||||
table.bigInteger('card_id').notNullable();
|
||||
table.bigInteger('label_id').notNullable();
|
||||
|
||||
table.timestamp('created_at', true);
|
||||
table.timestamp('updated_at', true);
|
||||
|
||||
/* Indexes */
|
||||
|
||||
table.unique(['card_id', 'label_id']);
|
||||
table.index('label_id');
|
||||
});
|
||||
|
||||
module.exports.down = (knex) => knex.schema.dropTable('card_label');
|
||||
|
||||
@ -1,44 +1,44 @@
|
||||
module.exports.up = async (knex) => {
|
||||
await knex.schema.createTable('identity_provider_user', (table) => {
|
||||
/* Columns */
|
||||
|
||||
table.bigInteger('id').primary().defaultTo(knex.raw('next_id()'));
|
||||
|
||||
table.bigInteger('user_id').notNullable();
|
||||
|
||||
table.text('issuer').notNullable();
|
||||
table.text('sub').notNullable();
|
||||
|
||||
table.timestamp('created_at', true);
|
||||
table.timestamp('updated_at', true);
|
||||
|
||||
/* Indexes */
|
||||
|
||||
table.unique(['issuer', 'sub']);
|
||||
table.index('user_id');
|
||||
});
|
||||
|
||||
await knex.schema.table('user_account', (table) => {
|
||||
/* Columns */
|
||||
|
||||
table.boolean('is_sso').notNullable().default(false);
|
||||
|
||||
/* Modifications */
|
||||
|
||||
table.setNullable('password');
|
||||
});
|
||||
|
||||
return knex.schema.alterTable('user_account', (table) => {
|
||||
table.boolean('is_sso').notNullable().alter();
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.down = async (knex) => {
|
||||
await knex.schema.dropTable('identity_provider_user');
|
||||
|
||||
return knex.schema.table('user_account', (table) => {
|
||||
table.dropColumn('is_sso');
|
||||
|
||||
table.dropNullable('password');
|
||||
});
|
||||
};
|
||||
module.exports.up = async (knex) => {
|
||||
await knex.schema.createTable('identity_provider_user', (table) => {
|
||||
/* Columns */
|
||||
|
||||
table.bigInteger('id').primary().defaultTo(knex.raw('next_id()'));
|
||||
|
||||
table.bigInteger('user_id').notNullable();
|
||||
|
||||
table.text('issuer').notNullable();
|
||||
table.text('sub').notNullable();
|
||||
|
||||
table.timestamp('created_at', true);
|
||||
table.timestamp('updated_at', true);
|
||||
|
||||
/* Indexes */
|
||||
|
||||
table.unique(['issuer', 'sub']);
|
||||
table.index('user_id');
|
||||
});
|
||||
|
||||
await knex.schema.table('user_account', (table) => {
|
||||
/* Columns */
|
||||
|
||||
table.boolean('is_sso').notNullable().default(false);
|
||||
|
||||
/* Modifications */
|
||||
|
||||
table.setNullable('password');
|
||||
});
|
||||
|
||||
return knex.schema.alterTable('user_account', (table) => {
|
||||
table.boolean('is_sso').notNullable().alter();
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.down = async (knex) => {
|
||||
await knex.schema.dropTable('identity_provider_user');
|
||||
|
||||
return knex.schema.table('user_account', (table) => {
|
||||
table.dropColumn('is_sso');
|
||||
|
||||
table.dropNullable('password');
|
||||
});
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue