Compare commits
33 Commits
v1.102.0
...
web/automa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
736b968eab | ||
|
|
d5d8426bda | ||
|
|
be4a783845 | ||
|
|
c30cd3b378 | ||
|
|
0d3cc28f45 | ||
|
|
f004487be0 | ||
|
|
21231d53a5 | ||
|
|
a99862120d | ||
|
|
776023b149 | ||
|
|
7d4187962a | ||
|
|
a93534fc3c | ||
|
|
cef84f6ced | ||
|
|
a2180a467d | ||
|
|
1e3dceea4d | ||
|
|
fd4514711f | ||
|
|
2dd7c13b88 | ||
|
|
40931b5668 | ||
|
|
25549b87c9 | ||
|
|
7ec62f12b5 | ||
|
|
caf76f0713 | ||
|
|
6778653825 | ||
|
|
c858b43717 | ||
|
|
6eb1b82541 | ||
|
|
71b6d8b569 | ||
|
|
3abfe3c99e | ||
|
|
171b6bb0a6 | ||
|
|
78c7ff855d | ||
|
|
57be9182d4 | ||
|
|
7e92ef9428 | ||
|
|
372fae20d9 | ||
|
|
16543a233b | ||
|
|
73b961f5fa | ||
|
|
e0d15c96f1 |
10
.github/workflows/build-mobile.yml
vendored
10
.github/workflows/build-mobile.yml
vendored
@@ -37,15 +37,15 @@ jobs:
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: "11.0.21+9"
|
||||
cache: "gradle"
|
||||
distribution: 'zulu'
|
||||
java-version: '17'
|
||||
cache: 'gradle'
|
||||
|
||||
- name: Setup Flutter SDK
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: "stable"
|
||||
flutter-version: "3.19.3"
|
||||
channel: 'stable'
|
||||
flutter-version: '3.19.3'
|
||||
cache: true
|
||||
|
||||
- name: Create the Keystore
|
||||
|
||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -208,7 +208,7 @@ jobs:
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: 'stable'
|
||||
flutter-version: '3.16.9'
|
||||
flutter-version: '3.19.3'
|
||||
- name: Run tests
|
||||
working-directory: ./mobile
|
||||
run: flutter test -j 1
|
||||
|
||||
2
cli/package-lock.json
generated
2
cli/package-lock.json
generated
@@ -47,7 +47,7 @@
|
||||
},
|
||||
"../open-api/typescript-sdk": {
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"dev": true,
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
|
||||
6
e2e/package-lock.json
generated
6
e2e/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "immich-e2e",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "immich-e2e",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"devDependencies": {
|
||||
"@immich/cli": "file:../cli",
|
||||
@@ -81,7 +81,7 @@
|
||||
},
|
||||
"../open-api/typescript-sdk": {
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"dev": true,
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich-e2e",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
|
||||
@@ -572,6 +572,22 @@ describe('/asset', () => {
|
||||
}
|
||||
|
||||
const tests = [
|
||||
{
|
||||
input: 'formats/avif/8bit-sRGB.avif',
|
||||
expected: {
|
||||
type: AssetTypeEnum.Image,
|
||||
originalFileName: '8bit-sRGB.avif',
|
||||
resized: true,
|
||||
exifInfo: {
|
||||
description: '',
|
||||
exifImageHeight: 1080,
|
||||
exifImageWidth: 1617,
|
||||
fileSizeInByte: 862_424,
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: 'formats/jpg/el_torcal_rocks.jpg',
|
||||
expected: {
|
||||
@@ -596,6 +612,22 @@ describe('/asset', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: 'formats/jxl/8bit-sRGB.jxl',
|
||||
expected: {
|
||||
type: AssetTypeEnum.Image,
|
||||
originalFileName: '8bit-sRGB.jxl',
|
||||
resized: true,
|
||||
exifInfo: {
|
||||
description: '',
|
||||
exifImageHeight: 1080,
|
||||
exifImageWidth: 1440,
|
||||
fileSizeInByte: 1_780_777,
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: 'formats/heic/IMG_2682.heic',
|
||||
expected: {
|
||||
@@ -681,6 +713,80 @@ describe('/asset', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: 'formats/raw/Panasonic/DMC-GH4/4_3.rw2',
|
||||
expected: {
|
||||
type: AssetTypeEnum.Image,
|
||||
originalFileName: '4_3.rw2',
|
||||
resized: true,
|
||||
fileCreatedAt: '2018-05-10T08:42:37.842Z',
|
||||
exifInfo: {
|
||||
make: 'Panasonic',
|
||||
model: 'DMC-GH4',
|
||||
exifImageHeight: 3456,
|
||||
exifImageWidth: 4608,
|
||||
exposureTime: '1/100',
|
||||
fNumber: 3.2,
|
||||
focalLength: 35,
|
||||
iso: 400,
|
||||
fileSizeInByte: 19_587_072,
|
||||
dateTimeOriginal: '2018-05-10T08:42:37.842Z',
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
orientation: '1',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: 'formats/raw/Sony/ILCE-6300/12bit-compressed-(3_2).arw',
|
||||
expected: {
|
||||
type: AssetTypeEnum.Image,
|
||||
originalFileName: '12bit-compressed-(3_2).arw',
|
||||
resized: true,
|
||||
fileCreatedAt: '2016-09-27T10:51:44.000Z',
|
||||
exifInfo: {
|
||||
make: 'SONY',
|
||||
model: 'ILCE-6300',
|
||||
exifImageHeight: 4024,
|
||||
exifImageWidth: 6048,
|
||||
exposureTime: '1/320',
|
||||
fNumber: 8,
|
||||
focalLength: 97,
|
||||
iso: 100,
|
||||
lensModel: 'E PZ 18-105mm F4 G OSS',
|
||||
fileSizeInByte: 25_001_984,
|
||||
dateTimeOriginal: '2016-09-27T10:51:44.000Z',
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
orientation: '1',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: 'formats/raw/Sony/ILCE-7M2/14bit-uncompressed-(3_2).arw',
|
||||
expected: {
|
||||
type: AssetTypeEnum.Image,
|
||||
originalFileName: '14bit-uncompressed-(3_2).arw',
|
||||
resized: true,
|
||||
fileCreatedAt: '2016-01-08T15:08:01.000Z',
|
||||
exifInfo: {
|
||||
make: 'SONY',
|
||||
model: 'ILCE-7M2',
|
||||
exifImageHeight: 4024,
|
||||
exifImageWidth: 6048,
|
||||
exposureTime: '1.3',
|
||||
fNumber: 22,
|
||||
focalLength: 25,
|
||||
iso: 100,
|
||||
lensModel: 'E 25mm F2',
|
||||
fileSizeInByte: 49_512_448,
|
||||
dateTimeOriginal: '2016-01-08T15:08:01.000Z',
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
orientation: '1',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
for (const { input, expected } of tests) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { LoginResponseDto, getServerConfig } from '@immich/sdk';
|
||||
import { LoginResponseDto } from '@immich/sdk';
|
||||
import { createUserDto } from 'src/fixtures';
|
||||
import { errorDto } from 'src/responses';
|
||||
import { app, utils } from 'src/utils';
|
||||
@@ -162,19 +162,4 @@ describe('/server-info', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /server-info/admin-onboarding', () => {
|
||||
it('should set admin onboarding', async () => {
|
||||
const config = await getServerConfig({});
|
||||
expect(config.isOnboarded).toBe(false);
|
||||
|
||||
const { status } = await request(app)
|
||||
.post('/server-info/admin-onboarding')
|
||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||
expect(status).toBe(204);
|
||||
|
||||
const newConfig = await getServerConfig({});
|
||||
expect(newConfig.isOnboarded).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
76
e2e/src/api/specs/system-metadata.e2e-spec.ts
Normal file
76
e2e/src/api/specs/system-metadata.e2e-spec.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { LoginResponseDto, getServerConfig } from '@immich/sdk';
|
||||
import { createUserDto } from 'src/fixtures';
|
||||
import { errorDto } from 'src/responses';
|
||||
import { app, utils } from 'src/utils';
|
||||
import request from 'supertest';
|
||||
import { beforeAll, describe, expect, it } from 'vitest';
|
||||
|
||||
describe('/server-info', () => {
|
||||
let admin: LoginResponseDto;
|
||||
let nonAdmin: LoginResponseDto;
|
||||
|
||||
beforeAll(async () => {
|
||||
await utils.resetDatabase();
|
||||
admin = await utils.adminSetup({ onboarding: false });
|
||||
nonAdmin = await utils.userSetup(admin.accessToken, createUserDto.user1);
|
||||
});
|
||||
|
||||
describe('POST /system-metadata/admin-onboarding', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(app).post('/system-metadata/admin-onboarding').send({ isOnboarded: true });
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorDto.unauthorized);
|
||||
});
|
||||
|
||||
it('should only work for admins', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.post('/system-metadata/admin-onboarding')
|
||||
.set('Authorization', `Bearer ${nonAdmin.accessToken}`)
|
||||
.send({ isOnboarded: true });
|
||||
expect(status).toBe(403);
|
||||
expect(body).toEqual(errorDto.forbidden);
|
||||
});
|
||||
|
||||
it('should set admin onboarding', async () => {
|
||||
const config = await getServerConfig({});
|
||||
expect(config.isOnboarded).toBe(false);
|
||||
|
||||
const { status } = await request(app)
|
||||
.post('/system-metadata/admin-onboarding')
|
||||
.set('Authorization', `Bearer ${admin.accessToken}`)
|
||||
.send({ isOnboarded: true });
|
||||
expect(status).toBe(204);
|
||||
|
||||
const newConfig = await getServerConfig({});
|
||||
expect(newConfig.isOnboarded).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /system-metadata/reverse-geocoding-state', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(app).get('/system-metadata/reverse-geocoding-state');
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorDto.unauthorized);
|
||||
});
|
||||
|
||||
it('should only work for admins', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.get('/system-metadata/reverse-geocoding-state')
|
||||
.set('Authorization', `Bearer ${nonAdmin.accessToken}`);
|
||||
expect(status).toBe(403);
|
||||
expect(body).toEqual(errorDto.forbidden);
|
||||
});
|
||||
|
||||
it('should get the reverse geocoding state', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.get('/system-metadata/reverse-geocoding-state')
|
||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||
|
||||
expect(status).toBe(200);
|
||||
expect(body).toEqual({
|
||||
lastUpdate: expect.any(String),
|
||||
lastImportFileName: 'cities500.txt',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -24,8 +24,8 @@ import {
|
||||
getConfigDefaults,
|
||||
login,
|
||||
searchMetadata,
|
||||
setAdminOnboarding,
|
||||
signUpAdmin,
|
||||
updateAdminOnboarding,
|
||||
updateConfig,
|
||||
validate,
|
||||
} from '@immich/sdk';
|
||||
@@ -264,7 +264,10 @@ export const utils = {
|
||||
await signUpAdmin({ signUpDto: signupDto.admin });
|
||||
const response = await login({ loginCredentialDto: loginDto.admin });
|
||||
if (options.onboarding) {
|
||||
await setAdminOnboarding({ headers: asBearerAuth(response.accessToken) });
|
||||
await updateAdminOnboarding(
|
||||
{ adminOnboardingUpdateDto: { isOnboarded: true } },
|
||||
{ headers: asBearerAuth(response.accessToken) },
|
||||
);
|
||||
}
|
||||
return response;
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "machine-learning"
|
||||
version = "1.102.0"
|
||||
version = "1.102.3"
|
||||
description = ""
|
||||
authors = ["Hau Tran <alex.tran1502@gmail.com>"]
|
||||
readme = "README.md"
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
plugins {
|
||||
id "com.android.application"
|
||||
id "kotlin-android"
|
||||
id "dev.flutter.flutter-gradle-plugin"
|
||||
id "kotlin-kapt"
|
||||
}
|
||||
|
||||
def localProperties = new Properties()
|
||||
def localPropertiesFile = rootProject.file('local.properties')
|
||||
if (localPropertiesFile.exists()) {
|
||||
localPropertiesFile.withReader('UTF-8') { reader ->
|
||||
localProperties.load(reader)
|
||||
}
|
||||
}
|
||||
|
||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||
if (flutterRoot == null) {
|
||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||
localPropertiesFile.withInputStream { localProperties.load(it) }
|
||||
}
|
||||
|
||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||
@@ -21,18 +21,12 @@ if (flutterVersionName == null) {
|
||||
flutterVersionName = '1.0'
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
|
||||
def keystoreProperties = new Properties()
|
||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||
keystorePropertiesFile.withInputStream { keystoreProperties.load(it) }
|
||||
}
|
||||
|
||||
|
||||
android {
|
||||
compileSdkVersion 34
|
||||
|
||||
@@ -50,7 +44,6 @@ android {
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "app.alextran.immich"
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 33
|
||||
@@ -88,6 +81,13 @@ flutter {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
def kotlin_version = '1.9.23'
|
||||
def kotlin_coroutines_version = '1.8.0'
|
||||
def work_version = '2.9.0'
|
||||
def concurrent_version = '1.1.0'
|
||||
def guava_version = '33.1.0-android'
|
||||
def glide_version = '4.16.0'
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||
implementation "androidx.work:work-runtime-ktx:$work_version"
|
||||
|
||||
@@ -276,7 +276,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
|
||||
private const val NOTIFICATION_CHANNEL_ERROR_ID = "immich/backgroundServiceError"
|
||||
private const val NOTIFICATION_DEFAULT_TITLE = "Immich"
|
||||
private const val NOTIFICATION_ID = 1
|
||||
private const val NOTIFICATION_ERROR_ID = 2
|
||||
private const val NOTIFICATION_ERROR_ID = 2
|
||||
private const val NOTIFICATION_DETAIL_ID = 3
|
||||
private const val ONE_MINUTE = 60000L
|
||||
|
||||
@@ -304,7 +304,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
|
||||
val workInfoList = workInfoFuture.get(1000, TimeUnit.MILLISECONDS)
|
||||
if (workInfoList != null) {
|
||||
for (workInfo in workInfoList) {
|
||||
if (workInfo.getState() == WorkInfo.State.ENQUEUED) {
|
||||
if (workInfo.state == WorkInfo.State.ENQUEUED) {
|
||||
val workRequest = buildWorkRequest(requireWifi, requireCharging)
|
||||
wm.enqueueUniqueWork(TASK_NAME_BACKUP, ExistingWorkPolicy.REPLACE, workRequest)
|
||||
Log.d(TAG, "updateBackupWorker updated BackupWorker constraints")
|
||||
@@ -346,7 +346,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
|
||||
.setRequiresBatteryNotLow(true)
|
||||
.setRequiresCharging(requireCharging)
|
||||
.build();
|
||||
|
||||
|
||||
val work = OneTimeWorkRequest.Builder(BackupWorker::class.java)
|
||||
.setConstraints(constraints)
|
||||
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, ONE_MINUTE, TimeUnit.MILLISECONDS)
|
||||
@@ -359,4 +359,4 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
|
||||
}
|
||||
}
|
||||
|
||||
private const val TAG = "BackupWorker"
|
||||
private const val TAG = "BackupWorker"
|
||||
|
||||
@@ -1,21 +1,3 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.8.20'
|
||||
ext.kotlin_coroutines_version = '1.7.1'
|
||||
ext.work_version = '2.7.1'
|
||||
ext.concurrent_version = '1.1.0'
|
||||
ext.guava_version = '33.0.0-android'
|
||||
ext.glide_version = '4.14.2'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.4.2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
@@ -34,3 +16,7 @@ subprojects {
|
||||
tasks.register("clean", Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
|
||||
tasks.named('wrapper') {
|
||||
distributionType = Wrapper.DistributionType.ALL
|
||||
}
|
||||
@@ -35,8 +35,8 @@ platform :android do
|
||||
task: 'bundle',
|
||||
build_type: 'Release',
|
||||
properties: {
|
||||
"android.injected.version.code" => 132,
|
||||
"android.injected.version.name" => "1.102.0",
|
||||
"android.injected.version.code" => 136,
|
||||
"android.injected.version.name" => "1.102.3",
|
||||
}
|
||||
)
|
||||
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000219">
|
||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000261">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="67.515419">
|
||||
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="32.48099">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="35.431743">
|
||||
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="30.236974">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
|
||||
distributionSha256Sum=6001aba9b2204d26fa25a5800bb9382cf3ee01ccb78fe77317b2872336eb2f80
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-all.zip
|
||||
distributionSha256Sum=fe696c020f241a5f69c30f763c5a7f38eec54b490db19cd2b0962dda420d7d12
|
||||
@@ -1,11 +1,26 @@
|
||||
include ':app'
|
||||
pluginManagement {
|
||||
def flutterSdkPath = {
|
||||
def properties = new Properties()
|
||||
file("local.properties").withInputStream { properties.load(it) }
|
||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||
return flutterSdkPath
|
||||
}()
|
||||
|
||||
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
|
||||
def properties = new Properties()
|
||||
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||
|
||||
assert localPropertiesFile.exists()
|
||||
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
|
||||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
id "com.android.application" version "7.4.2" apply false
|
||||
id "org.jetbrains.kotlin.android" version "1.9.23" apply false
|
||||
id "org.jetbrains.kotlin.kapt" version "1.9.23" apply false
|
||||
}
|
||||
|
||||
include ":app"
|
||||
|
||||
@@ -296,6 +296,7 @@
|
||||
"motion_photos_page_title": "Motion Photos",
|
||||
"multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping",
|
||||
"multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping",
|
||||
"no_assets_to_show" : "No assets to show",
|
||||
"notification_permission_dialog_cancel": "Cancel",
|
||||
"notification_permission_dialog_content": "To enable notifications, go to Settings and select allow.",
|
||||
"notification_permission_dialog_settings": "Settings",
|
||||
|
||||
@@ -296,6 +296,7 @@
|
||||
"motion_photos_page_title": "Photos avec mouvement",
|
||||
"multiselect_grid_edit_date_time_err_read_only": "Impossible de modifier la date d'un élément d'actif en lecture seule.",
|
||||
"multiselect_grid_edit_gps_err_read_only": "Impossible de modifier l'emplacement d'un élément en lecture seule.",
|
||||
"no_assets_to_show" : "Aucun élément à afficher",
|
||||
"notification_permission_dialog_cancel": "Annuler",
|
||||
"notification_permission_dialog_content": "Pour activer les notifications, allez dans Paramètres et sélectionnez Autoriser.",
|
||||
"notification_permission_dialog_settings": "Paramètres",
|
||||
@@ -509,5 +510,7 @@
|
||||
"version_announcement_overlay_title": "Nouvelle version serveur disponible \uD83C\uDF89",
|
||||
"viewer_remove_from_stack": "Retirer de la pile",
|
||||
"viewer_stack_use_as_main_asset": "Utiliser comme élément principal",
|
||||
"viewer_unstack": "Désempiler"
|
||||
"viewer_unstack": "Désempiler",
|
||||
"haptic_feedback_title": "Retour haptique",
|
||||
"haptic_feedback_switch": "Activer le retour haptique"
|
||||
}
|
||||
@@ -383,7 +383,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 147;
|
||||
CURRENT_PROJECT_VERSION = 150;
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@@ -525,7 +525,7 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 147;
|
||||
CURRENT_PROJECT_VERSION = 150;
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@@ -553,7 +553,7 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 147;
|
||||
CURRENT_PROJECT_VERSION = 150;
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
|
||||
@@ -58,11 +58,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.101.0</string>
|
||||
<string>1.102.2</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>147</string>
|
||||
<string>150</string>
|
||||
<key>FLTEnableImpeller</key>
|
||||
<true />
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
|
||||
@@ -19,7 +19,7 @@ platform :ios do
|
||||
desc "iOS Beta"
|
||||
lane :beta do
|
||||
increment_version_number(
|
||||
version_number: "1.102.0"
|
||||
version_number: "1.102.3"
|
||||
)
|
||||
increment_build_number(
|
||||
build_number: latest_testflight_build_number + 1,
|
||||
|
||||
@@ -5,32 +5,32 @@
|
||||
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000242">
|
||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000231">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="0.761829">
|
||||
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="0.155919">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="4.47461">
|
||||
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="4.252784">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="0.179512">
|
||||
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="0.210502">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="4: build_app" time="165.636347">
|
||||
<testcase classname="fastlane.lanes" name="4: build_app" time="175.813647">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="5: upload_to_testflight" time="77.651963">
|
||||
<testcase classname="fastlane.lanes" name="5: upload_to_testflight" time="73.512517">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ class MultiselectGrid extends HookConsumerWidget {
|
||||
const Center(child: ImmichLoadingIndicator());
|
||||
|
||||
Widget buildEmptyIndicator() =>
|
||||
emptyIndicator ?? const Center(child: Text("No assets to show"));
|
||||
emptyIndicator ?? Center(child: const Text("no_assets_to_show").tr());
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
|
||||
@@ -25,7 +25,6 @@ class SplashScreenPage extends HookConsumerWidget {
|
||||
void performLoggingIn() async {
|
||||
bool isSuccess = false;
|
||||
bool deviceIsOffline = false;
|
||||
|
||||
if (accessToken != null && serverUrl != null) {
|
||||
try {
|
||||
// Resolve API server endpoint from user provided serverUrl
|
||||
@@ -51,11 +50,15 @@ class SplashScreenPage extends HookConsumerWidget {
|
||||
offlineLogin: deviceIsOffline,
|
||||
);
|
||||
} catch (error, stackTrace) {
|
||||
ref.read(authenticationProvider.notifier).logout();
|
||||
|
||||
log.severe(
|
||||
'Cannot set success login info',
|
||||
error,
|
||||
stackTrace,
|
||||
);
|
||||
|
||||
context.pushRoute(const LoginRoute());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,11 +76,6 @@ class SplashScreenPage extends HookConsumerWidget {
|
||||
}
|
||||
context.replaceRoute(const TabControllerRoute());
|
||||
} else {
|
||||
log.severe(
|
||||
'Unable to login through offline or online methods - logging out completely',
|
||||
);
|
||||
|
||||
ref.read(authenticationProvider.notifier).logout();
|
||||
// User was unable to login through either offline or online methods
|
||||
context.replaceRoute(const LoginRoute());
|
||||
}
|
||||
|
||||
12
mobile/openapi/.openapi-generator/FILES
generated
12
mobile/openapi/.openapi-generator/FILES
generated
@@ -13,6 +13,7 @@ doc/ActivityCreateDto.md
|
||||
doc/ActivityResponseDto.md
|
||||
doc/ActivityStatisticsResponseDto.md
|
||||
doc/AddUsersDto.md
|
||||
doc/AdminOnboardingUpdateDto.md
|
||||
doc/AlbumApi.md
|
||||
doc/AlbumCountResponseDto.md
|
||||
doc/AlbumResponseDto.md
|
||||
@@ -69,6 +70,7 @@ doc/FaceApi.md
|
||||
doc/FaceDto.md
|
||||
doc/FileChecksumDto.md
|
||||
doc/FileChecksumResponseDto.md
|
||||
doc/FileReportApi.md
|
||||
doc/FileReportDto.md
|
||||
doc/FileReportFixDto.md
|
||||
doc/FileReportItemDto.md
|
||||
@@ -122,6 +124,7 @@ doc/QueueStatusDto.md
|
||||
doc/ReactionLevel.md
|
||||
doc/ReactionType.md
|
||||
doc/RecognitionConfig.md
|
||||
doc/ReverseGeocodingStateResponseDto.md
|
||||
doc/ScanLibraryDto.md
|
||||
doc/SearchAlbumResponseDto.md
|
||||
doc/SearchApi.md
|
||||
@@ -173,6 +176,7 @@ doc/SystemConfigTemplateStorageOptionDto.md
|
||||
doc/SystemConfigThemeDto.md
|
||||
doc/SystemConfigTrashDto.md
|
||||
doc/SystemConfigUserDto.md
|
||||
doc/SystemMetadataApi.md
|
||||
doc/TagApi.md
|
||||
doc/TagResponseDto.md
|
||||
doc/TagTypeEnum.md
|
||||
@@ -212,6 +216,7 @@ lib/api/audit_api.dart
|
||||
lib/api/authentication_api.dart
|
||||
lib/api/download_api.dart
|
||||
lib/api/face_api.dart
|
||||
lib/api/file_report_api.dart
|
||||
lib/api/job_api.dart
|
||||
lib/api/library_api.dart
|
||||
lib/api/memory_api.dart
|
||||
@@ -224,6 +229,7 @@ lib/api/sessions_api.dart
|
||||
lib/api/shared_link_api.dart
|
||||
lib/api/sync_api.dart
|
||||
lib/api/system_config_api.dart
|
||||
lib/api/system_metadata_api.dart
|
||||
lib/api/tag_api.dart
|
||||
lib/api/timeline_api.dart
|
||||
lib/api/trash_api.dart
|
||||
@@ -240,6 +246,7 @@ lib/model/activity_create_dto.dart
|
||||
lib/model/activity_response_dto.dart
|
||||
lib/model/activity_statistics_response_dto.dart
|
||||
lib/model/add_users_dto.dart
|
||||
lib/model/admin_onboarding_update_dto.dart
|
||||
lib/model/album_count_response_dto.dart
|
||||
lib/model/album_response_dto.dart
|
||||
lib/model/all_job_status_response_dto.dart
|
||||
@@ -341,6 +348,7 @@ lib/model/queue_status_dto.dart
|
||||
lib/model/reaction_level.dart
|
||||
lib/model/reaction_type.dart
|
||||
lib/model/recognition_config.dart
|
||||
lib/model/reverse_geocoding_state_response_dto.dart
|
||||
lib/model/scan_library_dto.dart
|
||||
lib/model/search_album_response_dto.dart
|
||||
lib/model/search_asset_response_dto.dart
|
||||
@@ -417,6 +425,7 @@ test/activity_create_dto_test.dart
|
||||
test/activity_response_dto_test.dart
|
||||
test/activity_statistics_response_dto_test.dart
|
||||
test/add_users_dto_test.dart
|
||||
test/admin_onboarding_update_dto_test.dart
|
||||
test/album_api_test.dart
|
||||
test/album_count_response_dto_test.dart
|
||||
test/album_response_dto_test.dart
|
||||
@@ -478,6 +487,7 @@ test/face_api_test.dart
|
||||
test/face_dto_test.dart
|
||||
test/file_checksum_dto_test.dart
|
||||
test/file_checksum_response_dto_test.dart
|
||||
test/file_report_api_test.dart
|
||||
test/file_report_dto_test.dart
|
||||
test/file_report_fix_dto_test.dart
|
||||
test/file_report_item_dto_test.dart
|
||||
@@ -531,6 +541,7 @@ test/queue_status_dto_test.dart
|
||||
test/reaction_level_test.dart
|
||||
test/reaction_type_test.dart
|
||||
test/recognition_config_test.dart
|
||||
test/reverse_geocoding_state_response_dto_test.dart
|
||||
test/scan_library_dto_test.dart
|
||||
test/search_album_response_dto_test.dart
|
||||
test/search_api_test.dart
|
||||
@@ -582,6 +593,7 @@ test/system_config_template_storage_option_dto_test.dart
|
||||
test/system_config_theme_dto_test.dart
|
||||
test/system_config_trash_dto_test.dart
|
||||
test/system_config_user_dto_test.dart
|
||||
test/system_metadata_api_test.dart
|
||||
test/tag_api_test.dart
|
||||
test/tag_response_dto_test.dart
|
||||
test/tag_type_enum_test.dart
|
||||
|
||||
14
mobile/openapi/README.md
generated
14
mobile/openapi/README.md
generated
@@ -3,7 +3,7 @@ Immich API
|
||||
|
||||
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
- API version: 1.102.0
|
||||
- API version: 1.102.3
|
||||
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
||||
|
||||
## Requirements
|
||||
@@ -112,10 +112,7 @@ Class | Method | HTTP request | Description
|
||||
*AssetApi* | [**updateAssets**](doc//AssetApi.md#updateassets) | **PUT** /asset |
|
||||
*AssetApi* | [**updateStackParent**](doc//AssetApi.md#updatestackparent) | **PUT** /asset/stack/parent |
|
||||
*AssetApi* | [**uploadFile**](doc//AssetApi.md#uploadfile) | **POST** /asset/upload |
|
||||
*AuditApi* | [**fixAuditFiles**](doc//AuditApi.md#fixauditfiles) | **POST** /audit/file-report/fix |
|
||||
*AuditApi* | [**getAuditDeletes**](doc//AuditApi.md#getauditdeletes) | **GET** /audit/deletes |
|
||||
*AuditApi* | [**getAuditFiles**](doc//AuditApi.md#getauditfiles) | **GET** /audit/file-report |
|
||||
*AuditApi* | [**getFileChecksums**](doc//AuditApi.md#getfilechecksums) | **POST** /audit/file-report/checksum |
|
||||
*AuthenticationApi* | [**changePassword**](doc//AuthenticationApi.md#changepassword) | **POST** /auth/change-password |
|
||||
*AuthenticationApi* | [**login**](doc//AuthenticationApi.md#login) | **POST** /auth/login |
|
||||
*AuthenticationApi* | [**logout**](doc//AuthenticationApi.md#logout) | **POST** /auth/logout |
|
||||
@@ -126,6 +123,9 @@ Class | Method | HTTP request | Description
|
||||
*DownloadApi* | [**getDownloadInfo**](doc//DownloadApi.md#getdownloadinfo) | **POST** /download/info |
|
||||
*FaceApi* | [**getFaces**](doc//FaceApi.md#getfaces) | **GET** /face |
|
||||
*FaceApi* | [**reassignFacesById**](doc//FaceApi.md#reassignfacesbyid) | **PUT** /face/{id} |
|
||||
*FileReportApi* | [**fixAuditFiles**](doc//FileReportApi.md#fixauditfiles) | **POST** /report/fix |
|
||||
*FileReportApi* | [**getAuditFiles**](doc//FileReportApi.md#getauditfiles) | **GET** /report |
|
||||
*FileReportApi* | [**getFileChecksums**](doc//FileReportApi.md#getfilechecksums) | **POST** /report/checksum |
|
||||
*JobApi* | [**getAllJobsStatus**](doc//JobApi.md#getalljobsstatus) | **GET** /jobs |
|
||||
*JobApi* | [**sendJobCommand**](doc//JobApi.md#sendjobcommand) | **PUT** /jobs/{id} |
|
||||
*LibraryApi* | [**createLibrary**](doc//LibraryApi.md#createlibrary) | **POST** /library |
|
||||
@@ -179,7 +179,6 @@ Class | Method | HTTP request | Description
|
||||
*ServerInfoApi* | [**getSupportedMediaTypes**](doc//ServerInfoApi.md#getsupportedmediatypes) | **GET** /server-info/media-types |
|
||||
*ServerInfoApi* | [**getTheme**](doc//ServerInfoApi.md#gettheme) | **GET** /server-info/theme |
|
||||
*ServerInfoApi* | [**pingServer**](doc//ServerInfoApi.md#pingserver) | **GET** /server-info/ping |
|
||||
*ServerInfoApi* | [**setAdminOnboarding**](doc//ServerInfoApi.md#setadminonboarding) | **POST** /server-info/admin-onboarding |
|
||||
*SessionsApi* | [**deleteAllSessions**](doc//SessionsApi.md#deleteallsessions) | **DELETE** /sessions |
|
||||
*SessionsApi* | [**deleteSession**](doc//SessionsApi.md#deletesession) | **DELETE** /sessions/{id} |
|
||||
*SessionsApi* | [**getSessions**](doc//SessionsApi.md#getsessions) | **GET** /sessions |
|
||||
@@ -198,6 +197,9 @@ Class | Method | HTTP request | Description
|
||||
*SystemConfigApi* | [**getMapStyle**](doc//SystemConfigApi.md#getmapstyle) | **GET** /system-config/map/style.json |
|
||||
*SystemConfigApi* | [**getStorageTemplateOptions**](doc//SystemConfigApi.md#getstoragetemplateoptions) | **GET** /system-config/storage-template-options |
|
||||
*SystemConfigApi* | [**updateConfig**](doc//SystemConfigApi.md#updateconfig) | **PUT** /system-config |
|
||||
*SystemMetadataApi* | [**getAdminOnboarding**](doc//SystemMetadataApi.md#getadminonboarding) | **GET** /system-metadata/admin-onboarding |
|
||||
*SystemMetadataApi* | [**getReverseGeocodingState**](doc//SystemMetadataApi.md#getreversegeocodingstate) | **GET** /system-metadata/reverse-geocoding-state |
|
||||
*SystemMetadataApi* | [**updateAdminOnboarding**](doc//SystemMetadataApi.md#updateadminonboarding) | **POST** /system-metadata/admin-onboarding |
|
||||
*TagApi* | [**createTag**](doc//TagApi.md#createtag) | **POST** /tag |
|
||||
*TagApi* | [**deleteTag**](doc//TagApi.md#deletetag) | **DELETE** /tag/{id} |
|
||||
*TagApi* | [**getAllTags**](doc//TagApi.md#getalltags) | **GET** /tag |
|
||||
@@ -233,6 +235,7 @@ Class | Method | HTTP request | Description
|
||||
- [ActivityResponseDto](doc//ActivityResponseDto.md)
|
||||
- [ActivityStatisticsResponseDto](doc//ActivityStatisticsResponseDto.md)
|
||||
- [AddUsersDto](doc//AddUsersDto.md)
|
||||
- [AdminOnboardingUpdateDto](doc//AdminOnboardingUpdateDto.md)
|
||||
- [AlbumCountResponseDto](doc//AlbumCountResponseDto.md)
|
||||
- [AlbumResponseDto](doc//AlbumResponseDto.md)
|
||||
- [AllJobStatusResponseDto](doc//AllJobStatusResponseDto.md)
|
||||
@@ -330,6 +333,7 @@ Class | Method | HTTP request | Description
|
||||
- [ReactionLevel](doc//ReactionLevel.md)
|
||||
- [ReactionType](doc//ReactionType.md)
|
||||
- [RecognitionConfig](doc//RecognitionConfig.md)
|
||||
- [ReverseGeocodingStateResponseDto](doc//ReverseGeocodingStateResponseDto.md)
|
||||
- [ScanLibraryDto](doc//ScanLibraryDto.md)
|
||||
- [SearchAlbumResponseDto](doc//SearchAlbumResponseDto.md)
|
||||
- [SearchAssetResponseDto](doc//SearchAssetResponseDto.md)
|
||||
|
||||
15
mobile/openapi/doc/AdminOnboardingUpdateDto.md
generated
Normal file
15
mobile/openapi/doc/AdminOnboardingUpdateDto.md
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
# openapi.model.AdminOnboardingUpdateDto
|
||||
|
||||
## Load the model package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**isOnboarded** | **bool** | |
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
163
mobile/openapi/doc/AuditApi.md
generated
163
mobile/openapi/doc/AuditApi.md
generated
@@ -9,66 +9,9 @@ All URIs are relative to */api*
|
||||
|
||||
Method | HTTP request | Description
|
||||
------------- | ------------- | -------------
|
||||
[**fixAuditFiles**](AuditApi.md#fixauditfiles) | **POST** /audit/file-report/fix |
|
||||
[**getAuditDeletes**](AuditApi.md#getauditdeletes) | **GET** /audit/deletes |
|
||||
[**getAuditFiles**](AuditApi.md#getauditfiles) | **GET** /audit/file-report |
|
||||
[**getFileChecksums**](AuditApi.md#getfilechecksums) | **POST** /audit/file-report/checksum |
|
||||
|
||||
|
||||
# **fixAuditFiles**
|
||||
> fixAuditFiles(fileReportFixDto)
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = AuditApi();
|
||||
final fileReportFixDto = FileReportFixDto(); // FileReportFixDto |
|
||||
|
||||
try {
|
||||
api_instance.fixAuditFiles(fileReportFixDto);
|
||||
} catch (e) {
|
||||
print('Exception when calling AuditApi->fixAuditFiles: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**fileReportFixDto** | [**FileReportFixDto**](FileReportFixDto.md)| |
|
||||
|
||||
### Return type
|
||||
|
||||
void (empty response body)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: application/json
|
||||
- **Accept**: Not defined
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **getAuditDeletes**
|
||||
> AuditDeletesResponseDto getAuditDeletes(after, entityType, userId)
|
||||
|
||||
@@ -128,109 +71,3 @@ Name | Type | Description | Notes
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **getAuditFiles**
|
||||
> FileReportDto getAuditFiles()
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = AuditApi();
|
||||
|
||||
try {
|
||||
final result = api_instance.getAuditFiles();
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling AuditApi->getAuditFiles: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
This endpoint does not need any parameter.
|
||||
|
||||
### Return type
|
||||
|
||||
[**FileReportDto**](FileReportDto.md)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: Not defined
|
||||
- **Accept**: application/json
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **getFileChecksums**
|
||||
> List<FileChecksumResponseDto> getFileChecksums(fileChecksumDto)
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = AuditApi();
|
||||
final fileChecksumDto = FileChecksumDto(); // FileChecksumDto |
|
||||
|
||||
try {
|
||||
final result = api_instance.getFileChecksums(fileChecksumDto);
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling AuditApi->getFileChecksums: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**fileChecksumDto** | [**FileChecksumDto**](FileChecksumDto.md)| |
|
||||
|
||||
### Return type
|
||||
|
||||
[**List<FileChecksumResponseDto>**](FileChecksumResponseDto.md)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: application/json
|
||||
- **Accept**: application/json
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
176
mobile/openapi/doc/FileReportApi.md
generated
Normal file
176
mobile/openapi/doc/FileReportApi.md
generated
Normal file
@@ -0,0 +1,176 @@
|
||||
# openapi.api.FileReportApi
|
||||
|
||||
## Load the API package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
All URIs are relative to */api*
|
||||
|
||||
Method | HTTP request | Description
|
||||
------------- | ------------- | -------------
|
||||
[**fixAuditFiles**](FileReportApi.md#fixauditfiles) | **POST** /report/fix |
|
||||
[**getAuditFiles**](FileReportApi.md#getauditfiles) | **GET** /report |
|
||||
[**getFileChecksums**](FileReportApi.md#getfilechecksums) | **POST** /report/checksum |
|
||||
|
||||
|
||||
# **fixAuditFiles**
|
||||
> fixAuditFiles(fileReportFixDto)
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = FileReportApi();
|
||||
final fileReportFixDto = FileReportFixDto(); // FileReportFixDto |
|
||||
|
||||
try {
|
||||
api_instance.fixAuditFiles(fileReportFixDto);
|
||||
} catch (e) {
|
||||
print('Exception when calling FileReportApi->fixAuditFiles: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**fileReportFixDto** | [**FileReportFixDto**](FileReportFixDto.md)| |
|
||||
|
||||
### Return type
|
||||
|
||||
void (empty response body)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: application/json
|
||||
- **Accept**: Not defined
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **getAuditFiles**
|
||||
> FileReportDto getAuditFiles()
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = FileReportApi();
|
||||
|
||||
try {
|
||||
final result = api_instance.getAuditFiles();
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling FileReportApi->getAuditFiles: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
This endpoint does not need any parameter.
|
||||
|
||||
### Return type
|
||||
|
||||
[**FileReportDto**](FileReportDto.md)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: Not defined
|
||||
- **Accept**: application/json
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **getFileChecksums**
|
||||
> List<FileChecksumResponseDto> getFileChecksums(fileChecksumDto)
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = FileReportApi();
|
||||
final fileChecksumDto = FileChecksumDto(); // FileChecksumDto |
|
||||
|
||||
try {
|
||||
final result = api_instance.getFileChecksums(fileChecksumDto);
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling FileReportApi->getFileChecksums: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**fileChecksumDto** | [**FileChecksumDto**](FileChecksumDto.md)| |
|
||||
|
||||
### Return type
|
||||
|
||||
[**List<FileChecksumResponseDto>**](FileChecksumResponseDto.md)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: application/json
|
||||
- **Accept**: application/json
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
16
mobile/openapi/doc/ReverseGeocodingStateResponseDto.md
generated
Normal file
16
mobile/openapi/doc/ReverseGeocodingStateResponseDto.md
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
# openapi.model.ReverseGeocodingStateResponseDto
|
||||
|
||||
## Load the model package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**lastImportFileName** | **String** | |
|
||||
**lastUpdate** | **String** | |
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
51
mobile/openapi/doc/ServerInfoApi.md
generated
51
mobile/openapi/doc/ServerInfoApi.md
generated
@@ -17,7 +17,6 @@ Method | HTTP request | Description
|
||||
[**getSupportedMediaTypes**](ServerInfoApi.md#getsupportedmediatypes) | **GET** /server-info/media-types |
|
||||
[**getTheme**](ServerInfoApi.md#gettheme) | **GET** /server-info/theme |
|
||||
[**pingServer**](ServerInfoApi.md#pingserver) | **GET** /server-info/ping |
|
||||
[**setAdminOnboarding**](ServerInfoApi.md#setadminonboarding) | **POST** /server-info/admin-onboarding |
|
||||
|
||||
|
||||
# **getServerConfig**
|
||||
@@ -344,53 +343,3 @@ No authorization required
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **setAdminOnboarding**
|
||||
> setAdminOnboarding()
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = ServerInfoApi();
|
||||
|
||||
try {
|
||||
api_instance.setAdminOnboarding();
|
||||
} catch (e) {
|
||||
print('Exception when calling ServerInfoApi->setAdminOnboarding: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
This endpoint does not need any parameter.
|
||||
|
||||
### Return type
|
||||
|
||||
void (empty response body)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: Not defined
|
||||
- **Accept**: Not defined
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
172
mobile/openapi/doc/SystemMetadataApi.md
generated
Normal file
172
mobile/openapi/doc/SystemMetadataApi.md
generated
Normal file
@@ -0,0 +1,172 @@
|
||||
# openapi.api.SystemMetadataApi
|
||||
|
||||
## Load the API package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
All URIs are relative to */api*
|
||||
|
||||
Method | HTTP request | Description
|
||||
------------- | ------------- | -------------
|
||||
[**getAdminOnboarding**](SystemMetadataApi.md#getadminonboarding) | **GET** /system-metadata/admin-onboarding |
|
||||
[**getReverseGeocodingState**](SystemMetadataApi.md#getreversegeocodingstate) | **GET** /system-metadata/reverse-geocoding-state |
|
||||
[**updateAdminOnboarding**](SystemMetadataApi.md#updateadminonboarding) | **POST** /system-metadata/admin-onboarding |
|
||||
|
||||
|
||||
# **getAdminOnboarding**
|
||||
> AdminOnboardingUpdateDto getAdminOnboarding()
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = SystemMetadataApi();
|
||||
|
||||
try {
|
||||
final result = api_instance.getAdminOnboarding();
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling SystemMetadataApi->getAdminOnboarding: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
This endpoint does not need any parameter.
|
||||
|
||||
### Return type
|
||||
|
||||
[**AdminOnboardingUpdateDto**](AdminOnboardingUpdateDto.md)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: Not defined
|
||||
- **Accept**: application/json
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **getReverseGeocodingState**
|
||||
> ReverseGeocodingStateResponseDto getReverseGeocodingState()
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = SystemMetadataApi();
|
||||
|
||||
try {
|
||||
final result = api_instance.getReverseGeocodingState();
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling SystemMetadataApi->getReverseGeocodingState: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
This endpoint does not need any parameter.
|
||||
|
||||
### Return type
|
||||
|
||||
[**ReverseGeocodingStateResponseDto**](ReverseGeocodingStateResponseDto.md)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: Not defined
|
||||
- **Accept**: application/json
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **updateAdminOnboarding**
|
||||
> updateAdminOnboarding(adminOnboardingUpdateDto)
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = SystemMetadataApi();
|
||||
final adminOnboardingUpdateDto = AdminOnboardingUpdateDto(); // AdminOnboardingUpdateDto |
|
||||
|
||||
try {
|
||||
api_instance.updateAdminOnboarding(adminOnboardingUpdateDto);
|
||||
} catch (e) {
|
||||
print('Exception when calling SystemMetadataApi->updateAdminOnboarding: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**adminOnboardingUpdateDto** | [**AdminOnboardingUpdateDto**](AdminOnboardingUpdateDto.md)| |
|
||||
|
||||
### Return type
|
||||
|
||||
void (empty response body)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: application/json
|
||||
- **Accept**: Not defined
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
4
mobile/openapi/lib/api.dart
generated
4
mobile/openapi/lib/api.dart
generated
@@ -37,6 +37,7 @@ part 'api/audit_api.dart';
|
||||
part 'api/authentication_api.dart';
|
||||
part 'api/download_api.dart';
|
||||
part 'api/face_api.dart';
|
||||
part 'api/file_report_api.dart';
|
||||
part 'api/job_api.dart';
|
||||
part 'api/library_api.dart';
|
||||
part 'api/memory_api.dart';
|
||||
@@ -49,6 +50,7 @@ part 'api/sessions_api.dart';
|
||||
part 'api/shared_link_api.dart';
|
||||
part 'api/sync_api.dart';
|
||||
part 'api/system_config_api.dart';
|
||||
part 'api/system_metadata_api.dart';
|
||||
part 'api/tag_api.dart';
|
||||
part 'api/timeline_api.dart';
|
||||
part 'api/trash_api.dart';
|
||||
@@ -62,6 +64,7 @@ part 'model/activity_create_dto.dart';
|
||||
part 'model/activity_response_dto.dart';
|
||||
part 'model/activity_statistics_response_dto.dart';
|
||||
part 'model/add_users_dto.dart';
|
||||
part 'model/admin_onboarding_update_dto.dart';
|
||||
part 'model/album_count_response_dto.dart';
|
||||
part 'model/album_response_dto.dart';
|
||||
part 'model/all_job_status_response_dto.dart';
|
||||
@@ -159,6 +162,7 @@ part 'model/queue_status_dto.dart';
|
||||
part 'model/reaction_level.dart';
|
||||
part 'model/reaction_type.dart';
|
||||
part 'model/recognition_config.dart';
|
||||
part 'model/reverse_geocoding_state_response_dto.dart';
|
||||
part 'model/scan_library_dto.dart';
|
||||
part 'model/search_album_response_dto.dart';
|
||||
part 'model/search_asset_response_dto.dart';
|
||||
|
||||
130
mobile/openapi/lib/api/audit_api.dart
generated
130
mobile/openapi/lib/api/audit_api.dart
generated
@@ -16,45 +16,6 @@ class AuditApi {
|
||||
|
||||
final ApiClient apiClient;
|
||||
|
||||
/// Performs an HTTP 'POST /audit/file-report/fix' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [FileReportFixDto] fileReportFixDto (required):
|
||||
Future<Response> fixAuditFilesWithHttpInfo(FileReportFixDto fileReportFixDto,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/audit/file-report/fix';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody = fileReportFixDto;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>['application/json'];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'POST',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [FileReportFixDto] fileReportFixDto (required):
|
||||
Future<void> fixAuditFiles(FileReportFixDto fileReportFixDto,) async {
|
||||
final response = await fixAuditFilesWithHttpInfo(fileReportFixDto,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'GET /audit/deletes' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
@@ -115,95 +76,4 @@ class AuditApi {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'GET /audit/file-report' operation and returns the [Response].
|
||||
Future<Response> getAuditFilesWithHttpInfo() async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/audit/file-report';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'GET',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
Future<FileReportDto?> getAuditFiles() async {
|
||||
final response = await getAuditFilesWithHttpInfo();
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'FileReportDto',) as FileReportDto;
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'POST /audit/file-report/checksum' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [FileChecksumDto] fileChecksumDto (required):
|
||||
Future<Response> getFileChecksumsWithHttpInfo(FileChecksumDto fileChecksumDto,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/audit/file-report/checksum';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody = fileChecksumDto;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>['application/json'];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'POST',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [FileChecksumDto] fileChecksumDto (required):
|
||||
Future<List<FileChecksumResponseDto>?> getFileChecksums(FileChecksumDto fileChecksumDto,) async {
|
||||
final response = await getFileChecksumsWithHttpInfo(fileChecksumDto,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
final responseBody = await _decodeBodyBytes(response);
|
||||
return (await apiClient.deserializeAsync(responseBody, 'List<FileChecksumResponseDto>') as List)
|
||||
.cast<FileChecksumResponseDto>()
|
||||
.toList(growable: false);
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
148
mobile/openapi/lib/api/file_report_api.dart
generated
Normal file
148
mobile/openapi/lib/api/file_report_api.dart
generated
Normal file
@@ -0,0 +1,148 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class FileReportApi {
|
||||
FileReportApi([ApiClient? apiClient]) : apiClient = apiClient ?? defaultApiClient;
|
||||
|
||||
final ApiClient apiClient;
|
||||
|
||||
/// Performs an HTTP 'POST /report/fix' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [FileReportFixDto] fileReportFixDto (required):
|
||||
Future<Response> fixAuditFilesWithHttpInfo(FileReportFixDto fileReportFixDto,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/report/fix';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody = fileReportFixDto;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>['application/json'];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'POST',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [FileReportFixDto] fileReportFixDto (required):
|
||||
Future<void> fixAuditFiles(FileReportFixDto fileReportFixDto,) async {
|
||||
final response = await fixAuditFilesWithHttpInfo(fileReportFixDto,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'GET /report' operation and returns the [Response].
|
||||
Future<Response> getAuditFilesWithHttpInfo() async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/report';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'GET',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
Future<FileReportDto?> getAuditFiles() async {
|
||||
final response = await getAuditFilesWithHttpInfo();
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'FileReportDto',) as FileReportDto;
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'POST /report/checksum' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [FileChecksumDto] fileChecksumDto (required):
|
||||
Future<Response> getFileChecksumsWithHttpInfo(FileChecksumDto fileChecksumDto,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/report/checksum';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody = fileChecksumDto;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>['application/json'];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'POST',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [FileChecksumDto] fileChecksumDto (required):
|
||||
Future<List<FileChecksumResponseDto>?> getFileChecksums(FileChecksumDto fileChecksumDto,) async {
|
||||
final response = await getFileChecksumsWithHttpInfo(fileChecksumDto,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
final responseBody = await _decodeBodyBytes(response);
|
||||
return (await apiClient.deserializeAsync(responseBody, 'List<FileChecksumResponseDto>') as List)
|
||||
.cast<FileChecksumResponseDto>()
|
||||
.toList(growable: false);
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
33
mobile/openapi/lib/api/server_info_api.dart
generated
33
mobile/openapi/lib/api/server_info_api.dart
generated
@@ -343,37 +343,4 @@ class ServerInfoApi {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'POST /server-info/admin-onboarding' operation and returns the [Response].
|
||||
Future<Response> setAdminOnboardingWithHttpInfo() async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/server-info/admin-onboarding';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'POST',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> setAdminOnboarding() async {
|
||||
final response = await setAdminOnboardingWithHttpInfo();
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
139
mobile/openapi/lib/api/system_metadata_api.dart
generated
Normal file
139
mobile/openapi/lib/api/system_metadata_api.dart
generated
Normal file
@@ -0,0 +1,139 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class SystemMetadataApi {
|
||||
SystemMetadataApi([ApiClient? apiClient]) : apiClient = apiClient ?? defaultApiClient;
|
||||
|
||||
final ApiClient apiClient;
|
||||
|
||||
/// Performs an HTTP 'GET /system-metadata/admin-onboarding' operation and returns the [Response].
|
||||
Future<Response> getAdminOnboardingWithHttpInfo() async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/system-metadata/admin-onboarding';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'GET',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
Future<AdminOnboardingUpdateDto?> getAdminOnboarding() async {
|
||||
final response = await getAdminOnboardingWithHttpInfo();
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'AdminOnboardingUpdateDto',) as AdminOnboardingUpdateDto;
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'GET /system-metadata/reverse-geocoding-state' operation and returns the [Response].
|
||||
Future<Response> getReverseGeocodingStateWithHttpInfo() async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/system-metadata/reverse-geocoding-state';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'GET',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
Future<ReverseGeocodingStateResponseDto?> getReverseGeocodingState() async {
|
||||
final response = await getReverseGeocodingStateWithHttpInfo();
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'ReverseGeocodingStateResponseDto',) as ReverseGeocodingStateResponseDto;
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'POST /system-metadata/admin-onboarding' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [AdminOnboardingUpdateDto] adminOnboardingUpdateDto (required):
|
||||
Future<Response> updateAdminOnboardingWithHttpInfo(AdminOnboardingUpdateDto adminOnboardingUpdateDto,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/system-metadata/admin-onboarding';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody = adminOnboardingUpdateDto;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>['application/json'];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'POST',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [AdminOnboardingUpdateDto] adminOnboardingUpdateDto (required):
|
||||
Future<void> updateAdminOnboarding(AdminOnboardingUpdateDto adminOnboardingUpdateDto,) async {
|
||||
final response = await updateAdminOnboardingWithHttpInfo(adminOnboardingUpdateDto,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
}
|
||||
}
|
||||
4
mobile/openapi/lib/api_client.dart
generated
4
mobile/openapi/lib/api_client.dart
generated
@@ -198,6 +198,8 @@ class ApiClient {
|
||||
return ActivityStatisticsResponseDto.fromJson(value);
|
||||
case 'AddUsersDto':
|
||||
return AddUsersDto.fromJson(value);
|
||||
case 'AdminOnboardingUpdateDto':
|
||||
return AdminOnboardingUpdateDto.fromJson(value);
|
||||
case 'AlbumCountResponseDto':
|
||||
return AlbumCountResponseDto.fromJson(value);
|
||||
case 'AlbumResponseDto':
|
||||
@@ -392,6 +394,8 @@ class ApiClient {
|
||||
return ReactionTypeTypeTransformer().decode(value);
|
||||
case 'RecognitionConfig':
|
||||
return RecognitionConfig.fromJson(value);
|
||||
case 'ReverseGeocodingStateResponseDto':
|
||||
return ReverseGeocodingStateResponseDto.fromJson(value);
|
||||
case 'ScanLibraryDto':
|
||||
return ScanLibraryDto.fromJson(value);
|
||||
case 'SearchAlbumResponseDto':
|
||||
|
||||
98
mobile/openapi/lib/model/admin_onboarding_update_dto.dart
generated
Normal file
98
mobile/openapi/lib/model/admin_onboarding_update_dto.dart
generated
Normal file
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class AdminOnboardingUpdateDto {
|
||||
/// Returns a new [AdminOnboardingUpdateDto] instance.
|
||||
AdminOnboardingUpdateDto({
|
||||
required this.isOnboarded,
|
||||
});
|
||||
|
||||
bool isOnboarded;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is AdminOnboardingUpdateDto &&
|
||||
other.isOnboarded == isOnboarded;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(isOnboarded.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'AdminOnboardingUpdateDto[isOnboarded=$isOnboarded]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'isOnboarded'] = this.isOnboarded;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [AdminOnboardingUpdateDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static AdminOnboardingUpdateDto? fromJson(dynamic value) {
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return AdminOnboardingUpdateDto(
|
||||
isOnboarded: mapValueOfType<bool>(json, r'isOnboarded')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<AdminOnboardingUpdateDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <AdminOnboardingUpdateDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = AdminOnboardingUpdateDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, AdminOnboardingUpdateDto> mapFromJson(dynamic json) {
|
||||
final map = <String, AdminOnboardingUpdateDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = AdminOnboardingUpdateDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of AdminOnboardingUpdateDto-objects as value to a dart map
|
||||
static Map<String, List<AdminOnboardingUpdateDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<AdminOnboardingUpdateDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = AdminOnboardingUpdateDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'isOnboarded',
|
||||
};
|
||||
}
|
||||
|
||||
114
mobile/openapi/lib/model/reverse_geocoding_state_response_dto.dart
generated
Normal file
114
mobile/openapi/lib/model/reverse_geocoding_state_response_dto.dart
generated
Normal file
@@ -0,0 +1,114 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class ReverseGeocodingStateResponseDto {
|
||||
/// Returns a new [ReverseGeocodingStateResponseDto] instance.
|
||||
ReverseGeocodingStateResponseDto({
|
||||
required this.lastImportFileName,
|
||||
required this.lastUpdate,
|
||||
});
|
||||
|
||||
String? lastImportFileName;
|
||||
|
||||
String? lastUpdate;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is ReverseGeocodingStateResponseDto &&
|
||||
other.lastImportFileName == lastImportFileName &&
|
||||
other.lastUpdate == lastUpdate;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(lastImportFileName == null ? 0 : lastImportFileName!.hashCode) +
|
||||
(lastUpdate == null ? 0 : lastUpdate!.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'ReverseGeocodingStateResponseDto[lastImportFileName=$lastImportFileName, lastUpdate=$lastUpdate]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
if (this.lastImportFileName != null) {
|
||||
json[r'lastImportFileName'] = this.lastImportFileName;
|
||||
} else {
|
||||
// json[r'lastImportFileName'] = null;
|
||||
}
|
||||
if (this.lastUpdate != null) {
|
||||
json[r'lastUpdate'] = this.lastUpdate;
|
||||
} else {
|
||||
// json[r'lastUpdate'] = null;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [ReverseGeocodingStateResponseDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static ReverseGeocodingStateResponseDto? fromJson(dynamic value) {
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return ReverseGeocodingStateResponseDto(
|
||||
lastImportFileName: mapValueOfType<String>(json, r'lastImportFileName'),
|
||||
lastUpdate: mapValueOfType<String>(json, r'lastUpdate'),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<ReverseGeocodingStateResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <ReverseGeocodingStateResponseDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = ReverseGeocodingStateResponseDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, ReverseGeocodingStateResponseDto> mapFromJson(dynamic json) {
|
||||
final map = <String, ReverseGeocodingStateResponseDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = ReverseGeocodingStateResponseDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of ReverseGeocodingStateResponseDto-objects as value to a dart map
|
||||
static Map<String, List<ReverseGeocodingStateResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<ReverseGeocodingStateResponseDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = ReverseGeocodingStateResponseDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'lastImportFileName',
|
||||
'lastUpdate',
|
||||
};
|
||||
}
|
||||
|
||||
27
mobile/openapi/test/admin_onboarding_update_dto_test.dart
generated
Normal file
27
mobile/openapi/test/admin_onboarding_update_dto_test.dart
generated
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// tests for AdminOnboardingUpdateDto
|
||||
void main() {
|
||||
// final instance = AdminOnboardingUpdateDto();
|
||||
|
||||
group('test AdminOnboardingUpdateDto', () {
|
||||
// bool isOnboarded
|
||||
test('to test the property `isOnboarded`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
15
mobile/openapi/test/audit_api_test.dart
generated
15
mobile/openapi/test/audit_api_test.dart
generated
@@ -17,25 +17,10 @@ void main() {
|
||||
// final instance = AuditApi();
|
||||
|
||||
group('tests for AuditApi', () {
|
||||
//Future fixAuditFiles(FileReportFixDto fileReportFixDto) async
|
||||
test('test fixAuditFiles', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future<AuditDeletesResponseDto> getAuditDeletes(DateTime after, EntityType entityType, { String userId }) async
|
||||
test('test getAuditDeletes', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future<FileReportDto> getAuditFiles() async
|
||||
test('test getAuditFiles', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future<List<FileChecksumResponseDto>> getFileChecksums(FileChecksumDto fileChecksumDto) async
|
||||
test('test getFileChecksums', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
36
mobile/openapi/test/file_report_api_test.dart
generated
Normal file
36
mobile/openapi/test/file_report_api_test.dart
generated
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
|
||||
/// tests for FileReportApi
|
||||
void main() {
|
||||
// final instance = FileReportApi();
|
||||
|
||||
group('tests for FileReportApi', () {
|
||||
//Future fixAuditFiles(FileReportFixDto fileReportFixDto) async
|
||||
test('test fixAuditFiles', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future<FileReportDto> getAuditFiles() async
|
||||
test('test getAuditFiles', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future<List<FileChecksumResponseDto>> getFileChecksums(FileChecksumDto fileChecksumDto) async
|
||||
test('test getFileChecksums', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
32
mobile/openapi/test/reverse_geocoding_state_response_dto_test.dart
generated
Normal file
32
mobile/openapi/test/reverse_geocoding_state_response_dto_test.dart
generated
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// tests for ReverseGeocodingStateResponseDto
|
||||
void main() {
|
||||
// final instance = ReverseGeocodingStateResponseDto();
|
||||
|
||||
group('test ReverseGeocodingStateResponseDto', () {
|
||||
// String lastImportFileName
|
||||
test('to test the property `lastImportFileName`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// String lastUpdate
|
||||
test('to test the property `lastUpdate`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
5
mobile/openapi/test/server_info_api_test.dart
generated
5
mobile/openapi/test/server_info_api_test.dart
generated
@@ -57,10 +57,5 @@ void main() {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future setAdminOnboarding() async
|
||||
test('test setAdminOnboarding', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
36
mobile/openapi/test/system_metadata_api_test.dart
generated
Normal file
36
mobile/openapi/test/system_metadata_api_test.dart
generated
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
|
||||
/// tests for SystemMetadataApi
|
||||
void main() {
|
||||
// final instance = SystemMetadataApi();
|
||||
|
||||
group('tests for SystemMetadataApi', () {
|
||||
//Future<AdminOnboardingUpdateDto> getAdminOnboarding() async
|
||||
test('test getAdminOnboarding', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future<ReverseGeocodingStateResponseDto> getReverseGeocodingState() async
|
||||
test('test getReverseGeocodingState', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future updateAdminOnboarding(AdminOnboardingUpdateDto adminOnboardingUpdateDto) async
|
||||
test('test updateAdminOnboarding', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
@@ -1804,5 +1804,5 @@ packages:
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.2.0 <4.0.0"
|
||||
dart: ">=3.3.0 <4.0.0"
|
||||
flutter: ">=3.16.0"
|
||||
|
||||
@@ -2,10 +2,10 @@ name: immich_mobile
|
||||
description: Immich - selfhosted backup media file on mobile phone
|
||||
|
||||
publish_to: 'none'
|
||||
version: 1.102.0+132
|
||||
version: 1.102.3+136
|
||||
|
||||
environment:
|
||||
sdk: '>=3.0.0 <4.0.0'
|
||||
sdk: '>=3.3.0 <4.0.0'
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
|
||||
@@ -2345,118 +2345,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/audit/file-report": {
|
||||
"get": {
|
||||
"operationId": "getAuditFiles",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/FileReportDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Audit"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/audit/file-report/checksum": {
|
||||
"post": {
|
||||
"operationId": "getFileChecksums",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/FileChecksumDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/FileChecksumResponseDto"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Audit"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/audit/file-report/fix": {
|
||||
"post": {
|
||||
"operationId": "fixAuditFiles",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/FileReportFixDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Audit"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/auth/admin-sign-up": {
|
||||
"post": {
|
||||
"operationId": "signUpAdmin",
|
||||
@@ -4429,6 +4317,118 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/report": {
|
||||
"get": {
|
||||
"operationId": "getAuditFiles",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/FileReportDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"File Report"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/report/checksum": {
|
||||
"post": {
|
||||
"operationId": "getFileChecksums",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/FileChecksumDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/FileChecksumResponseDto"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"File Report"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/report/fix": {
|
||||
"post": {
|
||||
"operationId": "fixAuditFiles",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/FileReportFixDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"File Report"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/search": {
|
||||
"get": {
|
||||
"deprecated": true,
|
||||
@@ -4908,31 +4908,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/server-info/admin-onboarding": {
|
||||
"post": {
|
||||
"operationId": "setAdminOnboarding",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Server Info"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/server-info/config": {
|
||||
"get": {
|
||||
"operationId": "getServerConfig",
|
||||
@@ -5885,6 +5860,103 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/system-metadata/admin-onboarding": {
|
||||
"get": {
|
||||
"operationId": "getAdminOnboarding",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/AdminOnboardingUpdateDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"System Metadata"
|
||||
]
|
||||
},
|
||||
"post": {
|
||||
"operationId": "updateAdminOnboarding",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/AdminOnboardingUpdateDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"System Metadata"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/system-metadata/reverse-geocoding-state": {
|
||||
"get": {
|
||||
"operationId": "getReverseGeocodingState",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ReverseGeocodingStateResponseDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"System Metadata"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/tag": {
|
||||
"get": {
|
||||
"operationId": "getAllTags",
|
||||
@@ -7006,7 +7078,7 @@
|
||||
"info": {
|
||||
"title": "Immich",
|
||||
"description": "Immich API",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"contact": {}
|
||||
},
|
||||
"tags": [],
|
||||
@@ -7180,6 +7252,17 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"AdminOnboardingUpdateDto": {
|
||||
"properties": {
|
||||
"isOnboarded": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"isOnboarded"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"AlbumCountResponseDto": {
|
||||
"properties": {
|
||||
"notShared": {
|
||||
@@ -9618,6 +9701,23 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ReverseGeocodingStateResponseDto": {
|
||||
"properties": {
|
||||
"lastImportFileName": {
|
||||
"nullable": true,
|
||||
"type": "string"
|
||||
},
|
||||
"lastUpdate": {
|
||||
"nullable": true,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"lastImportFileName",
|
||||
"lastUpdate"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ScanLibraryDto": {
|
||||
"properties": {
|
||||
"refreshAllFiles": {
|
||||
|
||||
4
open-api/typescript-sdk/package-lock.json
generated
4
open-api/typescript-sdk/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
"@oazapfts/runtime": "^1.0.2"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"description": "Auto-generated TypeScript SDK for the Immich API",
|
||||
"type": "module",
|
||||
"main": "./build/index.js",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Immich
|
||||
* 1.102.0
|
||||
* 1.102.3
|
||||
* DO NOT MODIFY - This file has been generated using oazapfts.
|
||||
* See https://www.npmjs.com/package/oazapfts
|
||||
*/
|
||||
@@ -316,27 +316,6 @@ export type AuditDeletesResponseDto = {
|
||||
ids: string[];
|
||||
needsFullSync: boolean;
|
||||
};
|
||||
export type FileReportItemDto = {
|
||||
checksum?: string;
|
||||
entityId: string;
|
||||
entityType: PathEntityType;
|
||||
pathType: PathType;
|
||||
pathValue: string;
|
||||
};
|
||||
export type FileReportDto = {
|
||||
extras: string[];
|
||||
orphans: FileReportItemDto[];
|
||||
};
|
||||
export type FileChecksumDto = {
|
||||
filenames: string[];
|
||||
};
|
||||
export type FileChecksumResponseDto = {
|
||||
checksum: string;
|
||||
filename: string;
|
||||
};
|
||||
export type FileReportFixDto = {
|
||||
items: FileReportItemDto[];
|
||||
};
|
||||
export type SignUpDto = {
|
||||
email: string;
|
||||
name: string;
|
||||
@@ -599,6 +578,27 @@ export type AssetFaceUpdateDto = {
|
||||
export type PersonStatisticsResponseDto = {
|
||||
assets: number;
|
||||
};
|
||||
export type FileReportItemDto = {
|
||||
checksum?: string;
|
||||
entityId: string;
|
||||
entityType: PathEntityType;
|
||||
pathType: PathType;
|
||||
pathValue: string;
|
||||
};
|
||||
export type FileReportDto = {
|
||||
extras: string[];
|
||||
orphans: FileReportItemDto[];
|
||||
};
|
||||
export type FileChecksumDto = {
|
||||
filenames: string[];
|
||||
};
|
||||
export type FileChecksumResponseDto = {
|
||||
checksum: string;
|
||||
filename: string;
|
||||
};
|
||||
export type FileReportFixDto = {
|
||||
items: FileReportItemDto[];
|
||||
};
|
||||
export type SearchFacetCountResponseDto = {
|
||||
count: number;
|
||||
value: string;
|
||||
@@ -998,6 +998,13 @@ export type SystemConfigTemplateStorageOptionDto = {
|
||||
weekOptions: string[];
|
||||
yearOptions: string[];
|
||||
};
|
||||
export type AdminOnboardingUpdateDto = {
|
||||
isOnboarded: boolean;
|
||||
};
|
||||
export type ReverseGeocodingStateResponseDto = {
|
||||
lastImportFileName: string | null;
|
||||
lastUpdate: string | null;
|
||||
};
|
||||
export type CreateTagDto = {
|
||||
name: string;
|
||||
"type": TagTypeEnum;
|
||||
@@ -1651,35 +1658,6 @@ export function getAuditDeletes({ after, entityType, userId }: {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export function getAuditFiles(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: FileReportDto;
|
||||
}>("/audit/file-report", {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export function getFileChecksums({ fileChecksumDto }: {
|
||||
fileChecksumDto: FileChecksumDto;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 201;
|
||||
data: FileChecksumResponseDto[];
|
||||
}>("/audit/file-report/checksum", oazapfts.json({
|
||||
...opts,
|
||||
method: "POST",
|
||||
body: fileChecksumDto
|
||||
})));
|
||||
}
|
||||
export function fixAuditFiles({ fileReportFixDto }: {
|
||||
fileReportFixDto: FileReportFixDto;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchText("/audit/file-report/fix", oazapfts.json({
|
||||
...opts,
|
||||
method: "POST",
|
||||
body: fileReportFixDto
|
||||
})));
|
||||
}
|
||||
export function signUpAdmin({ signUpDto }: {
|
||||
signUpDto: SignUpDto;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
@@ -2206,6 +2184,35 @@ export function getPersonThumbnail({ id }: {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export function getAuditFiles(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: FileReportDto;
|
||||
}>("/report", {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export function getFileChecksums({ fileChecksumDto }: {
|
||||
fileChecksumDto: FileChecksumDto;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 201;
|
||||
data: FileChecksumResponseDto[];
|
||||
}>("/report/checksum", oazapfts.json({
|
||||
...opts,
|
||||
method: "POST",
|
||||
body: fileChecksumDto
|
||||
})));
|
||||
}
|
||||
export function fixAuditFiles({ fileReportFixDto }: {
|
||||
fileReportFixDto: FileReportFixDto;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchText("/report/fix", oazapfts.json({
|
||||
...opts,
|
||||
method: "POST",
|
||||
body: fileReportFixDto
|
||||
})));
|
||||
}
|
||||
export function search({ clip, motion, page, q, query, recent, size, smart, $type, withArchived }: {
|
||||
clip?: boolean;
|
||||
motion?: boolean;
|
||||
@@ -2330,12 +2337,6 @@ export function getServerInfo(opts?: Oazapfts.RequestOpts) {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export function setAdminOnboarding(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchText("/server-info/admin-onboarding", {
|
||||
...opts,
|
||||
method: "POST"
|
||||
}));
|
||||
}
|
||||
export function getServerConfig(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
@@ -2597,6 +2598,31 @@ export function getStorageTemplateOptions(opts?: Oazapfts.RequestOpts) {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export function getAdminOnboarding(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: AdminOnboardingUpdateDto;
|
||||
}>("/system-metadata/admin-onboarding", {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export function updateAdminOnboarding({ adminOnboardingUpdateDto }: {
|
||||
adminOnboardingUpdateDto: AdminOnboardingUpdateDto;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchText("/system-metadata/admin-onboarding", oazapfts.json({
|
||||
...opts,
|
||||
method: "POST",
|
||||
body: adminOnboardingUpdateDto
|
||||
})));
|
||||
}
|
||||
export function getReverseGeocodingState(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: ReverseGeocodingStateResponseDto;
|
||||
}>("/system-metadata/reverse-geocoding-state", {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export function getAllTags(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
@@ -2948,20 +2974,6 @@ export enum EntityType {
|
||||
Asset = "ASSET",
|
||||
Album = "ALBUM"
|
||||
}
|
||||
export enum PathEntityType {
|
||||
Asset = "asset",
|
||||
Person = "person",
|
||||
User = "user"
|
||||
}
|
||||
export enum PathType {
|
||||
Original = "original",
|
||||
Preview = "preview",
|
||||
Thumbnail = "thumbnail",
|
||||
EncodedVideo = "encoded_video",
|
||||
Sidecar = "sidecar",
|
||||
Face = "face",
|
||||
Profile = "profile"
|
||||
}
|
||||
export enum JobName {
|
||||
ThumbnailGeneration = "thumbnailGeneration",
|
||||
MetadataExtraction = "metadataExtraction",
|
||||
@@ -2993,6 +3005,20 @@ export enum Type2 {
|
||||
export enum MemoryType {
|
||||
OnThisDay = "on_this_day"
|
||||
}
|
||||
export enum PathEntityType {
|
||||
Asset = "asset",
|
||||
Person = "person",
|
||||
User = "user"
|
||||
}
|
||||
export enum PathType {
|
||||
Original = "original",
|
||||
Preview = "preview",
|
||||
Thumbnail = "thumbnail",
|
||||
EncodedVideo = "encoded_video",
|
||||
Sidecar = "sidecar",
|
||||
Face = "face",
|
||||
Profile = "profile"
|
||||
}
|
||||
export enum SearchSuggestionType {
|
||||
Country = "country",
|
||||
State = "state",
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
"matchFileNames": ["mobile/**"],
|
||||
"groupName": "mobile",
|
||||
"matchUpdateTypes": ["minor", "patch"],
|
||||
"schedule": "on tuesday"
|
||||
"schedule": "on tuesday",
|
||||
"addLabels": ["📱mobile"]
|
||||
},
|
||||
{
|
||||
"groupName": "exiftool",
|
||||
|
||||
4
server/package-lock.json
generated
4
server/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "immich",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "immich",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
"@nestjs/bullmq": "^10.0.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
import { Body, Controller, Get, Post, Query } from '@nestjs/common';
|
||||
import { Controller, Get, Query } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import {
|
||||
AuditDeletesDto,
|
||||
AuditDeletesResponseDto,
|
||||
FileChecksumDto,
|
||||
FileChecksumResponseDto,
|
||||
FileReportDto,
|
||||
FileReportFixDto,
|
||||
} from 'src/dtos/audit.dto';
|
||||
import { AuditDeletesDto, AuditDeletesResponseDto } from 'src/dtos/audit.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { AdminRoute, Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||
import { AuditService } from 'src/services/audit.service';
|
||||
|
||||
@ApiTags('Audit')
|
||||
@@ -22,22 +15,4 @@ export class AuditController {
|
||||
getAuditDeletes(@Auth() auth: AuthDto, @Query() dto: AuditDeletesDto): Promise<AuditDeletesResponseDto> {
|
||||
return this.service.getDeletes(auth, dto);
|
||||
}
|
||||
|
||||
@AdminRoute()
|
||||
@Get('file-report')
|
||||
getAuditFiles(): Promise<FileReportDto> {
|
||||
return this.service.getFileReport();
|
||||
}
|
||||
|
||||
@AdminRoute()
|
||||
@Post('file-report/checksum')
|
||||
getFileChecksums(@Body() dto: FileChecksumDto): Promise<FileChecksumResponseDto[]> {
|
||||
return this.service.getChecksums(dto);
|
||||
}
|
||||
|
||||
@AdminRoute()
|
||||
@Post('file-report/fix')
|
||||
fixAuditFiles(@Body() dto: FileReportFixDto): Promise<void> {
|
||||
return this.service.fixItems(dto.items);
|
||||
}
|
||||
}
|
||||
|
||||
30
server/src/controllers/file-report.controller.ts
Normal file
30
server/src/controllers/file-report.controller.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { Body, Controller, Get, Post } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { FileChecksumDto, FileChecksumResponseDto, FileReportDto, FileReportFixDto } from 'src/dtos/audit.dto';
|
||||
import { AdminRoute, Authenticated } from 'src/middleware/auth.guard';
|
||||
import { AuditService } from 'src/services/audit.service';
|
||||
|
||||
@ApiTags('File Report')
|
||||
@Controller('report')
|
||||
@Authenticated()
|
||||
export class ReportController {
|
||||
constructor(private service: AuditService) {}
|
||||
|
||||
@AdminRoute()
|
||||
@Get()
|
||||
getAuditFiles(): Promise<FileReportDto> {
|
||||
return this.service.getFileReport();
|
||||
}
|
||||
|
||||
@AdminRoute()
|
||||
@Post('/checksum')
|
||||
getFileChecksums(@Body() dto: FileChecksumDto): Promise<FileChecksumResponseDto[]> {
|
||||
return this.service.getChecksums(dto);
|
||||
}
|
||||
|
||||
@AdminRoute()
|
||||
@Post('/fix')
|
||||
fixAuditFiles(@Body() dto: FileReportFixDto): Promise<void> {
|
||||
return this.service.fixItems(dto.items);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import { AuditController } from 'src/controllers/audit.controller';
|
||||
import { AuthController } from 'src/controllers/auth.controller';
|
||||
import { DownloadController } from 'src/controllers/download.controller';
|
||||
import { FaceController } from 'src/controllers/face.controller';
|
||||
import { ReportController } from 'src/controllers/file-report.controller';
|
||||
import { JobController } from 'src/controllers/job.controller';
|
||||
import { LibraryController } from 'src/controllers/library.controller';
|
||||
import { MemoryController } from 'src/controllers/memory.controller';
|
||||
@@ -20,19 +21,20 @@ import { SessionController } from 'src/controllers/session.controller';
|
||||
import { SharedLinkController } from 'src/controllers/shared-link.controller';
|
||||
import { SyncController } from 'src/controllers/sync.controller';
|
||||
import { SystemConfigController } from 'src/controllers/system-config.controller';
|
||||
import { SystemMetadataController } from 'src/controllers/system-metadata.controller';
|
||||
import { TagController } from 'src/controllers/tag.controller';
|
||||
import { TimelineController } from 'src/controllers/timeline.controller';
|
||||
import { TrashController } from 'src/controllers/trash.controller';
|
||||
import { UserController } from 'src/controllers/user.controller';
|
||||
|
||||
export const controllers = [
|
||||
ActivityController,
|
||||
AssetsController,
|
||||
AssetControllerV1,
|
||||
AssetController,
|
||||
AppController,
|
||||
AlbumController,
|
||||
APIKeyController,
|
||||
ActivityController,
|
||||
AlbumController,
|
||||
AppController,
|
||||
AssetController,
|
||||
AssetControllerV1,
|
||||
AssetsController,
|
||||
AuditController,
|
||||
AuthController,
|
||||
DownloadController,
|
||||
@@ -42,15 +44,17 @@ export const controllers = [
|
||||
MemoryController,
|
||||
OAuthController,
|
||||
PartnerController,
|
||||
PersonController,
|
||||
ReportController,
|
||||
SearchController,
|
||||
ServerInfoController,
|
||||
SessionController,
|
||||
SharedLinkController,
|
||||
SyncController,
|
||||
SystemConfigController,
|
||||
SystemMetadataController,
|
||||
TagController,
|
||||
TimelineController,
|
||||
TrashController,
|
||||
UserController,
|
||||
PersonController,
|
||||
];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Controller, Get, HttpCode, HttpStatus, Post } from '@nestjs/common';
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import {
|
||||
ServerConfigDto,
|
||||
@@ -65,11 +65,4 @@ export class ServerInfoController {
|
||||
getSupportedMediaTypes(): ServerMediaTypesResponseDto {
|
||||
return this.service.getSupportedMediaTypes();
|
||||
}
|
||||
|
||||
@AdminRoute()
|
||||
@Post('admin-onboarding')
|
||||
@HttpCode(HttpStatus.NO_CONTENT)
|
||||
setAdminOnboarding(): Promise<void> {
|
||||
return this.service.setAdminOnboarding();
|
||||
}
|
||||
}
|
||||
|
||||
28
server/src/controllers/system-metadata.controller.ts
Normal file
28
server/src/controllers/system-metadata.controller.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Body, Controller, Get, HttpCode, HttpStatus, Post } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { AdminOnboardingUpdateDto, ReverseGeocodingStateResponseDto } from 'src/dtos/system-metadata.dto';
|
||||
import { Authenticated } from 'src/middleware/auth.guard';
|
||||
import { SystemMetadataService } from 'src/services/system-metadata.service';
|
||||
|
||||
@ApiTags('System Metadata')
|
||||
@Controller('system-metadata')
|
||||
@Authenticated({ admin: true })
|
||||
export class SystemMetadataController {
|
||||
constructor(private service: SystemMetadataService) {}
|
||||
|
||||
@Get('admin-onboarding')
|
||||
getAdminOnboarding(): Promise<AdminOnboardingUpdateDto> {
|
||||
return this.service.getAdminOnboarding();
|
||||
}
|
||||
|
||||
@Post('admin-onboarding')
|
||||
@HttpCode(HttpStatus.NO_CONTENT)
|
||||
updateAdminOnboarding(@Body() dto: AdminOnboardingUpdateDto): Promise<void> {
|
||||
return this.service.updateAdminOnboarding(dto);
|
||||
}
|
||||
|
||||
@Get('reverse-geocoding-state')
|
||||
getReverseGeocodingState(): Promise<ReverseGeocodingStateResponseDto> {
|
||||
return this.service.getReverseGeocodingState();
|
||||
}
|
||||
}
|
||||
15
server/src/dtos/system-metadata.dto.ts
Normal file
15
server/src/dtos/system-metadata.dto.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { IsBoolean } from 'class-validator';
|
||||
|
||||
export class AdminOnboardingUpdateDto {
|
||||
@IsBoolean()
|
||||
isOnboarded!: boolean;
|
||||
}
|
||||
|
||||
export class AdminOnboardingResponseDto {
|
||||
isOnboarded!: boolean;
|
||||
}
|
||||
|
||||
export class ReverseGeocodingStateResponseDto {
|
||||
lastUpdate!: string | null;
|
||||
lastImportFileName!: string | null;
|
||||
}
|
||||
@@ -2,10 +2,12 @@ import { SessionEntity } from 'src/entities/session.entity';
|
||||
|
||||
export const ISessionRepository = 'ISessionRepository';
|
||||
|
||||
type E = SessionEntity;
|
||||
|
||||
export interface ISessionRepository {
|
||||
create(dto: Partial<SessionEntity>): Promise<SessionEntity>;
|
||||
update(dto: Partial<SessionEntity>): Promise<SessionEntity>;
|
||||
create<T extends Partial<E>>(dto: T): Promise<T>;
|
||||
update<T extends Partial<E>>(dto: T): Promise<T>;
|
||||
delete(id: string): Promise<void>;
|
||||
getByToken(token: string): Promise<SessionEntity | null>;
|
||||
getByUserId(userId: string): Promise<SessionEntity[]>;
|
||||
getByToken(token: string): Promise<E | null>;
|
||||
getByUserId(userId: string): Promise<E[]>;
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ export class MetadataRepository implements IMetadataRepository {
|
||||
this.logger.log('Initializing metadata repository');
|
||||
const geodataDate = await readFile(geodataDatePath, 'utf8');
|
||||
|
||||
// TODO move to metadata service init
|
||||
const geocodingMetadata = await this.systemMetadataRepository.get(SystemMetadataKey.REVERSE_GEOCODING_STATE);
|
||||
|
||||
if (geocodingMetadata?.lastUpdate === geodataDate) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -31,12 +31,12 @@ export class SessionRepository implements ISessionRepository {
|
||||
});
|
||||
}
|
||||
|
||||
create(session: Partial<SessionEntity>): Promise<SessionEntity> {
|
||||
return this.repository.save(session);
|
||||
create<T extends Partial<SessionEntity>>(dto: T): Promise<T & { id: string }> {
|
||||
return this.repository.save(dto);
|
||||
}
|
||||
|
||||
update(session: Partial<SessionEntity>): Promise<SessionEntity> {
|
||||
return this.repository.save(session);
|
||||
update<T extends Partial<SessionEntity>>(dto: T): Promise<T> {
|
||||
return this.repository.save(dto);
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID] })
|
||||
|
||||
@@ -340,10 +340,7 @@ describe('AuthService', () => {
|
||||
sessionMock.getByToken.mockResolvedValue(sessionStub.inactive);
|
||||
sessionMock.update.mockResolvedValue(sessionStub.valid);
|
||||
const headers: IncomingHttpHeaders = { cookie: 'immich_access_token=auth_token' };
|
||||
await expect(sut.validate(headers, {})).resolves.toEqual({
|
||||
user: userStub.user1,
|
||||
session: sessionStub.valid,
|
||||
});
|
||||
await expect(sut.validate(headers, {})).resolves.toBeDefined();
|
||||
expect(sessionMock.update.mock.calls[0][0]).toMatchObject({ id: 'not_active', updatedAt: expect.any(Date) });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -374,14 +374,14 @@ export class AuthService {
|
||||
|
||||
private async validateSession(tokenValue: string): Promise<AuthDto> {
|
||||
const hashedToken = this.cryptoRepository.hashSha256(tokenValue);
|
||||
let session = await this.sessionRepository.getByToken(hashedToken);
|
||||
const session = await this.sessionRepository.getByToken(hashedToken);
|
||||
|
||||
if (session?.user) {
|
||||
const now = DateTime.now();
|
||||
const updatedAt = DateTime.fromJSDate(session.updatedAt);
|
||||
const diff = now.diff(updatedAt, ['hours']);
|
||||
if (diff.hours > 1) {
|
||||
session = await this.sessionRepository.update({ id: session.id, updatedAt: new Date() });
|
||||
await this.sessionRepository.update({ id: session.id, updatedAt: new Date() });
|
||||
}
|
||||
|
||||
return { user: session.user, session: session };
|
||||
|
||||
@@ -25,6 +25,7 @@ import { StorageTemplateService } from 'src/services/storage-template.service';
|
||||
import { StorageService } from 'src/services/storage.service';
|
||||
import { SyncService } from 'src/services/sync.service';
|
||||
import { SystemConfigService } from 'src/services/system-config.service';
|
||||
import { SystemMetadataService } from 'src/services/system-metadata.service';
|
||||
import { TagService } from 'src/services/tag.service';
|
||||
import { TimelineService } from 'src/services/timeline.service';
|
||||
import { TrashService } from 'src/services/trash.service';
|
||||
@@ -58,6 +59,7 @@ export const services = [
|
||||
StorageTemplateService,
|
||||
SyncService,
|
||||
SystemConfigService,
|
||||
SystemMetadataService,
|
||||
TagService,
|
||||
TimelineService,
|
||||
TrashService,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { serverVersion } from 'src/constants';
|
||||
import { SystemMetadataKey } from 'src/entities/system-metadata.entity';
|
||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||
import { ILoggerRepository } from 'src/interfaces/logger.interface';
|
||||
import { IServerInfoRepository } from 'src/interfaces/server-info.interface';
|
||||
@@ -207,13 +206,6 @@ describe(ServerInfoService.name, () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('setAdminOnboarding', () => {
|
||||
it('should set admin onboarding to true', async () => {
|
||||
await sut.setAdminOnboarding();
|
||||
expect(systemMetadataMock.set).toHaveBeenCalledWith(SystemMetadataKey.ADMIN_ONBOARDING, { isOnboarded: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe('getStats', () => {
|
||||
it('should total up usage by user', async () => {
|
||||
userMock.getUserStats.mockResolvedValue([
|
||||
|
||||
@@ -51,7 +51,9 @@ export class ServerInfoService {
|
||||
|
||||
const featureFlags = await this.getFeatures();
|
||||
if (featureFlags.configFile) {
|
||||
await this.setAdminOnboarding();
|
||||
await this.systemMetadataRepository.set(SystemMetadataKey.ADMIN_ONBOARDING, {
|
||||
isOnboarded: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,10 +107,6 @@ export class ServerInfoService {
|
||||
};
|
||||
}
|
||||
|
||||
setAdminOnboarding(): Promise<void> {
|
||||
return this.systemMetadataRepository.set(SystemMetadataKey.ADMIN_ONBOARDING, { isOnboarded: true });
|
||||
}
|
||||
|
||||
async getStatistics(): Promise<ServerStatsResponseDto> {
|
||||
const userStats: UserStatsQueryResponse[] = await this.userRepository.getUserStats();
|
||||
const serverStats = new ServerStatsResponseDto();
|
||||
|
||||
31
server/src/services/system-metadata.service.spec.ts
Normal file
31
server/src/services/system-metadata.service.spec.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { SystemMetadataKey } from 'src/entities/system-metadata.entity';
|
||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||
import { SystemMetadataService } from 'src/services/system-metadata.service';
|
||||
import { newSystemMetadataRepositoryMock } from 'test/repositories/system-metadata.repository.mock';
|
||||
import { Mocked } from 'vitest';
|
||||
|
||||
describe(SystemMetadataService.name, () => {
|
||||
let sut: SystemMetadataService;
|
||||
let metadataMock: Mocked<ISystemMetadataRepository>;
|
||||
|
||||
beforeEach(() => {
|
||||
metadataMock = newSystemMetadataRepositoryMock();
|
||||
sut = new SystemMetadataService(metadataMock);
|
||||
});
|
||||
|
||||
it('should work', () => {
|
||||
expect(sut).toBeDefined();
|
||||
});
|
||||
|
||||
describe('updateAdminOnboarding', () => {
|
||||
it('should update isOnboarded to true', async () => {
|
||||
await expect(sut.updateAdminOnboarding({ isOnboarded: true })).resolves.toBeUndefined();
|
||||
expect(metadataMock.set).toHaveBeenCalledWith(SystemMetadataKey.ADMIN_ONBOARDING, { isOnboarded: true });
|
||||
});
|
||||
|
||||
it('should update isOnboarded to false', async () => {
|
||||
await expect(sut.updateAdminOnboarding({ isOnboarded: false })).resolves.toBeUndefined();
|
||||
expect(metadataMock.set).toHaveBeenCalledWith(SystemMetadataKey.ADMIN_ONBOARDING, { isOnboarded: false });
|
||||
});
|
||||
});
|
||||
});
|
||||
29
server/src/services/system-metadata.service.ts
Normal file
29
server/src/services/system-metadata.service.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import {
|
||||
AdminOnboardingResponseDto,
|
||||
AdminOnboardingUpdateDto,
|
||||
ReverseGeocodingStateResponseDto,
|
||||
} from 'src/dtos/system-metadata.dto';
|
||||
import { SystemMetadataKey } from 'src/entities/system-metadata.entity';
|
||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||
|
||||
@Injectable()
|
||||
export class SystemMetadataService {
|
||||
constructor(@Inject(ISystemMetadataRepository) private repository: ISystemMetadataRepository) {}
|
||||
|
||||
async getAdminOnboarding(): Promise<AdminOnboardingResponseDto> {
|
||||
const value = await this.repository.get(SystemMetadataKey.ADMIN_ONBOARDING);
|
||||
return { isOnboarded: false, ...value };
|
||||
}
|
||||
|
||||
async updateAdminOnboarding(dto: AdminOnboardingUpdateDto): Promise<void> {
|
||||
await this.repository.set(SystemMetadataKey.ADMIN_ONBOARDING, {
|
||||
isOnboarded: dto.isOnboarded,
|
||||
});
|
||||
}
|
||||
|
||||
async getReverseGeocodingState(): Promise<ReverseGeocodingStateResponseDto> {
|
||||
const value = await this.repository.get(SystemMetadataKey.REVERSE_GEOCODING_STATE);
|
||||
return { lastUpdate: null, lastImportFileName: null, ...value };
|
||||
}
|
||||
}
|
||||
@@ -436,7 +436,7 @@ export class AV1Config extends BaseConfig {
|
||||
|
||||
export class NVENCConfig extends BaseHWConfig {
|
||||
getSupportedCodecs() {
|
||||
return [VideoCodec.H264, VideoCodec.HEVC];
|
||||
return [VideoCodec.H264, VideoCodec.HEVC, VideoCodec.AV1];
|
||||
}
|
||||
|
||||
getBaseInputOptions() {
|
||||
@@ -566,7 +566,7 @@ export class QSVConfig extends BaseHWConfig {
|
||||
}
|
||||
|
||||
getSupportedCodecs() {
|
||||
return [VideoCodec.H264, VideoCodec.HEVC, VideoCodec.VP9];
|
||||
return [VideoCodec.H264, VideoCodec.HEVC, VideoCodec.VP9, VideoCodec.AV1];
|
||||
}
|
||||
|
||||
// recommended from https://github.com/intel/media-delivery/blob/master/doc/benchmarks/intel-iris-xe-max-graphics/intel-iris-xe-max-graphics.md
|
||||
|
||||
@@ -3,8 +3,8 @@ import { Mocked, vitest } from 'vitest';
|
||||
|
||||
export const newSessionRepositoryMock = (): Mocked<ISessionRepository> => {
|
||||
return {
|
||||
create: vitest.fn(),
|
||||
update: vitest.fn(),
|
||||
create: vitest.fn() as any,
|
||||
update: vitest.fn() as any,
|
||||
delete: vitest.fn(),
|
||||
getByToken: vitest.fn(),
|
||||
getByUserId: vitest.fn(),
|
||||
|
||||
24
web/package-lock.json
generated
24
web/package-lock.json
generated
@@ -1,17 +1,19 @@
|
||||
{
|
||||
"name": "immich-web",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "immich-web",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
||||
"@mdi/js": "^7.4.47",
|
||||
"@photo-sphere-viewer/core": "^5.7.1",
|
||||
"@photo-sphere-viewer/equirectangular-video-adapter": "^5.7.2",
|
||||
"@photo-sphere-viewer/video-plugin": "^5.7.2",
|
||||
"@zoom-image/svelte": "^0.2.6",
|
||||
"buffer": "^6.0.3",
|
||||
"copy-image-clipboard": "^2.1.2",
|
||||
@@ -63,7 +65,7 @@
|
||||
},
|
||||
"../open-api/typescript-sdk": {
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
"@oazapfts/runtime": "^1.0.2"
|
||||
@@ -1590,6 +1592,22 @@
|
||||
"three": "^0.161.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@photo-sphere-viewer/equirectangular-video-adapter": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@photo-sphere-viewer/equirectangular-video-adapter/-/equirectangular-video-adapter-5.7.2.tgz",
|
||||
"integrity": "sha512-cAaot52nPqa2p77Xp1humRvuxRIa8cqbZ/XRhA8kBToFLT1Ugh9YBcDD7pM/358JtAjicUbLpT7Ioap9iEigxQ==",
|
||||
"peerDependencies": {
|
||||
"@photo-sphere-viewer/core": "5.7.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@photo-sphere-viewer/video-plugin": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@photo-sphere-viewer/video-plugin/-/video-plugin-5.7.2.tgz",
|
||||
"integrity": "sha512-vrPV9RCr4HsYiORkto1unDPeUkbN2kbyogvNUoLiQ78M4xkPOqoKxtfxCxTYoM+7gECwNL9VTF81+okck498qA==",
|
||||
"peerDependencies": {
|
||||
"@photo-sphere-viewer/core": "5.7.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@polka/url": {
|
||||
"version": "1.0.0-next.24",
|
||||
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.24.tgz",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich-web",
|
||||
"version": "1.102.0",
|
||||
"version": "1.102.3",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"scripts": {
|
||||
"dev": "vite dev --host 0.0.0.0 --port 3000",
|
||||
@@ -61,6 +61,8 @@
|
||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
||||
"@mdi/js": "^7.4.47",
|
||||
"@photo-sphere-viewer/core": "^5.7.1",
|
||||
"@photo-sphere-viewer/equirectangular-video-adapter": "^5.7.2",
|
||||
"@photo-sphere-viewer/video-plugin": "^5.7.2",
|
||||
"@zoom-image/svelte": "^0.2.6",
|
||||
"buffer": "^6.0.3",
|
||||
"copy-image-clipboard": "^2.1.2",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
mdiFolderDownloadOutline,
|
||||
mdiHeart,
|
||||
mdiHeartOutline,
|
||||
mdiHistory,
|
||||
mdiImageAlbum,
|
||||
mdiImageMinusOutline,
|
||||
mdiImageOutline,
|
||||
@@ -52,6 +53,7 @@
|
||||
|
||||
type MenuItemEvent =
|
||||
| 'addToAlbum'
|
||||
| 'restoreAsset'
|
||||
| 'addToSharedAlbum'
|
||||
| 'asProfileImage'
|
||||
| 'setAsAlbumCover'
|
||||
@@ -70,6 +72,7 @@
|
||||
delete: void;
|
||||
toggleArchive: void;
|
||||
addToAlbum: void;
|
||||
restoreAsset: void;
|
||||
addToSharedAlbum: void;
|
||||
asProfileImage: void;
|
||||
setAsAlbumCover: void;
|
||||
@@ -208,12 +211,16 @@
|
||||
{#if showDownloadButton}
|
||||
<MenuOption icon={mdiFolderDownloadOutline} on:click={() => onMenuClick('download')} text="Download" />
|
||||
{/if}
|
||||
<MenuOption icon={mdiImageAlbum} on:click={() => onMenuClick('addToAlbum')} text="Add to album" />
|
||||
<MenuOption
|
||||
icon={mdiShareVariantOutline}
|
||||
on:click={() => onMenuClick('addToSharedAlbum')}
|
||||
text="Add to shared album"
|
||||
/>
|
||||
{#if asset.isTrashed}
|
||||
<MenuOption icon={mdiHistory} on:click={() => onMenuClick('restoreAsset')} text="Restore" />
|
||||
{:else}
|
||||
<MenuOption icon={mdiImageAlbum} on:click={() => onMenuClick('addToAlbum')} text="Add to album" />
|
||||
<MenuOption
|
||||
icon={mdiShareVariantOutline}
|
||||
on:click={() => onMenuClick('addToSharedAlbum')}
|
||||
text="Add to shared album"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if isOwner}
|
||||
{#if hasStackChildren}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
getActivityStatistics,
|
||||
getAllAlbums,
|
||||
runAssetJobs,
|
||||
restoreAssets,
|
||||
updateAsset,
|
||||
updateAlbumInfo,
|
||||
type ActivityResponseDto,
|
||||
@@ -49,7 +50,7 @@
|
||||
import PanoramaViewer from './panorama-viewer.svelte';
|
||||
import PhotoViewer from './photo-viewer.svelte';
|
||||
import SlideshowBar from './slideshow-bar.svelte';
|
||||
import VideoViewer from './video-viewer.svelte';
|
||||
import VideoViewer from './video-wrapper-viewer.svelte';
|
||||
|
||||
export let assetStore: AssetStore | null = null;
|
||||
export let asset: AssetResponseDto;
|
||||
@@ -403,6 +404,22 @@
|
||||
await handleGetAllAlbums();
|
||||
};
|
||||
|
||||
const handleRestoreAsset = async () => {
|
||||
try {
|
||||
await restoreAssets({ bulkIdsDto: { ids: [asset.id] } });
|
||||
asset.isTrashed = false;
|
||||
|
||||
dispatch('action', { type: AssetAction.RESTORE, asset });
|
||||
|
||||
notificationController.show({
|
||||
type: NotificationType.Info,
|
||||
message: `Restored asset`,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, 'Error restoring asset');
|
||||
}
|
||||
};
|
||||
|
||||
const toggleArchive = async () => {
|
||||
try {
|
||||
const data = await updateAsset({
|
||||
@@ -556,6 +573,7 @@
|
||||
on:delete={() => trashOrDelete()}
|
||||
on:favorite={toggleFavorite}
|
||||
on:addToAlbum={() => openAlbumPicker(false)}
|
||||
on:restoreAsset={() => handleRestoreAsset()}
|
||||
on:addToSharedAlbum={() => openAlbumPicker(true)}
|
||||
on:playMotionPhoto={() => (shouldPlayMotionPhoto = true)}
|
||||
on:stopMotionPhoto={() => (shouldPlayMotionPhoto = false)}
|
||||
@@ -604,6 +622,7 @@
|
||||
{:else}
|
||||
<VideoViewer
|
||||
assetId={previewStackedAsset.id}
|
||||
projectionType={previewStackedAsset.exifInfo?.projectionType}
|
||||
on:close={closeViewer}
|
||||
on:onVideoEnded={() => navigateAsset()}
|
||||
on:onVideoStarted={handleVideoStarted}
|
||||
@@ -624,6 +643,7 @@
|
||||
{#if shouldPlayMotionPhoto && asset.livePhotoVideoId}
|
||||
<VideoViewer
|
||||
assetId={asset.livePhotoVideoId}
|
||||
projectionType={asset.exifInfo?.projectionType}
|
||||
on:close={closeViewer}
|
||||
on:onVideoEnded={() => (shouldPlayMotionPhoto = false)}
|
||||
/>
|
||||
@@ -637,6 +657,7 @@
|
||||
{:else}
|
||||
<VideoViewer
|
||||
assetId={asset.id}
|
||||
projectionType={asset.exifInfo?.projectionType}
|
||||
on:close={closeViewer}
|
||||
on:onVideoEnded={() => navigateAsset()}
|
||||
on:onVideoStarted={handleVideoStarted}
|
||||
|
||||
@@ -1,22 +1,39 @@
|
||||
<script lang="ts">
|
||||
import { serveFile, type AssetResponseDto } from '@immich/sdk';
|
||||
import { serveFile, type AssetResponseDto, AssetTypeEnum } from '@immich/sdk';
|
||||
import { fade } from 'svelte/transition';
|
||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||
import { getKey } from '$lib/utils';
|
||||
export let asset: AssetResponseDto;
|
||||
import type { AdapterConstructor, PluginConstructor } from '@photo-sphere-viewer/core';
|
||||
export let asset: Pick<AssetResponseDto, 'id' | 'type'>;
|
||||
|
||||
const photoSphereConfigs =
|
||||
asset.type === AssetTypeEnum.Video
|
||||
? ([
|
||||
import('@photo-sphere-viewer/equirectangular-video-adapter').then(
|
||||
({ EquirectangularVideoAdapter }) => EquirectangularVideoAdapter,
|
||||
),
|
||||
import('@photo-sphere-viewer/video-plugin').then(({ VideoPlugin }) => [VideoPlugin]),
|
||||
true,
|
||||
import('@photo-sphere-viewer/video-plugin/index.css'),
|
||||
] as [PromiseLike<AdapterConstructor>, Promise<PluginConstructor[]>, true, unknown])
|
||||
: ([undefined, [], false] as [undefined, [], false]);
|
||||
|
||||
const loadAssetData = async () => {
|
||||
const data = await serveFile({ id: asset.id, isWeb: false, isThumb: false, key: getKey() });
|
||||
return URL.createObjectURL(data);
|
||||
const url = URL.createObjectURL(data);
|
||||
if (asset.type === AssetTypeEnum.Video) {
|
||||
return { source: url };
|
||||
}
|
||||
return url;
|
||||
};
|
||||
</script>
|
||||
|
||||
<div transition:fade={{ duration: 150 }} class="flex h-full select-none place-content-center place-items-center">
|
||||
<!-- the photo sphere viewer is quite large, so lazy load it in parallel with loading the data -->
|
||||
{#await Promise.all([loadAssetData(), import('./photo-sphere-viewer-adapter.svelte')])}
|
||||
{#await Promise.all([loadAssetData(), import('./photo-sphere-viewer-adapter.svelte'), ...photoSphereConfigs])}
|
||||
<LoadingSpinner />
|
||||
{:then [data, module]}
|
||||
<svelte:component this={module.default} panorama={data} />
|
||||
{:then [data, module, adapter, plugins, navbar]}
|
||||
<svelte:component this={module.default} panorama={data} plugins={plugins ?? undefined} {navbar} {adapter} />
|
||||
{:catch}
|
||||
Failed to load asset
|
||||
{/await}
|
||||
|
||||
@@ -1,17 +1,32 @@
|
||||
<script lang="ts">
|
||||
import { Viewer } from '@photo-sphere-viewer/core';
|
||||
import {
|
||||
Viewer,
|
||||
EquirectangularAdapter,
|
||||
type PluginConstructor,
|
||||
type AdapterConstructor,
|
||||
} from '@photo-sphere-viewer/core';
|
||||
import '@photo-sphere-viewer/core/index.css';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
|
||||
export let panorama: string;
|
||||
export let panorama: string | { source: string };
|
||||
export let adapter: AdapterConstructor | [AdapterConstructor, unknown] = EquirectangularAdapter;
|
||||
export let plugins: (PluginConstructor | [PluginConstructor, unknown])[] = [];
|
||||
export let navbar = false;
|
||||
|
||||
let container: HTMLDivElement;
|
||||
let viewer: Viewer;
|
||||
|
||||
onMount(() => {
|
||||
viewer = new Viewer({
|
||||
adapter,
|
||||
plugins,
|
||||
container,
|
||||
panorama,
|
||||
navbar: false,
|
||||
touchmoveTwoFingers: true,
|
||||
mousewheelCtrlKey: false,
|
||||
navbar,
|
||||
maxFov: 180,
|
||||
fisheye: true,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||
import { getAltText } from '$lib/utils/thumbnail-util';
|
||||
import { slideshowLookCssMapping, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
|
||||
import { SlideshowLook, slideshowLookCssMapping, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
|
||||
|
||||
const { slideshowState, slideshowLook } = slideshowStore;
|
||||
|
||||
@@ -150,15 +150,24 @@
|
||||
<div
|
||||
bind:this={element}
|
||||
transition:fade={{ duration: haveFadeTransition ? 150 : 0 }}
|
||||
class="flex h-full select-none place-content-center place-items-center"
|
||||
class="relative h-full select-none"
|
||||
>
|
||||
{#if !imageLoaded}
|
||||
<LoadingSpinner />
|
||||
<div class="flex h-full items-center justify-center">
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
{:else}
|
||||
<div bind:this={imgElement} class="h-full w-full">
|
||||
<div bind:this={imgElement} class="h-full w-full" transition:fade={{ duration: haveFadeTransition ? 150 : 0 }}>
|
||||
{#if $slideshowState !== SlideshowState.None && $slideshowLook === SlideshowLook.BlurredBackground}
|
||||
<img
|
||||
src={assetData}
|
||||
alt={getAltText(asset)}
|
||||
class="absolute top-0 left-0 -z-10 object-cover h-full w-full blur-lg"
|
||||
draggable="false"
|
||||
/>
|
||||
{/if}
|
||||
<img
|
||||
bind:this={$photoViewer}
|
||||
transition:fade={{ duration: haveFadeTransition ? 150 : 0 }}
|
||||
src={assetData}
|
||||
alt={getAltText(asset)}
|
||||
class="h-full w-full {$slideshowState === SlideshowState.None
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { AssetTypeEnum } from '@immich/sdk';
|
||||
import { ProjectionType } from '$lib/constants';
|
||||
import VideoNativeViewer from '$lib/components/asset-viewer/video-native-viewer.svelte';
|
||||
import PanoramaViewer from '$lib/components/asset-viewer/panorama-viewer.svelte';
|
||||
|
||||
export let assetId: string;
|
||||
export let projectionType: string | null | undefined;
|
||||
</script>
|
||||
|
||||
{#if projectionType === ProjectionType.EQUIRECTANGULAR}
|
||||
<PanoramaViewer asset={{ id: assetId, type: AssetTypeEnum.Video }} />
|
||||
{:else}
|
||||
<VideoNativeViewer {assetId} on:onVideoEnded on:onVideoStarted />
|
||||
{/if}
|
||||
@@ -43,7 +43,7 @@
|
||||
'text-immich-primary dark:text-immich-dark-primary enabled:dark:hover:bg-immich-dark-primary/10 enabled:hover:bg-immich-primary/10',
|
||||
'light-red': 'bg-[#F9DEDC] text-[#410E0B] enabled:hover:bg-red-50',
|
||||
red: 'bg-red-500 text-white enabled:hover:bg-red-400',
|
||||
green: 'bg-green-500 text-gray-800 enabled:hover:bg-green-400/90',
|
||||
green: 'bg-green-600 text-white enabled:hover:bg-green-400/90',
|
||||
gray: 'bg-gray-500 dark:bg-gray-200 enabled:hover:bg-gray-500/75 enabled:dark:hover:bg-gray-200/80 text-white dark:text-immich-dark-gray',
|
||||
'transparent-gray':
|
||||
'dark:text-immich-dark-fg enabled:hover:bg-immich-primary/5 enabled:hover:text-gray-700 enabled:hover:dark:text-immich-dark-fg enabled:dark:hover:bg-immich-dark-primary/25',
|
||||
|
||||
@@ -169,6 +169,7 @@
|
||||
switch (action) {
|
||||
case removeAction:
|
||||
case AssetAction.TRASH:
|
||||
case AssetAction.RESTORE:
|
||||
case AssetAction.DELETE: {
|
||||
// find the next asset to show or close the viewer
|
||||
(await handleNext()) || (await handlePrevious()) || handleClose();
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
hoverLabel = new Date(attr).toLocaleString($locale, {
|
||||
month: 'short',
|
||||
year: 'numeric',
|
||||
timeZone: 'UTC',
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
mdiMagnify,
|
||||
mdiMap,
|
||||
mdiTrashCanOutline,
|
||||
mdiTuneVariant,
|
||||
} from '@mdi/js';
|
||||
import LoadingSpinner from '../loading-spinner.svelte';
|
||||
import StatusBox from '../status-box.svelte';
|
||||
@@ -145,6 +146,12 @@
|
||||
</svelte:fragment>
|
||||
</SideBarLink>
|
||||
{/if}
|
||||
|
||||
<div class="text-xs transition-all duration-200 dark:text-immich-dark-fg">
|
||||
<p class="hidden p-6 group-hover:sm:block md:block">AUTOMATION</p>
|
||||
<hr class="mx-4 mb-[31px] mt-8 block group-hover:sm:hidden md:hidden" />
|
||||
</div>
|
||||
<SideBarLink title="Workflows" routeId="/(user)/workflows" icon={mdiTuneVariant} />
|
||||
</nav>
|
||||
|
||||
<!-- Status Box -->
|
||||
|
||||
@@ -4,7 +4,14 @@
|
||||
SettingInputFieldType,
|
||||
} from '$lib/components/shared-components/settings/setting-input-field.svelte';
|
||||
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
|
||||
import { mdiArrowDownThin, mdiArrowUpThin, mdiFitToPageOutline, mdiFitToScreenOutline, mdiShuffle } from '@mdi/js';
|
||||
import {
|
||||
mdiArrowDownThin,
|
||||
mdiArrowUpThin,
|
||||
mdiFitToPageOutline,
|
||||
mdiFitToScreenOutline,
|
||||
mdiPanorama,
|
||||
mdiShuffle,
|
||||
} from '@mdi/js';
|
||||
import { SlideshowLook, SlideshowNavigation, slideshowStore } from '../stores/slideshow.store';
|
||||
import Button from './elements/buttons/button.svelte';
|
||||
import type { RenderedOption } from './elements/dropdown.svelte';
|
||||
@@ -23,6 +30,7 @@
|
||||
const lookOptions: Record<SlideshowLook, RenderedOption> = {
|
||||
[SlideshowLook.Contain]: { icon: mdiFitToScreenOutline, title: 'Contain' },
|
||||
[SlideshowLook.Cover]: { icon: mdiFitToPageOutline, title: 'Cover' },
|
||||
[SlideshowLook.BlurredBackground]: { icon: mdiPanorama, title: 'Blurred background' },
|
||||
};
|
||||
|
||||
const handleToggle = <Type extends SlideshowNavigation | SlideshowLook>(
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<script lang="ts">
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import { mdiPencil, mdiTrashCan } from '@mdi/js';
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="bg-zinc-300 dark:bg-zinc-800 text-black dark:text-white min-h-[60px] grid grid-cols-[15%_70%_15%] place-items-center place-content-center rounded-2xl mx-4 mt-2 p-2"
|
||||
>
|
||||
<p class="col-start-2 col-span-1">Add to album "RANDOM"</p>
|
||||
|
||||
<div class="col-start-3 col-span-1 flex gap-2 justify-self-end">
|
||||
<CircleIconButton size="20" padding="2" title="Remove rule" icon={mdiTrashCan} />
|
||||
<CircleIconButton size="20" padding="2" title="Edit rule" icon={mdiPencil} />
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,15 @@
|
||||
<script lang="ts">
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import { mdiPencil, mdiTrashCan } from '@mdi/js';
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="bg-zinc-200 text-black dark:bg-zinc-700 dark:text-white min-h-[60px] grid grid-cols-[15%_70%_15%] place-items-center place-content-center rounded-2xl mx-4 mt-2 p-2"
|
||||
>
|
||||
<p class="col-start-2 col-span-1">And has Alex and Henry and Nate</p>
|
||||
|
||||
<div class="col-start-3 col-span-1 flex gap-2 justify-self-end">
|
||||
<CircleIconButton size="20" padding="2" title="Remove rule" icon={mdiTrashCan} />
|
||||
<CircleIconButton size="20" padding="2" title="Edit rule" icon={mdiPencil} />
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,5 @@
|
||||
<div
|
||||
class="bg-immich-primary text-white dark:bg-immich-dark-primary dark:text-black min-h-[60px] flex place-items-center place-content-center mx-4 mt-2 rounded-2xl"
|
||||
>
|
||||
When an asset is uploaded
|
||||
</div>
|
||||
10
web/src/lib/components/workflow-page/workflow-card.svelte
Normal file
10
web/src/lib/components/workflow-page/workflow-card.svelte
Normal file
@@ -0,0 +1,10 @@
|
||||
<script lang="ts">
|
||||
// export let onSelect: () => void;
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="rounded-3xl mr-2 my-4 min-h-[60px] grid grid-cols-[32px_1fr] gap-2 place-items-center p-4 place-content-center bg-gray-100 hover:bg-gray-200 dark:bg-gray-900 hover:dark:bg-gray-800"
|
||||
>
|
||||
<div class="w-4 h-4 rounded-full bg-green-400"></div>
|
||||
<p class="dark:text-gray-300">Add this photo to every albums and notify everybody about this glorious asset</p>
|
||||
</div>
|
||||
82
web/src/lib/components/workflow-page/workflow-editor.svelte
Normal file
82
web/src/lib/components/workflow-page/workflow-editor.svelte
Normal file
@@ -0,0 +1,82 @@
|
||||
<script lang="ts">
|
||||
import Button from '$lib/components/elements/buttons/button.svelte';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import WorkflowActionCard from '$lib/components/workflow-page/editor/workflow-action-card.svelte';
|
||||
import WorkflowRuleCard from '$lib/components/workflow-page/editor/workflow-rule-card.svelte';
|
||||
import WorkflowTriggerCard from '$lib/components/workflow-page/editor/workflow-trigger-card.svelte';
|
||||
import { mdiPlus } from '@mdi/js';
|
||||
</script>
|
||||
|
||||
<section class="h-full overflow-scroll">
|
||||
<div
|
||||
id="workflow-control-bar"
|
||||
class="sticky top-0 flex justify-between place-items-center border-b border-gray-200 dark:border-gray-800 p-4 bg-zinc-50 dark:bg-zinc-900 z-20"
|
||||
>
|
||||
<p class="uppercase text-lg dark:text-white font-medium">
|
||||
Add this photo to every albums and notify everybody about this glorious asset
|
||||
</p>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<Button size="sm" color="red">Discard</Button>
|
||||
<Button size="sm">Disable</Button>
|
||||
<Button size="sm" color="green">Save</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="workflows-selection">
|
||||
<!-- TRIGGER BLOCK -->
|
||||
<div class="translate-y-3">
|
||||
<p class="pl-4 text-xs dark:text-gray-300">TRIGGER</p>
|
||||
<WorkflowTriggerCard />
|
||||
</div>
|
||||
|
||||
<!-- VISUAL CONNECTOR -->
|
||||
<div class="relative w-full grid grid-cols-3 place-items-center place-content-center z-10">
|
||||
<p class="col-start-1 col-span-1 justify-self-start self-end pl-4 pb-6 text-xs dark:text-gray-300">RULES</p>
|
||||
<div class="col-start-2 col-span-1 flex flex-col place-items-center">
|
||||
<div
|
||||
class="rounded-full border-[6px] border-immich-primary dark:border-immich-dark-primary h-[20px] w-[20px] bg-white translate-y-1"
|
||||
></div>
|
||||
<div
|
||||
class="h-[60px] w-[5px] bg-white bg-gradient-to-b from-immich-primary dark:from-immich-dark-primary via-zinc-300 dark:via-gray-600 dark:to-zinc-700"
|
||||
></div>
|
||||
<div
|
||||
class="rounded-full border-[6px] border-zinc-200 dark:border-gray-700 h-[20px] w-[20px] bg-white -translate-y-1"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- RULES BLOCK -->
|
||||
<div id="rule-block" class="-translate-y-6">
|
||||
<WorkflowRuleCard />
|
||||
<WorkflowRuleCard />
|
||||
|
||||
<div
|
||||
class="border-2 dark:border-gray-700 dark:text-white min-h-[60px] flex place-items-center place-content-center rounded-2xl mx-4 mt-2"
|
||||
>
|
||||
<span><Icon path={mdiPlus} /></span> ADD RULE
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- VISUAL CONNECTOR -->
|
||||
<div class="relative w-full grid grid-cols-3 place-items-center place-content-center -translate-y-9 z-10">
|
||||
<p class="col-start-1 col-span-1 justify-self-start self-end pl-4 pb-6 text-xs dark:text-gray-300">ACTIONS</p>
|
||||
<div class="col-start-2 col-span-1 flex flex-col place-items-center">
|
||||
<div class="rounded-full border-[6px] border-gray-900 h-[20px] w-[20px] bg-white translate-y-1"></div>
|
||||
<div class="h-[60px] w-[5px] bg-white bg-gradient-to-b from-gray-900 via-indigo-800 to-gray-700"></div>
|
||||
<div class="rounded-full border-[6px] border-gray-700 h-[20px] w-[20px] bg-white -translate-y-1"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ACTION BLOCK -->
|
||||
<div id="action-block" class="-translate-y-14">
|
||||
<WorkflowActionCard />
|
||||
<WorkflowActionCard />
|
||||
<div
|
||||
class="border-2 dark:border-gray-500 dark:text-white min-h-[60px] flex place-items-center place-content-center rounded-2xl mx-4 mt-2"
|
||||
>
|
||||
<span><Icon path={mdiPlus} /></span> ADD ACTION
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
17
web/src/lib/components/workflow-page/workflow-list.svelte
Normal file
17
web/src/lib/components/workflow-page/workflow-list.svelte
Normal file
@@ -0,0 +1,17 @@
|
||||
<script lang="ts">
|
||||
import Button from '$lib/components/elements/buttons/button.svelte';
|
||||
import WorkflowCard from '$lib/components/workflow-page/workflow-card.svelte';
|
||||
</script>
|
||||
|
||||
<section id="workflow-list" class="border-r border-gray-200 dark:border-gray-800 h-full relative overflow-scroll pr-2">
|
||||
<div class="sticky top-0 dark:bg-immich-dark-bg flex justify-between place-items-center pr-2 py-4 bg-immich-bg">
|
||||
<p class="text-xs dark:text-white">CURRENT WORKFLOWS</p>
|
||||
<Button size="sm">New Workflow</Button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{#each Array.from({ length: 50 }) as _}
|
||||
<WorkflowCard />
|
||||
{/each}
|
||||
</div>
|
||||
</section>
|
||||
@@ -5,7 +5,7 @@ export enum AssetAction {
|
||||
UNFAVORITE = 'unfavorite',
|
||||
TRASH = 'trash',
|
||||
DELETE = 'delete',
|
||||
// RESTORE = 'restore',
|
||||
RESTORE = 'restore',
|
||||
ADD = 'add',
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,13 @@ export enum SlideshowNavigation {
|
||||
export enum SlideshowLook {
|
||||
Contain = 'contain',
|
||||
Cover = 'cover',
|
||||
BlurredBackground = 'blurred-background',
|
||||
}
|
||||
|
||||
export const slideshowLookCssMapping: Record<SlideshowLook, string> = {
|
||||
[SlideshowLook.Contain]: 'object-contain',
|
||||
[SlideshowLook.Cover]: 'object-cover',
|
||||
[SlideshowLook.BlurredBackground]: 'object-contain',
|
||||
};
|
||||
|
||||
function createSlideshowStore() {
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
|
||||
const handleSearch = async (force: boolean) => {
|
||||
$page.url.searchParams.set(QueryParameter.SEARCHED_PEOPLE, searchName);
|
||||
await goto($page.url);
|
||||
await goto($page.url, { keepFocus: true });
|
||||
await handleSearchPeople(force);
|
||||
};
|
||||
|
||||
|
||||
@@ -39,8 +39,12 @@
|
||||
try {
|
||||
await emptyTrash();
|
||||
|
||||
const deletedAssetIds = assetStore.assets.map((a) => a.id);
|
||||
const numberOfAssets = deletedAssetIds.length;
|
||||
assetStore.removeAssets(deletedAssetIds);
|
||||
|
||||
notificationController.show({
|
||||
message: `Empty trash initiated. Refresh the page to see the changes`,
|
||||
message: `Permanently deleted ${numberOfAssets} ${numberOfAssets == 1 ? 'asset' : 'assets'}`,
|
||||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -52,8 +56,12 @@
|
||||
try {
|
||||
await restoreTrash();
|
||||
|
||||
const restoredAssetIds = assetStore.assets.map((a) => a.id);
|
||||
const numberOfAssets = restoredAssetIds.length;
|
||||
assetStore.removeAssets(restoredAssetIds);
|
||||
|
||||
notificationController.show({
|
||||
message: `Restore trash initiated. Refresh the page to see the changes`,
|
||||
message: `Restored ${numberOfAssets} ${numberOfAssets == 1 ? 'asset' : 'assets'}`,
|
||||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
15
web/src/routes/(user)/workflows/+page.svelte
Normal file
15
web/src/routes/(user)/workflows/+page.svelte
Normal file
@@ -0,0 +1,15 @@
|
||||
<script lang="ts">
|
||||
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
|
||||
import WorkflowEditor from '$lib/components/workflow-page/workflow-editor.svelte';
|
||||
import WorkflowList from '$lib/components/workflow-page/workflow-list.svelte';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
<UserPageLayout title={data.meta.title} scrollbar={false}>
|
||||
<section class="grid grid-cols-[25%_1fr] h-full">
|
||||
<WorkflowList />
|
||||
<WorkflowEditor />
|
||||
</section>
|
||||
</UserPageLayout>
|
||||
12
web/src/routes/(user)/workflows/+page.ts
Normal file
12
web/src/routes/(user)/workflows/+page.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
await authenticate();
|
||||
|
||||
return {
|
||||
meta: {
|
||||
title: 'Workflows',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user